Traction control system for an electric vehicle - School Project

Hello, I'm a student in electronic engineering and I have a school project I'm having problems with. What I'm trying to do is implement a traction control system for a smaller RC car that works in a similar way to a normal car.

The robot has 4 motors. The motors are connected 2 by 2 to a single driver motor (the car will only move forward or backward). Total consumption 400 mA (100 mA per wheel).
There are 2 Modules : 1 ECU Module and 1 ABS - TCS Module
ECU contains Arduino Uno with 328p uC + CAN + l298n motor driver + 1.1Mohm potentiometer (pedal input).
ABS - TCS Module contains a PCB with that has 2 speed sensors (mounted on 1 motor on each axle), Arduino Nano with 328p uC + CAN + MMA8452Q Accelerometer.
The modules are powered by a 12V battery. The motor driver needs 12V and we are using a 12V-5V converter to power the development boards.
There are 2 programs needed to be made for the 2 modules.
The program for the microcontroller(from ABS-TCS) needs to read the signals from the speed sensors and accelerometer, calculate the wheel speeds and vehicle speed, estimate the direction of the car and transmit control signals via the CAN bus.
The program for the other module (ECU) must take the information from the ABS - TCS module and if it detects a difference in speed from normal operating conditions, it sends the information to the engine controller to reduce acceleration, and to the ABS - TCS system to brake the slipping wheel, thus controlling the traction of the vehicle.

     These are the connections for ABS - TCS module:

Arduino Nano CAN Speed sensor 1 Speed sensor 2 Accelerometer
VCC +5V +5V +5V VCC_IN
GND GND GND GND GND
D2 INT - - -
D7 - OUT - -
D8 - - OUT -
D10 CS - - -
D11 MOSI - - -
D12 MISO - - -
D13 SCK - - -
A4 - - - SDA
A5 - - - SCL

  These are the connections for ECU module:

Arduino Nano CAN Driver motor Potentiometer
VCC +5V +5V VCC
GND GND GND GND
2 INT - -
3 - Enable A -
4 - IN1 -
5 - IN2 -
6 - IN3 -
7 - IN4 -
9 - Enable B -
10 CS - -
11 MOSI - -
12 - MISO - -
13 SCK - -
A1 - - Cursor

     So far I have tried to send the rpm values through the can interface using the can.h library. 
     The rpm values are different (the values received by  ECU are different from those sent by the ABS - TCS).  I didn't use timers, everything was written in loop. 

Program for the Transmitter


#include <CAN.h>

int nr_slots = 20;
const byte sensor_MOTOR1 = 7;
const byte sensor_MOTOR2 = 8;
volatile unsigned int counter1=0; 
volatile unsigned int counter2=0;


//ISR for D7
ISR(PCINT2_vect)
{
  counter1++;
}

//ISR for D8 //interrupt service routine
ISR(PCINT0_vect)
{
  counter2++;
}

void setup() {
 pinMode(sensor_MOTOR1, INPUT);
 pinMode(sensor_MOTOR2, INPUT);
 PCICR  |= 0b00000001; //enable port B for PCI
 PCMSK0 |= 0b00000001; //PCINT0 (pin D8) //Pin Change MaSK
 PCICR  |= 0b00000100; 
 PCMSK2 |= 0b10000000; //PCINT 23 (pin D7)

  
  Serial.begin(9600); 
             
  while (!Serial);

  Serial.println("CAN Sender");


  if (!CAN.begin(500E3)) { 
    Serial.println("Starting CAN failed!");
    while (1);
  } 
  
}

void loop() {
  delay(500);  // Send every 1s data via CAN bus

  int rpm1 = counter1 / nr_slots * 120;
  int rpm2 = counter2 / nr_slots * 120;

  // Reset pulse sensor counter
  counter1 = counter2 = 0;
    
  Serial.print("Motor Speed 1: ");   
  Serial.print(rpm1); 
  Serial.print(" RPM - ");

  Serial.print("Motor Speed 2: ");
  Serial.print(rpm2); 
  Serial.println(" RPM ");

  CAN.beginPacket(0x10); 
  CAN.write(rpm1);  
  CAN.write(rpm2);  
  CAN.endPacket(); 

}

