Using Arduino for Slot car timing

Hi all

I am relatively new to Arduino and the world of programming, But I am already hooked on the few things I’ve tried…

Being the holiday season again, I took out my Scalextric set for some fun with the kids. And in playing a few evenings ago, I thought of creating a slot car lap counter as well as lap timing program using Arduino. Firstly, I’ll admit to scouring the Internet in search of a quick tutorial or step-by-step guide. But I haven’t found one. But the desire to create one is all the more present now…

So here is what my plan is:

Arduino Mega or Nano (I have both)
Reed switches glued under the track.

And I would like to use my Laptop to read back the info.

Here is the code I found for a simple counter using reed switches:

I’ll add more later…

ExtendedReed_V2.ino (1.1 KB)

Welcome to the forum.

Please read this and follow the advice on posting the code here using code tags. Using them makes it much easier to copy the program into an editor without downloading it.

Louisbaby: Being the holiday season again, I took out my Scalextric set for some fun with the kids. And in playing a few evenings ago, I thought of creating a slot car lap counter as well as lap timing program using Arduino. Firstly, I'll admit to scouring the Internet in search of a quick tutorial or step-by-step guide. But I haven't found one. But the desire to create one is all the more present now...

A while ago a guy in the German forum asked for a lap counting/timing code for his "Carrera-Bahn", which is the common brand of slot cars here in Germany.

I created him a small Arduino sketch for this hardware: - Carrera-Bahn with 2 slot cars - Arduino UNO - LCD Keypad Shield as a display - 2 reed switches glued under the track

The LCD provides a 2-second-changing display for: - lap counter - time display (last lap / fastest lap)

The slotcar timing sketch for this hardware is in this posting in the German forum: http://forum.arduino.cc/index.php?topic=158779.msg1189593#msg1189593 (Comments in that code are German)

I think I've everything prepared so that the sketch also can be used with a MEGA board and with 4 or 6 slots instead of 2 with only a few changes in the code.

Thanks Jurs

I have to say, Google translate didn't work properly, so I am a little in the dark with a few things.

Firstly the code is one long string - I'm a little unsure on how to seperate it. Secondly - could I make use of my Laptop for the graphical representation?

Louisbaby:
Firstly the code is one long string - I’m a little unsure on how to seperate it.

Which operating system do you use?
How did you copy-and-paste the code into the Arduino-IDE so that you got all code in one single line?

I’ve just copied the code into the Windows “notepad.exe” editor and saved as a TXT file. I’ll attach that. This file should contain “Windows line endings” (CR/LF). Copy the contents from the TXT file into the Arduino-IDE editor.

Louisbaby:
Secondly - could I make use of my Laptop for the graphical representation?

Currently, the display shows “text output” only.
You can easily send the same text output to Serial instead of LCD, so you could watch in the serial monitor or in any serial terminal software.

What do you mean by “graphical representation”?

slotcar.txt (3.82 KB)

Thanks for that, I will try and decipher the German back to english.

By graphical I ment seeing it on a screen. Not necessarily a graphic picture, that I will attempt later.

Louisbaby: Thanks for that, I will try and decipher the German back to english.

These days I'm a bit short of time, but perhaps next year, maybe. If anybody needs it with comments in English.

Louisbaby: By graphical I ment seeing it on a screen. Not necessarily a graphic picture, that I will attempt later.

If you just want to see the data on the serial.monitor, you could add Serial initialization in the setup() function by adding:

Serial.begin(9600);

And then you could replace every occurance of:

   lcd.print(lcdline);

with additional output on Serial:

   lcd.print(lcdline);
   Serial.println(lcdline);

Here is what I have so far…

Not sure about certain of the faults in the code that returns after compiling it.

sketch_Reed_slot_mach1.ino (3.94 KB)

Louisbaby: Not sure about certain of the faults in the code that returns after compiling it.

You better not try to use space characters in variable names.

So instead of:

long lap time [] = ...
long lap time record [] = ...

perhaps better name the variables like:

long lapTime [] = ...
long lapTimeRecord [] = ...

