Slotcar speed controller with display and electronic memory project

Wildbill,

Did the job and the EEPROM memory saving is working.
I divided the WRITE by 4 and mulitplied the READ by 4 too.
No hassle with low and high bytes saving and reading. Maybe in a later stage of the project.
If the value of the speedsensor differs +/- 1 this is no problem.

Next problem on the list is some pushbutton actions need to become push is one single step up or down in value.

I have seen a button libary for it but I couldnt got it to work sofar.
Even the samples cant be compiled.

Paco

Latest code

#include <EEPROM.h>



// constants that will not change:

const int displaybuttonPin = A0;        // pin that the 5 pushbutton from display is attached to
const int sensorPin = A1;               // pin that the sensor is attached to
const int speedcurveupbuttonPin = A2;    // the number of the input pin
const int speedcurvedownbuttonPin = A3;  // the number of the input pin
const int speedstartupbuttonPin = A4;        // the number of the input pin
const int speedstartdownbuttonPin = A5;      // the number of the input pin
const int pwmoutspeedPin = 2;           // the number of the output pin
const int pwmoutbrakePin = 3;           // the number of the output pin
const int calibratebuttonPin = 4;       // the number of the input pin
const int brakeupbuttonPin = 5;        // the number of the input pin
const int brakedownbuttonPin = 6;      // the number of the input pin
const int led2Pin = 12;                // currently in use as a check option
const int ledPin = 13;                  // the number of the LED output pin
const int writebuttonPin = 10;         // currently used to store the speed min max values in the EEPROM

// pin 7,8,9,10,11,12 are reserved for the display communication lines

// variables that will change:
int calibratebuttonState = 0;         // variable for reading the pushbutton status
int brakeupbuttonState = 0;           // variable for reading the pushbutton status 
int brakedownbuttonState = 0;         // variable for reading the pushbutton status
int writebuttonState = 0;             // variable for reading the pushbutton status
int sensorValue = 0;                  // the speed sensor value
int sensorMin = 1023;                 // minimum sensor value
int sensorMax = 0;                    // maximum sensor value
int deathBand = 10;                   // setting for deathband around zero point of trigger
int speedcurveValue = 0;              // setting for speedcurve (exponentional)
int speedstartValue = 0;              // setting for starting point of speed
int brakecurveValue = 0;              // setting for brakecurve (exponentional)
int brakeValue = 125;                 // Brake value set
int modelName = 9;                    // Model name in number raging from 1 to 10 for later recall
int displaybuttonCount = 0;           // Counter for display button
int speedcurveValueold = 0;
int speedstartValueold = 0;
int brakecurveValueold = 0;
int brakeValueold = 0;
int modelNameold = 0;
int minVal = 0;
int maxVal = 0;
int sensorMinold =0;
int sensorMaxold = 0;

void setup()
{
  Serial.begin(9600);                       // Output to serial writing
  
  pinMode(ledPin, OUTPUT);                  // initialize the led as a output control pin
  pinMode(led2Pin, OUTPUT);
  pinMode(calibratebuttonPin, INPUT);       // initialize the pushbutton pin as an input control pin
  pinMode(brakeupbuttonPin, INPUT);         // initialize the pushbutton pin as an input control pin
  pinMode(brakedownbuttonPin, INPUT);       // initialize the pushbutton pin as an input control pin
  pinMode(speedstartupbuttonPin, INPUT);    // initialize the pushbutton pin as an input control pin
  pinMode(speedstartdownbuttonPin, INPUT);  // initialize the pushbutton pin as an input control pin
  pinMode(speedcurveupbuttonPin, INPUT);    // initialize the pushbutton pin as an input control pin
  pinMode(speedcurvedownbuttonPin, INPUT);  // initialize the pushbutton pin as an input control pin
  pinMode(writebuttonPin, INPUT);
   
  //+++++++++++ EEprom read +++++++++++++      
  minVal = EEPROM.read(0);           // read a byte from the current address of the EEPROM
  maxVal = EEPROM.read(1);           // read a byte from the current address of the EEPROM
  sensorMin = (minVal * 4);          // read the sensorMin value and multiply by 4
  sensorMax = (maxVal * 4);          // read the sensorMax value and multiply by 4
  speedcurveValue = EEPROM.read(2);  // read a byte from the current address of the EEPROM
  speedstartValue = EEPROM.read(3);  // read a byte from the current address of the EEPROM
  brakecurveValue = EEPROM.read(4);  // read a byte from the current address of the EEPROM
  brakeValue = EEPROM.read(5);       // read a byte from the current address of the EEPROM
  modelName = EEPROM.read(6);        // read a byte from the current address of the EEPROM
  
} 

