Electric Vehicle Control via Remote Control

BY Control-EV-Team10

Vehicle control scheme is redeisgned to include battery information and variable speed control


Control of Electric Vehicle

Things used in this project


Hardware components

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 SparkFun Dual H-Bridge motor drivers L298
1 Hall Effect Sensor, Throttle Position
1 Volt Meter, Mini 3-Wire
1 Digilent 60W PCIe 12V 5A Power Supply

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



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



Electrical Schematic


Wiring Schematic for the vehicle




Real Life wiring





Code with Voltage/Current sensor and PWM peddle


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

// 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
 //begin the ThingSpeak
Particle.variable("Voltage", Voltage);
Particle.variable("Current", Current);
Particle.variable("Throttle", rawThrottle);

//set all sensor pins to inputs

// 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(" V, Filtered 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.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


All Rights