Besides of that: DO NOT replace the commas used as seperating characters between array elements by a point!

Louisbaby: Here is what I have so far...

Not sure about certain of the faults in the code that returns after compiling it.

You need to go thru the translated code and rename the variables into single "verbose" for C to understand.

For example "lap time processing" could be changed to "Lap_Time_Processing" or "LapTimeProcessing". There is no other way to correct the code so it will at least compile. Just step by step, each line.

Having a problem with this line:

void (*isrFunctions [])() = { timing1, timing2 };

It comes back with this fault:

sketch_Reed_slot_mach1:18: error: 'timing1' was not declared in this scope

void (*isrFunctions [])() = { timing1, timing2 };

^

sketch_Reed_slot_mach1:18: error: 'timing2' was not declared in this scope

void (*isrFunctions [])() = { timing1, timing2 };

^

What on earth am I missing?

Louisbaby: What on earth am I missing?

The code I posted was written for Arduino-IDE v1.0.5 and compiled fine with that IDE version.

I just tried a compile test with a more recent Arduino-IDE v1.6.5-r5 and the code compiled fine with that IDE version, although it creates some warnings like:

warning: comparison between signed and unsigned integer expressions (you can ignore warnings, or fix the variable type declarations if you like)

So you should not get any trouble compiling the posted code when using Arduino IDE versions between 1.0.5 and 1.6.5, at least.

Some hints: - use an Arduino IDE version in the range 1.0.5 and 1.6.5 for compiling the code - first compile the original code "as it is", no "error" should occor, only "warnings" (depends on IDE version) - better do not mangle the whole source code through a "translator service" - translate comment for comment for comment - translate single variable names (without adding space characters in variable names) - if the code compiles "before translation" but does not compile "after translation", it's the translation causing the error

Louisbaby: Having a problem with this line:

void (*isrFunctions [])() = { timing1, timing2 };

I am not sure this definition is "legal" as far as C is concerned anyway.

It comes back with this fault:

sketch_Reed_slot_mach1:18: error: 'timing1' was not declared in this scope

void (*isrFunctions [])() = { timing1, timing2 };

^

sketch_Reed_slot_mach1:18: error: 'timing2' was not declared in this scope

void (*isrFunctions [])() = { timing1, timing2 };

^

What on earth am I missing?

Look at the original single slot detector code.

In your code the single code has been replaced with an array , hence it has to be coded / defined as an array - both interrupt pins and the isr.

Single

#define LEDPIN 13  //das wirds der pin sein der meine led blinken lässt?!
#define REEDPIN1 2         //der Eingang der als erste von zwei Interrupts an Pin 2 fungiert?!
#define REEDINTERRUPT1 0
long roundStart1 = -9999;   //verstehe ich noch nicht

//denke das ich das ganze zweimal machen muss wegen der zwei eingänge, versuche das mal in einem script einzubauen

void setup() {
  // put your setup code here, to run once:
  pinMode(LEDPIN, OUTPUT);
  pinMode(REEDPIN1, INPUT_PULLUP);
  attachInterrupt(REEDINTERRUPT1, timing1, CHANGE);

timig1 is single ISR here 
}


Array


#define LEDPIN 13 
#define SLOTS 2 // minimum lap time in milliseconds, everything underneath interpreted as contact bounce 
#define MINROUNDTIME 500 // Pins for connection of reed contacts (D2, D3) 

byte reedPins[ ]= {2,3} ; // interrupt numbers to these pins 
byte pinInterrupts[ ]= {0,1}; // interrupt handlers 

single isr replaced with  pinInterrupts[ ] array here 

void (* isrFunctions []) () = {timing1, timing2}; 
// Start the final lap in milliseconds, volatile because access also from ISR! 
volatile long around the top[ ]= {0,0}; // lap time on the last lap in milliseconds 
long lap time[ ]= {99990.99990}; // lap time of the fastest lap in milliseconds 
long lap time record[ ]= {} 99990.99990; // lap counter 
int round number[ ]= {0,0};

jurs: - better do not mangle the whole source code through a "translator service"

This should go without saying.

