Control of Electric Vehicle

0 23515 Medium

The vehicle control system has been revamped to incorporate battery status updates and adjustable speed control.

 

Control of Electric Vehicle

Things used in this project

 

Hardware components

HARDWARE LIST
1 DFRobot LED Current Meter 10A (Green)
10 Jumper wires (generic)
1 Breadboard (generic)
1 Particle Argon
8 Pin Terminal, Crimp
1 power wheels car
1 Hall Effect Sensor, Throttle Position
1 Volt Meter, Mini 3-Wire
1 Digilent 60W PCIe 12V 5A Power Supply
1 SparkFun Dual H-Bridge motor drivers L298

Software apps and online services

 

ThingSpeak API

 

Particle Build Web IDE

 

Hand tools and fabrication machines

 

Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires

 

Crimp Tool, Heavy-Duty

 

Multitool, Screwdriver

 

Tape, Electrical

Story

 

According to the courses, "hardware, sensors, programming, performance, motor selection, regenerative braking, etc. A Budget of $300 per student is required. Students will be required to purchase used electric toytype ride on vehicles and electronic components. Students will implement their own control systems utilizing an Argon type device, various sensors and hardware."Currently using a voltmeter and current meter to gather battery load data with vehicle usage. Swapped throttle pedal out for variable sensor for variable motor speeds. Using a L298N motor driver for precise Dual motor control.

 

Attached Below is a picture of our live data acquisition that we are using Thingspeak for. https://thingspeak.com/channels/2060933

 

Live Data the spike at 12:35 is from pulling out the battery

 

Live Data the spike at 12:35 is from pulling out the battery

 

PWM Video working below

Wiring Diagram

Slew Rate Video

Schematics

 

Electrical Schematic

 

Wiring Schematic for the vehicle

 

 

Real Life wiring

 

Electrical Wiring Fritzing

 

Fritzing Wiring Diagram

 


 

Code

 

Code with Voltage/Current sensor and PWM peddle

Arduino

Program reads throttle, voltage, and current and varies motor speed accordingly.

CODE
// This #include statement was automatically added by the Particle IDE.
#include <ThingSpeak.h>

// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT.h>


//Things speak client setup
TCPClient client;
// Define the pins for the analog inputs and servo output
const int VOLTAGE_PIN = A0;
const int CURRENT_PIN = A1;
const int THROTTLE_PIN = A2;

// Define the ratios for the voltage divider and current sensor calibration
const float VOLTAGE_RATIO = 0.046;
const float CURRENT_CALIBRATION = 0.066;

// Define the variables to hold the raw analog readings
int rawVoltage;
int rawCurrent;
int rawThrottle;

int Voltage;
int Current;
int Throttle;

// Motor A connections
const int enA = D7;
const int in1 = D6;
const int in2 = D5;
// Motor B connections
const int in3 = D4;
const int in4 = D3;
const int enB = D2;

// Define the time interval for reading the analog inputs (in microseconds)
const unsigned long READ_INTERVAL = 20000;

// Define the time interval for outputting the filtered values (in milliseconds)
const unsigned long OUTPUT_INTERVAL = 10000;

// Define the filter coefficients for a first-order low-pass filter with a cutoff frequency of 5 Hz
const float FILTER_COEFFICIENT = 0.0183;

// Define the timer for outputting the filtered values
unsigned long outputTimer = 0;

// Define the servo object and the initial throttle value
int throttleValue = 0;

int PhotoValue;

// ThingSpeak client setting setup
unsigned long myChannelNumber = 2060933;
const char * myWriteAPIKey = "6EBZTLSYCCX2JMMD";

void setup() {
  // Initialize the serial communication
 Serial.begin(9600);
 //begin the ThingSpeak
ThingSpeak.begin(client);
Particle.variable("Voltage", Voltage);
Particle.variable("Current", Current);
Particle.variable("Throttle", rawThrottle);

//set all sensor pins to inputs
pinMode(VOLTAGE_PIN, INPUT);
pinMode(CURRENT_PIN, INPUT);
pinMode(THROTTLE_PIN, INPUT);

// Set all the motor control pins to outputs
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);