Program for the Receiver

#include <CAN.h>

 int motor1_1 = 4;
 int motor1_2 = 5; 
 int motor2_1 = 6;
 int motor2_2 = 7;
 int enA = 3;
 int enB = 9;
 int motorspeed1;
 int motorspeed2;
 int rpm1,rpm2; 

void computeMotorSpeed(int potValue) {   
 static int delta1 = 0, delta2 = 0;
 static int old_rpm1 = -1, old_rpm2 = -1;
 
 // nano hasnt updated RPMs, skip calculation
 if (old_rpm1 == rpm1 && old_rpm2 == rpm2) return; 
   
 motorspeed1 = motorspeed2 = map(potValue, 0, 1023, 0, 255);
// Serial.println("Calculate new pair of motorspeed...");
    
 if (rpm1 > rpm2) {

     delta1 += delta1 > 10 ? 1 : 0;
     delta2 = 0;
 }
 if (rpm2 > rpm1) {
     delta1 = 0;
     delta2 += delta2 > 10 ? 1 : 0;
 }
 if (rpm1 == rpm2) {
     delta1 = delta2 = 0;
 }
   
 motorspeed1 -= delta1;
 motorspeed2 -= delta2;
}   


void setup() {
  Serial.begin(9600);

  pinMode(motor1_1, OUTPUT);
  pinMode(motor1_2, OUTPUT);
  pinMode(motor2_1, OUTPUT);
  pinMode(motor2_2, OUTPUT);
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  
  while (!Serial);

  Serial.println("CAN Receiver");

  // start CAN bus 500kbps
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
}

void loop() {
  int packetSize = CAN.parsePacket();
  int potValue = analogRead(A1);
  potValue = potValue*0.2492668622; //We read the analog value from the potentiometer calibrate it
  
  if(potValue > 254){
   digitalWrite(motor1_1, HIGH);// Motor A Clockwise
   digitalWrite(motor1_2, LOW); // Motor B Clockwise
   digitalWrite(motor2_1, HIGH);
   digitalWrite(motor2_2, LOW);
   analogWrite(enA, 160);
   analogWrite(enB, 160);  
  }
  else{
   digitalWrite(motor1_1, LOW);// Motor A Clockwise
   digitalWrite(motor1_2, LOW); // Motor B Clockwise
   digitalWrite(motor2_1, LOW);
   digitalWrite(motor2_2, LOW);
   analogWrite(enA, 0);
   analogWrite(enB, 0); 
  }
  
   if(CAN.packetId() == 0x10){
      rpm1 = CAN.read();
      rpm2 = CAN.read();
      Serial.print(motorspeed1); 
      Serial.print(" ");
      Serial.print(motorspeed2); 
      Serial.print("MOTOR1 RPM "); 
      Serial.print(rpm1); 
      Serial.print("\tMOTOR2 RPM "); 
      Serial.print(rpm2); 
      Serial.println();
    }
}    
The values that are sent are about 600 - 720 rpms. And the values that are received are about 288,272. 
 I can't figure out why they are so different. If anyone can help me to figure out how to fix it I would really appreciate it. Thank you!

Divide and conquer

I've not used CAN for any personal projects. If I were you I would strip down both programs and send constants across the CAN bus. I.e. send 1 then 10 then 20 then 500 then 1000 then 5000. Or something like that.

1 Like

Nice presentation Alex231997! A schematic would go a long way in helping me understand what you are doing. Following johnRob's line of thought start with one hardware item at a time and get it working. Do that until you get them going. For the CAN I use the mcp_can.h library, and have had great success. When you start on the CAN part you MUST have two nodes or the bus will not work (in loopback the error flags and the bus do not operate. Start with the send and receive files in the library. It was set up for the original MPC2515 CAN controllers which had a 16MHz crystal, if you have a China one it probably has a 8 Mhz crystal. Those are easy to change in the setup part of each programs. With both modules terminated (if not terminated it will not work) it may work first shot. Let us know how you do, have fun and good luck.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.