Besides, you don't need to know German to make sense out of a lot of it. For example, what do you suppose "Millisekunden" are?

Thanks to everyone who has helped me so far, and I apologize if my questions are silly. I do only have 3 weeks worth of trail-and-error coding practice. So I suppose I shouldn’t be taking on such ambitious projects so early. But boys will be boys…

Anyway, I am running Arduino V1.6.6, and I will try to copy and paste your code from the TXT file you sent me, and see if it compiles correctly, and take it from there.

Louisbaby: So I suppose I shouldn't be taking on such ambitious projects so early. But boys will be boys...

Maybe those boys should try their hand at coding.

Ok, so I copied and paste straight from your TXT into Arduino 1.6.6 and this is the error message:

The error message seems quite clear. Where is timing2 declared in the program ?

If you need to post error messages in future please copy/paste them into a post here using code tags to avoid the need to download many Kb of a screen shot.

Ok, so I have completed my code about 85%. I am needing help with one more thing. I want to insert a code to increase the amount of laps by the push of a button before the race starts.

Here is the code that I have put together that works well:

Code "
#include <StopWatch.h>
#include <PString.h>
#include <Button.h>

#define switchPin 2 //Lane 1 Reed switch to digital pin 2 (BLUE)
#define switchPin2 3 //Lane 2 Reed switch to digital pin 3 (RED)
#define ledPin 4 //Lane 1 Lap count indicate Blue LED
#define ledPin2 5 //Lane 2 Lap count indicate Red LED
#define trafficLightGreen D6 //Red LED for traffic light
#define trafficLightOrange D7 //Orange LED for traffic light
#define trafficLightRed D8 //Green LED for traffic light

StopWatch SW1;
StopWatch SW2;
StopWatch SW3;

int sense0 = 2;
int sense1 = 3;
int counter0 = 0;
int counter1 = 0;
unsigned long start = 0;
int lap = 0;
unsigned long lapTime;
unsigned long lapArray[4];
long lastDebounce0 = 0;
long lastDebounce1 = 0;
long debounceDelay = 500; // Ignore bounces under 1/2 second
//long roundStart1=-9999;
unsigned short totalLaps = 10;

void setup() {
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(switchPin, INPUT); // switchPin is an input
digitalWrite(switchPin, HIGH); // Activate internal pullup resistor
pinMode(switchPin2, INPUT); // switchPin is an input
digitalWrite(switchPin2, HIGH); // Activate internal pullup resistor
Serial.begin(9600);
pinMode(sense0, INPUT);
digitalWrite(sense0, HIGH);
pinMode(ledPin,OUTPUT);
pinMode(sense1, INPUT);
digitalWrite(sense1, HIGH);
pinMode(ledPin2,OUTPUT);
attachInterrupt(0, trigger0, FALLING);
attachInterrupt(1, trigger1, FALLING);
Serial.println(“Race Lap counter”);
Serial.println(“Begin Race”);
trafficlight();

}

void trafficlight()
{
digitalWrite(6, HIGH); // Turns LED on pin 6 on
Serial.println(" READY ");
delay(5000); // LED on pin 6 remains on for 5 seconds
digitalWrite(6, LOW); // Turns LED on pin 6 off

digitalWrite(7, HIGH); // Turns LED on pin 7 on
Serial.println(" SET ");
delay(5000); // LED on pin 7 remains on for 5 seconds
digitalWrite(7, LOW); // Turns LED on pin 7 off

digitalWrite(8, HIGH); // Turns LED on pin 8 on
Serial.println(" GO ");
delay(2500); // LED on pin 8 remains on for 2.5 seconds
digitalWrite(8, LOW); // Turns LED on pin 8 off

SW1.reset();
SW1.start();
SW2.reset();
SW2.start();
SW3.reset();
SW3.start();
}

void ledindicate()
{
if( (millis() - lastDebounce0) > debounceDelay)
digitalWrite(ledPin,LOW);
else
digitalWrite(ledPin,HIGH);

if( (millis() - lastDebounce1) > debounceDelay)
digitalWrite(ledPin2,LOW);
else
digitalWrite(ledPin2,HIGH);

}