// Turn off motors - Initial state
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}

void loop() {
  // Read the analog inputs
  rawVoltage = analogRead(VOLTAGE_PIN);
  rawCurrent = analogRead(CURRENT_PIN);
  rawThrottle = analogRead(THROTTLE_PIN);
  
  //set motor direction to be forward
    digitalWrite(in1, LOW);
	digitalWrite(in2, HIGH);
	digitalWrite(in3, LOW);
	digitalWrite(in4, HIGH);

  // Convert the raw values to voltages and current
  float voltage = (rawVoltage * 16.5) / 4095.0;
  float current = (-(rawCurrent * 30.0) / 4095.0)+15.086;
  int motorSpeed = map(rawThrottle, 1048, 3100, 0, 255);
  
  ///use the PWM on the motor controller
    analogWrite(enA, motorSpeed);
    analogWrite(enB, motorSpeed);

  // Filter the values
  float filteredVoltage = (FILTER_COEFFICIENT * voltage + (1 - FILTER_COEFFICIENT) * filteredVoltage);
  float  filteredCurrent = (FILTER_COEFFICIENT * current + (1 - FILTER_COEFFICIENT) * filteredCurrent);

    //multiply by 1000 for more statiscal variance since we cant send floats
    int Voltage = voltage * 1000;
    int Current = current * 1000;
  // Check if it's time to output the filtered values
  if (millis() - outputTimer >= OUTPUT_INTERVAL) {
    // Output the filtered values
    Serial.print("Filtered voltage: ");
    Serial.print(Voltage);
    Serial.print(" V, Filtered current: ");
    Serial.print(Current);
    Serial.println(" A");

    
    //Publish all of the sensor readings via Particle Console
     Particle.publish("rawVoltage",String(rawVoltage), ALL_DEVICES);
     Particle.publish("rawCurrent",String(rawCurrent), ALL_DEVICES);;
     Particle.publish("rawThrottle",String(rawThrottle), ALL_DEVICES);
     Particle.publish("Voltage",String (Voltage), ALL_DEVICES);
     Particle.publish("Current",String (Current), ALL_DEVICES);
    
    //Publish all of the sensor readings via ThingSpeak Channela
    ThingSpeak.setField(1,Voltage);
    ThingSpeak.setField(2,Current);
    ThingSpeak.setField(3,rawThrottle);
    ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

    // Reset the output timer
    outputTimer = millis();
  }
}
  

Slew rate traction control

Arduino

Same thing as before but now with traction control!

CODE
// This #include statement was automatically added by the Particle IDE.
#include <ThingSpeak.h>

// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT.h>


//Things speak client setup
TCPClient client;
// Define the pins for the analog inputs and servo output
const int VOLTAGE_PIN = A0;
const int CURRENT_PIN = A1;
const int THROTTLE_PIN = A2;

// Define the ratios for the voltage divider and current sensor calibration
const float VOLTAGE_RATIO = 0.046;
const float CURRENT_CALIBRATION = 0.066;

// Define the variables to hold the raw analog readings
int rawVoltage;
int rawCurrent;
int rawThrottle;

int Voltage;
int Current;
int Throttle;

// Motor A connections
const int enA = D7;
const int in1 = D6;
const int in2 = D5;
// Motor B connections
const int in3 = D4;
const int in4 = D3;
const int enB = D2;

// Define the time interval for reading the analog inputs (in microseconds)
const unsigned long READ_INTERVAL = 20000;

// Define the time interval for outputting the filtered values (in milliseconds)
const unsigned long OUTPUT_INTERVAL = 10000;

// Define the filter coefficients for a first-order low-pass filter with a cutoff frequency of 5 Hz
const float FILTER_COEFFICIENT = 0.0183;

// Define the timer for outputting the filtered values
unsigned long outputTimer = 0;