void loop()
{
        //send data to serial port for debugging
      Serial.print("SPD=" );                       
      Serial.print(sensorValue);
      Serial.print(" BRK=" );                       
      Serial.print(brakeValue);
      Serial.print(" MIN=" );                       
      Serial.print((sensorMin/4));
      Serial.print(" MAX="  );
      Serial.println((sensorMax/4));

      delay(50);
      
      writebuttonState = digitalRead(writebuttonPin); //currently the speedsensor min and max values are stored here 
      if (writebuttonState == HIGH) // values are divided by 4 due to the max of 255
      {EEPROM.write(0,sensorMin/4); EEPROM.write(1,(sensorMax/4)); digitalWrite(led2Pin, HIGH);}
      else
      digitalWrite(led2Pin, LOW);
  
  calibratebuttonState = digitalRead(calibratebuttonPin); // read the state of the pushbutton value:

  if (calibratebuttonState == HIGH) // check if the calibrationpushbutton is pressed.
   {    // calibration mode for the full throw of the speedsensor trigger
    digitalWrite(ledPin, HIGH); sensorValue = analogRead(sensorPin); // turn LED on:
    analogWrite(pwmoutspeedPin, 0); analogWrite(pwmoutbrakePin, 0); 
    if (sensorValue > sensorMax) {sensorMax = sensorValue;} // record the maximum sensor value
    if (sensorValue < sensorMin) {sensorMin = sensorValue;} // record the minimum sensor value 
   } 
  else 
   {     //regular speed / brake mode
    digitalWrite(ledPin, LOW); // turn LED off:
   
    sensorValue = analogRead(sensorPin); // read the sensor:
    sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);// apply the calibration to the sensor reading
    sensorValue = constrain(sensorValue, 0, 255); // in case the sensor value is outside the range seen during calibration
    brakeValue = constrain(brakeValue, 0, 255); // in case the sensor value is outside the range seen during calibration
         // control the outputs
      if (sensorValue > deathBand) {analogWrite(pwmoutspeedPin, sensorValue); analogWrite(pwmoutbrakePin, 0  ); }
        else
      {analogWrite(pwmoutspeedPin, 0); analogWrite(pwmoutbrakePin, brakeValue); digitalWrite(ledPin, HIGH);}

      //     +++++ check button activities +++++++
      brakeupbuttonState = digitalRead(brakeupbuttonPin);
      brakedownbuttonState = digitalRead(brakedownbuttonPin);
      
      if (brakeupbuttonState == HIGH) {brakeValue = brakeValue + 1;}
      if (brakedownbuttonState == HIGH) {brakeValue = brakeValue - 1;}
      if (speedstartupbuttonPin == HIGH) {speedstartValue= speedstartValue + 1;}
      if (speedstartdownbuttonPin == HIGH) {speedstartValue= speedstartValue - 1;}
      if (speedcurveupbuttonPin == HIGH) {speedcurveValue = speedcurveValue +1;}
      if (speedcurvedownbuttonPin == HIGH) {speedcurveValue = speedcurveValue -1;}



       //++++++++++++ EEprom write ++++++++++++ 
      //if (sensorMin != sensorMinold)
      //{EEPROM.write(0,sensorMin); sensorMinold == sensorMin;}
      //if (sensorMax != sensorMaxold)
      //{EEPROM.write(1,sensorMax); sensorMaxold == sensorMax;}
      if (speedcurveValue != speedcurveValueold)
      {EEPROM.write(2,speedcurveValue); speedcurveValueold == speedcurveValue;}
      if (speedstartValue != speedstartValueold)
      {EEPROM.write(3,speedstartValue); speedstartValueold == speedstartValue;}
      if (brakecurveValue != brakecurveValueold)
      {EEPROM.write(4,brakecurveValue); brakecurveValueold == brakecurveValue;}
      if (brakeValue != brakeValueold)
      {EEPROM.write(5,brakeValue); brakeValueold == brakeValue;}
      if (modelName != modelNameold)
      {EEPROM.write(6,modelName); modelNameold == modelName;}
      

      sensorMinold = sensorMin;
      sensorMaxold = sensorMax;
      speedcurveValueold = speedcurveValue;
      speedstartValueold = speedstartValue;
      brakecurveValueold = brakecurveValue;
      brakeValueold = brakeValue;
      modelNameold = modelName;
       
   }

}