void loop()
{

ledindicate();

}

void trigger0()
{
if( (millis() - lastDebounce0) > debounceDelay)
{
SW1.stop();
counter0++;
Serial.print(“LANE1 >> Lap #”);
Serial.print(counter0);
Serial.print("; time: ");
Serial.println(SW1.value()/1000.0,3);
if (counter0 >= totalLaps)

{
Serial.print("Total Race Time: ");
Serial.println(SW3.value()/1000.0,3);

}

lastDebounce0 = millis();
SW1.reset();
SW1.start();
}
}

void trigger1()
{
if( (millis() - lastDebounce1) > debounceDelay)
{
SW2.stop();
counter1++;
Serial.print(“LANE2 >> Lap #”);
Serial.print(counter1);
Serial.print("; time: ");
Serial.println(SW2.value()/1000.0,3);
if (counter1 >= totalLaps)
{
Serial.print("Total Race Time: ");
Serial.println(SW3.value()/1000.0,3);
}

lastDebounce1 = millis();
SW2.reset();
SW2.start();
}

}
code end.

Then I inserted a code to increase laps, but it doesn’t seem to run before the main code runs. So the race begins before I can choose the amount of laps, and I have no idea why.

Code:
// 2 Lane reed switch lap counter with LED indication and timing(work in progress)
// Traffic light code designed by Marquez Santos! (on facebook)
// Connect green LED to pin D8
// Connect yellow LED to pin D7
// Connect red LED to pin D6

#include <StopWatch.h>
#include <PString.h>
#include <Button.h>

#define switchPin 2 //Lane 1 Reed switch to digital pin 2 (BLUE)
#define switchPin2 3 //Lane 2 Reed switch to digital pin 3 (RED)
#define ledPin 4 //Lane 1 Lap count indicate Blue LED
#define ledPin2 5 //Lane 2 Lap count indicate Red LED
#define trafficLightGreen D6 //Red LED for traffic light
#define trafficLightOrange D7 //Orange LED for traffic light
#define trafficLightRed D8 //Green LED for traffic light
#define pushButton D10 //Lap increase button
#define ledPinIncrease D13 //LED acknowledgement for addtion to laps from pushbutton

StopWatch SW1;
StopWatch SW2;
StopWatch SW3;

int ledPinIncrease = 13; // choose the pin for the LED
int pushButton = 10; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
//int totalLaps = 0;
int currentState = 0;
int previousState = 0;
int sense0 = 2;
int sense1 = 3;
int counter0 = 0;
int counter1 = 0;
unsigned long start = 0;
int lap = 0;
unsigned long lapTime;
unsigned long lapArray[4];
long lastDebounce0 = 0;
long lastDebounce1 = 0;
long debounceDelay = 500; // Ignore bounces under 1/2 second
long roundStart1=-9999;
unsigned short totalLaps = 0;

void setup() {
pinMode(ledPinIncrease, OUTPUT); // declare LED as output
pinMode(pushButton, INPUT); // declare pushbutton as input
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(switchPin, INPUT); // switchPin is an input
digitalWrite(switchPin, HIGH); // Activate internal pullup resistor
pinMode(switchPin2, INPUT); // switchPin is an input
digitalWrite(switchPin2, HIGH); // Activate internal pullup resistor
Serial.begin(9600);
pinMode(sense0, INPUT);
digitalWrite(sense0, HIGH);
pinMode(ledPin,OUTPUT);
pinMode(sense1, INPUT);
digitalWrite(sense1, HIGH);
pinMode(ledPin2,OUTPUT);
attachInterrupt(0, trigger0, FALLING);
attachInterrupt(1, trigger1, FALLING);
Serial.println(“Race Lap counter”);
Serial.println(“Begin Race”);
//lapcount();
trafficlight();

}

void lapcount()
{

val = digitalRead(pushButton); // read input value
if (val == HIGH) { // check if the input is HIGH (button released)
digitalWrite(ledPinIncrease, HIGH); // turn LED on
currentState = 1;
}
else {
digitalWrite(ledPinIncrease, LOW); // turn LED off
currentState = 0;
}
if(currentState != previousState){
if(currentState == 1){
totalLaps = totalLaps + 5;
Serial.print("Total Laps ");
Serial.println(totalLaps);
}
}
previousState = currentState;
delay(250);

/* while(1)
delay(10000);
digitalWrite(6, HIGH); // Turns LED on pin 6 on
Serial.println(" READY ");
delay(5000); // LED on pin 6 remains on for 5 seconds
digitalWrite(6, LOW); // Turns LED on pin 6 off

digitalWrite(7, HIGH); // Turns LED on pin 7 on
Serial.println(" SET ");
delay(5000); // LED on pin 7 remains on for 5 seconds
digitalWrite(7, LOW); // Turns LED on pin 7 off

digitalWrite(8, HIGH); // Turns LED on pin 8 on
Serial.println(" GO ");
delay(2500); // LED on pin 8 remains on for 2.5 seconds
digitalWrite(8, LOW); // Turns LED on pin 8 off

SW1.reset();
SW1.start();
SW2.reset();
SW2.start();
SW3.reset();
SW3.start();*/

}

void trafficlight()
{
delay(10000);
digitalWrite(6, HIGH); // Turns LED on pin 6 on
Serial.println(" READY ");
delay(5000); // LED on pin 6 remains on for 5 seconds
digitalWrite(6, LOW); // Turns LED on pin 6 off

digitalWrite(7, HIGH); // Turns LED on pin 7 on
Serial.println(" SET ");
delay(5000); // LED on pin 7 remains on for 5 seconds
digitalWrite(7, LOW); // Turns LED on pin 7 off

digitalWrite(8, HIGH); // Turns LED on pin 8 on
Serial.println(" GO ");
delay(2500); // LED on pin 8 remains on for 2.5 seconds
digitalWrite(8, LOW); // Turns LED on pin 8 off

SW1.reset();
SW1.start();
SW2.reset();
SW2.start();
SW3.reset();
SW3.start();
}

void ledindicate()
{
if( (millis() - lastDebounce0) > debounceDelay)
digitalWrite(ledPin,LOW);
else
digitalWrite(ledPin,HIGH);

if( (millis() - lastDebounce1) > debounceDelay)
digitalWrite(ledPin2,LOW);
else
digitalWrite(ledPin2,HIGH);

}

void loop()
{

ledindicate();
/*val = digitalRead(pushButton); // read input value
if (val == HIGH) { // check if the input is HIGH (button released)
digitalWrite(ledPinIncrease, HIGH); // turn LED on
currentState = 1;
}
else {
digitalWrite(ledPinIncrease, LOW); // turn LED off
currentState = 0;
}
if(currentState != previousState){
if(currentState == 1){
totalLaps = totalLaps + 5;
Serial.print("Total Laps ");
Serial.println(totalLaps);
}
}
previousState = currentState;
delay(250);
*/
}

void trigger0()
{
if( (millis() - lastDebounce0) > debounceDelay)
{
SW1.stop();
counter0++;
Serial.print(“LANE1 >> Lap #”);
Serial.print(counter0);
Serial.print("; time: ");
Serial.println(SW1.value()/1000.0,3);
if (counter0 >= totalLaps)
{
Serial.print("Total Race Time: ");
Serial.println(SW3.value()/1000.0,3);

}

lastDebounce0 = millis();
SW1.reset();
SW1.start();
}
}

void trigger1()
{
if( (millis() - lastDebounce1) > debounceDelay)
{
SW2.stop();
counter1++;
Serial.print(“LANE2 >> Lap #”);
Serial.print(counter1);
Serial.print("; time: ");
Serial.println(SW2.value()/1000.0,3);
if (counter1 >= totalLaps)
{
Serial.print("Total Race Time: ");
Serial.println(SW3.value()/1000.0,3);
}

lastDebounce1 = millis();
SW2.reset();
SW2.start();
}

}
Code ends.

Can somebody please guide me to the problem? I’ve learnt a lot, but I still have so much to learn.

P.S. I hope I got the Code tag right…