// Define the servo object and the initial throttle value
int throttleValue = 0;
int throttlerate = 50;
int prevThrottle = 0;
// ThingSpeak client setting setup
unsigned long myChannelNumber = 2060933;
const char * myWriteAPIKey = "6EBZTLSYCCX2JMMD";


void myHandler(const char *event, const char *data)
{
  throttlerate = String(data).toInt();
  //Log.info("%d: event=%s data=%s", i, event, (data ? data : "NULL"));
}


void setup() {
  // Initialize the serial communication
 Serial.begin(9600);
 //begin the ThingSpeak
ThingSpeak.begin(client);
Particle.variable("Voltage", Voltage);
Particle.variable("Current", Current);
Particle.variable("Throttle", rawThrottle);

 Particle.subscribe("Throttlerate", myHandler);

//set all sensor pins to inputs
pinMode(VOLTAGE_PIN, INPUT);
pinMode(CURRENT_PIN, INPUT);
pinMode(THROTTLE_PIN, INPUT);

// Set all the motor control pins to outputs
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);

// Turn off motors - Initial state
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}

void loop() {
  // Read the analog inputs
  rawVoltage = analogRead(VOLTAGE_PIN);
  rawCurrent = analogRead(CURRENT_PIN);
  rawThrottle = analogRead(THROTTLE_PIN);
  
  //set motor direction to be forward
    digitalWrite(in1, LOW);
	digitalWrite(in2, HIGH);
	digitalWrite(in3, LOW);
	digitalWrite(in4, HIGH);

  int throttle = min(rawThrottle, prevThrottle + throttlerate);
  delay(10);
  prevThrottle = throttle;
  // Convert the raw values to voltages and current
  float voltage = (rawVoltage * 16.5) / 4095.0;
  float current = (-(rawCurrent * 30.0) / 4095.0)+15.086;
  int motorSpeed = map(throttle, 1100, 3100, 0, 255);
  
  motorSpeed = constrain(motorSpeed, 0, 255);
  ///use the PWM on the motor controller
    analogWrite(enA, motorSpeed);
    analogWrite(enB, motorSpeed);

  // Filter the values
  float filteredVoltage = (FILTER_COEFFICIENT * voltage + (1 - FILTER_COEFFICIENT) * filteredVoltage);
  float  filteredCurrent = (FILTER_COEFFICIENT * current + (1 - FILTER_COEFFICIENT) * filteredCurrent);

    //multiply by 1000 for more statiscal variance since we cant send floats
    int Voltage = voltage * 1000;
    int Current = current * 1000;
  // Check if it's time to output the filtered values
  if (millis() - outputTimer >= OUTPUT_INTERVAL) {
    // Output the filtered values
    Serial.print("Filtered voltage: ");
    Serial.print(Voltage);
    Serial.print(" V, Filtered current: ");
    Serial.print(Current);
    Serial.println(" A");

    
    //Publish all of the sensor readings via Particle Console
     Particle.publish("rawVoltage",String(rawVoltage), ALL_DEVICES);
     Particle.publish("rawCurrent",String(rawCurrent), ALL_DEVICES);;
     Particle.publish("rawThrottle",String(rawThrottle), ALL_DEVICES);
     Particle.publish("Voltage",String (Voltage), ALL_DEVICES);
     Particle.publish("Current",String (Current), ALL_DEVICES);
    
    //Publish all of the sensor readings via ThingSpeak Channela
    ThingSpeak.setField(1,Voltage);
    ThingSpeak.setField(2,Current);
    ThingSpeak.setField(3,rawThrottle);
    ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

    // Reset the output timer
    outputTimer = millis();
  }
}
  

The article was first published in hackster, April 25,  2023

cr: https://www.hackster.io/control-ev-team10/control-of-electric-vehicle-9f6c5f

author: Control-EV-Team10: Gunter Hayes, Marcus Neacsu, Jason Matthews

License
All Rights
Reserved
licensBg
0