Just for those who are in need to build their own controller an overview of the current/optional functions (if the UNO pins allow).

Currently we use a potentiometer to control the speed.
The pot can wear and also have some tolerance in motion (slack) so we are trying to look in a simple contact less option.
Do not know if this is going to work, but when the project is ready we gonna try it this way.
Induction control with a little magnet in the trigger.
http://www.droboticsonline.com/index.php/buy-it-now-arduino-compatible-smd-magnetic-induction-sensor-cable.html
It says upto 3 cm reach and output is linear. Do not know yet which chip they use.

If you have other options for contact less control the easy way let me know.

Paco

What do I do wrong?

I downloaded and installed this button libary from the playground.
http://arduino.cc/playground/Code/Button

as per instruction added all needed.

When I debug I got a problem on this line
Button button = Button(10,PULLUP);
telling me that PULLUP was not declared in this scope

If I take a new sketch and add the sample code the same happens.

I like to use the uniquepress press function to have the software in the loop as long as the button is pressed only perfroms one add up or down of the value.

#include <Button.h>

/*3.create a Button object at pin 12
4.connect button between pin 12 and GND
5.
*/
    Button button = Button(12,PULLUP);
void setup()
    {pinMode(13,OUTPUT); //debug to led 13}

void loop()
{
    if(button.isPressed()){digitalWrite(13,HIGH);}
    else
    {digitalWrite(13,LOW);}
}

Hi, Its possible that this is another library which has not been updated to work with Arduino 1.0, there are quite a few, there is an easy fix if you search.

Duane B.

rcarduino.blogspot.com

Duane,

It says version for Arduino 1.0 for the windows download. Or am I wrong?

Paco

For those who follow the project.

The base settings can be done by 6 push buttons. We now can write the data set in the controller in realtime to a PC control panel. We can read on the controller the main data on a LCD. Bought a LCD shield using to much data lines. :( Have ordered a 4 x20 IIC lcd to overcome this problem as I have enough analog lines not used. :)

Next step is to send the data from the PC control panel to the UNO so the data at both side is syncronized. Still all is done by USB cable but the Bluetooth option is still on my list.

Paco

A screenshot of the current PC controlpanel of the data send by the controller.

Sofar my thanks go to Rob Tilltaart and Pauls for their assistance in the project.

Paco

We have the controller now running with a 4 x 20 display and six push buttons to control all settings this way by display. The prototype contactless sensor is working too using a small magnet and a ratiometric hall sensor. Ran only into Sram problems (2Kb seems a lot but in the end is nothing) with the UNO so might have to switch for prototyping to a Mega2560 board.

Paco

Are you still there? The Sram problem made me to ordering a Mega2560 as there is no option for the UNO I found to enlarge the Sram. The MENWIZ menu structure design by Roberto works and we now set all settings by using 4 buttons and the 4 x20 I2C display. For the 6 quick access up /down buttons used on the controller handle and the 4 buttons for the menu navigation I tried to use 2 analog pins to reduce wires running from the handle to the controller board. beside + and - we then have 2 lines for the pushbuttons 2 for I2c for the display. The analog port will detect 6 buttons each. Simple resistor ladder send a voltage to the Analog pin which convert it to statement.

More to come as the bluetooth modules are on their way too. Then beside USB connection the BT connection to a BT equipped smart phone running Android will be an orther hurdle to take.

Paco

Here an over view picture on the prototype sofar.

Paco

Altough the exponential power curve adding looked to be simple I am still working on it with help from other members here. What I achieved in the meantime is regenerative breaking.

Normally when you like to break the car to reduce speed dramaticly you have to release the trigger to its zero position so the brake FET is switched on.

If you reduce speed by releasing the trigger the motor will have less internal braking and still carry high speed.

Now when you release the trigger and the speedValue is lower as the previous speedValue the brakes are ON and Speed FET OFF until the speedvalue of the trigger is level or higher again. This way you brake much later and does not have to release the trigger to full brake section. In the end this would save time and lower the lap time.

More to come

Paco

Did some more programming and added the QAB Quick Access Buttons for speedstart, speedcurve and brake on the controller handle.
The four red buttons are for the menu navigation.
Ordered BTS6143 fets ( High side smart N-channel fet) for the speed side and regular logic level N-channel fet for the brake.
Still a long way to go… :sweat_smile:

Paco

Two steps further.

Breadboard stage has gone and we have a working prototype ready to use.
The upper DIY MEGA shield contains the 4 buttons for the MENWIZ menu navigation and 4 indication LED’s.
Two fets for speed and brake rated at 8 AMP continous mode each at the top of the shield.
Also the BT module is connected and working.
Wireless BT connection with the previous made Visual basic program is working too.
Next step is to communicated with the SMARTPHONE by BT and control en view the settings from there.

Paco

Update :slight_smile:

We are now a long way since the start but we are making progress.
We swapped the handmade controller handle for a ready to buy version.
The potentiometer who was giving eratic values during testing is replaced by a linear hall sensor and a 10x10x4 mm neodyne magnet.
The 6 six buttons for 3 selectable main functions up and down now have 4 neighbour buttons which control the menu navigation.
The cable to the Mega is a ripped USB cable with “+”, “-” and the analog values wires for the hall sensor and the menubuttons which work on an analog port too.
In the picture all looks to be connected but the Mega the display and the button board are mechanical seperated still.
More to come.

Paco

An other step.
We are currently wireless connected from conroller to the LAPTOP PC by BlueTooth.
This is only one direction communication.
PC screen shows all available settings in realtime.
The power curve screen also shown in realtime.
Now we like to set the controller by the PC screen in the other direction.

Paco

We replaced the 20x4 for a 16x2 and connected it to button pcb.
We had to replace the USB cable for a 6 wire telephone flatcable to get the I2C through it.
We placed the BT modul on the shield.

Paco

Hi Paco,

:) Very Nice Project!!!

What Means Regenerative Braking and his values ???

Steve

Hi Steve,

Pull the trigger full to get full speed. You reach a corner and have to reduce speed. Now if you release the trigger fully it will brake to reduce speed like any regular controller. When you enter the corner you have to pull the trigger again for let say 50%. So you go from 100 to 0 to 50% to enter the corner. This means lot of trigger travel and time.

Now with regenerative breaking. You reach a corner and release the trigger to 50%. As the regenrative brake hysteresys is set to 5% it will activate the break from 95 to 50% and then release the brake and go furhter with the speed of 50%.

So with this option you can brake later as you only release the trigger to the point you need to round the corner. This reduces trigger movement time and also make the driving and control more smooth. The hysteresys can be altered.

Now we also have speed brake. If the trigger was pulled fully you carry more speed so you need more brake to reduce speed. If the trigger was pulled 50% you carry less speed so you need less brake.

So speed brake is a speed dependable brake value.

Do you understand? :-)

Paco

Great !!!

Many thanks

When will be possible to see any "On Road Video" :astonished: :astonished: :astonished: :astonished:

I can't wait... :D

Steve

Any News???