I use two light sensors to calculate the speed of a marble. Here's the code and CAD file:
[...]
void speedtrap() {
speedtrap1 = millis();
speedtraptrig = 1;
}
void setup() {
pinMode(sensPin, INPUT_PULLUP);
pinMode(speedpin1, INPUT_PULLUP);
pinMode(speedpin2, INPUT_PULLUP);
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(speedpin1), speedtrap, FALLING);
lcd.init();
lcd.backlight();
lcd.setCursor(0,1);
}
void loop() {
if (speedtraptrig) {
speedtraptrig = 0;
unsigned long timestarted = millis();
while (digitalRead(speedpin2)) {
if (millis() - timestarted > speedtraptimeout) {
Serial.println("Speedtrap sens2 Timeout!, exiting");
return;
}
}
speedtrap2 = millis();
unsigned long timediffms = speedtrap2 - speedtrap1;
float velocity = sensordist/(timediffms/10.0);
lcd.clear();
lcd.print("Speed: ");
lcd.print(velocity);
lcd.print("m/s");
speeddisplay = 1;
}
}
[...]
The Problem is, that it only triggers 1/3 of the time, when the marble is at full speed (max. 5m/s). I can see the light of the ir detector blink, but nothing else happens. Does somebody know where the problem might be and how to fix it?
Thanls in advance
Are the variables that are updated in the ISR declared as volatile ?
It would have helped if you had posted your complete sketch (HINT)
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define motorPin 9
#define throttleDelay 3
#define spinupTime 100
#define sensPin 4
#define speedpin1 2
#define speedpin2 3
#define motorSpeed 200
#define motorTimeout 5000
#define sensordist 10
#define speedtraptimeout 1000
#define cols 16
#define rows 2
bool motorTrig = 0;
bool motorOn = 0;
unsigned long motorStarted;
unsigned long speedtrap1;
unsigned long speedtrap2;
bool speedtraptrig;
int speedmps;
bool speeddisplay = 0;
LiquidCrystal_I2C lcd(0x27, 16, 2);
void spinupMotor() {
if (motorOn == 0) {
speeddisplay = 0;
analogWrite(motorPin, 150);
delay(spinupTime);
lcd.clear();
lcd.print("Motor speed: ");
lcd.setCursor(15,0);
lcd.print("%");
motorOn = 1;
//Serial.println("motor started");
for (int i = 150; i <= motorSpeed; i++) {
analogWrite(motorPin, i);
lcd.setCursor(12, 0);
int percent = map(i, 130, 254, 000, 100);
if (percent < 10 ) {lcd.print(0);}
if (percent < 100 ) {lcd.print(0);}
lcd.print(percent);
delay(throttleDelay);
}
//Serial.print("current speed:");
//Serial.println(motorSpeed);
motorStarted = millis();
}
}
void speedtrap() {
speedtrap1 = millis();
speedtraptrig = 1;
}
void setup() {
pinMode(motorPin, OUTPUT);
pinMode(sensPin, INPUT);
pinMode(speedpin1, INPUT);
pinMode(speedpin2, INPUT);
analogWrite(motorPin, 120);
// Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(speedpin1), speedtrap, FALLING);
lcd.init();
lcd.backlight();
lcd.print("Get");
lcd.setCursor(0,1);
lcd.print("Ready!!");
}
void loop() {
if (digitalRead(sensPin) == 0 && motorOn == 0) {
lcd.clear();
lcd.print("Motor starting...");
spinupMotor();
}
if (millis() - motorStarted > motorTimeout && motorOn == 1) {
//Serial.print("motor timeout ");
//Serial.print(motorTimeout);
//Serial.println("ms");
analogWrite(motorPin, 120);
if (!speeddisplay) {
lcd.clear();
lcd.print("Motor Timeout");
}
motorOn = 0;
}
if (speedtraptrig) {
speedtraptrig = 0;
unsigned long timestarted = millis();
while (digitalRead(speedpin2)) {
if (millis() - timestarted > speedtraptimeout) {
//Serial.println("Speedtrap sens2 Timeout!, exiting");
return;
}
}
speedtrap2 = millis();
unsigned long timediffms = speedtrap2 - speedtrap1;
float velocity = sensordist/(timediffms/10.0);
lcd.clear();
lcd.print("Speed: ");
lcd.print(velocity);
lcd.print("m/s");
motorOn = 0;
speeddisplay = 1;
analogWrite(motorPin, 120);
}
}
It's a 2cm diameter stainless steel ball
xfpd
July 5, 2024, 10:13pm
6
speeter:
marble
Oh.
I see no lights or holes to let light through in your drawing.
It has two spots for sensors like these
And I can see they are triggering because their led blinks
Variables shared with interrupt routines MUST be declared volatile.
speedtrap1 = millis();
speedtraptrig = 1;
When accessed in the main program, it is essential to prevent shared variables from being corrupted by an interrupt. Make a copy with the interrupts off, something like the following:
noInterrupts();
unsigned long speedtrap1_copy = speedtrap1;
interrupts();
Serial.println(speedtrap1_copy);
Okay, I'll try that, although I am not quite sure why this should help since the problem only exists when the marble has a high velocity.
xfpd
July 5, 2024, 10:38pm
11
?
speeter:
It has two spots
Where?
speeter:
led blinks
Which LED?
The IR is reflecting off the curved surface (away) so is not long or strong enough to register.
Not long enough shouldn't be a problem when using interrupts, should it?
xfpd
July 5, 2024, 10:54pm
14
No. Your drawing shows a ramp. No IR LEDs.
speeter:
detection LED
That eliminates power (LED) problem.
Ok.
Time your "marble" the old fashioned way and calculate the time it spends in front of the IR transmitter. Now, use your television Remote Control and press any button for that length of time. How did your television react? Tell yourself, because I don't care. I'm not going to force you to drink the water.
Indeed, it looks like you have several problems, in addition to not taking advice.
Hi, @speeter
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
You have two sensors, why aren't you using two interrupts?
Tom..
JCA34F
July 6, 2024, 3:53am
17
You should use a beam break sensor, not a retro reflective type.
Slot sensors
dougp
July 6, 2024, 3:58am
18
By any chance are your sensors arranged like this?
No.
As already mentioned at full speed it works 1/3 of the time and always at slow speed
This is the circuit
The Power supply for the Arduino normally is a Notebook. The ESC is powered by an USB PD wall brick supplying 12V