I have a sketch that uses a laser and detector to count vehicles on the highway. When a vehicle blocks the path between the two, a determination is made, based on the speed limit, what that vehicle type is. Eg, a motorcycle is shorter than a bus so takes less time to transit. I use interrupts to trigger when the beam is broke.
This works, but the LEDs I'm using to tell me what vehicle went by don't stay on long enough, even though at this point I'm still using the delay function of 1/2 second to keep the LED on. What I want to do is:
- detect vehicle
- light appropriate LED and keep it on for 1/2 second to 1 second.
- if another vehicle breaks the beam during that period, keep the previous LED on anyway and light the second LED. Now if both vehicles are the same, a very likely scenario where two are passing simultaneously, I would just store the event and not display anything.
I will be adding RTC and SD card memory soon. I have that worked out already in another project. This car counter will be "unmanned" and I will gather information once a day from the card (or radio), so I don't really NEED the LEDs....this is more for testing, to show people how it works.
At top of my sketch are the transit times. At very bottom is the LED function call that I want to modify. I am familiar (somewhat) with using millis for this part of the code.
/* Name: LaserVehicleDetection21FE This program works 10Dec2019
By: Bob Found, Indian Harbour, NS Canada
Start Date: 30Nov2019
Last Rev: 19Dec2019
MCU: Arduino UNO
Hardware: UNO, laser, laser detector relay
Description: Laser and digital sensor with relay.
Vers History: V1.0 Simple test version
Vers 1.1 Change name to LaserVehicleDetection, added notes
1.2 use speed and vehicle size to determine vehicle type
1.5 use interrupts for laser detection, polling not fast enough
2.0 Used code from Nick Gammon for slot car race timer for proper logic.
2.1 cleanup, used own variables, took out superfluous code
2.2 Created array for 5 vehicles to minimize code, passed two parameters to
2 created functions: printResult and lightLED One LED for each vehicle
Transit times based on average length of vehicle shown in table,
at 3 speed limits. Very crude determination because speed is assumed,
not necessarily followed. Speed not measured (another project). Values
shown are absolutely correct).
11.1M/sec 13.9M/sec 16.7M/sec
40kph 50kph 60kph
Vehicle length length Transit time Transit time Transit time
meters feet sec sec sec
motorcycle 2.5 8.25 0.23 0.18 0.013
car 4.5 14.85 0.41 0.32 0.024
SUV 5.2 17.16 0.47 0.37 0.028
Pickup 6.6 21.78 0.59 0.47 0.036
Bus, semi 14 46.2 1.26 1.01 0.076
*/
const byte RelayPin = 2; // pin 2 or 3 for laser detector relay interrupt input
const byte LEDCycle = 8; //motorcycle LED
const byte LEDCar = 9; //car
const byte LEDSUV = 10; //SUV
const byte LEDPickup = 11; //pickup
const byte LEDBus = 12; //bus
unsigned long lastTriggerTime;
volatile unsigned long triggerTime;//used in main code and ISR, therefore volatile
volatile boolean triggered;
bool ledoff = HIGH; //inverted logic for LED since tied to current-sink
bool ledon = LOW;
float seconds;
String vehicle;
byte VehicArray [5] = {LEDCycle, LEDCar, LEDSUV, LEDPickup, LEDBus};
//*****************Interrupt Service Routine******************
void isr ()
{ // wait until we noticed last one
if (triggered)
return;
triggerTime = micros ();
triggered = true;
}
//*******************Setup Function*****************************
void setup() {
for (byte x = 0; x < 5; x++)
{ pinMode(VehicArray[x], OUTPUT);//Set all vehicle LED pins(in array) to Output
digitalWrite(VehicArray[x], ledoff);}//Initialize LEDs (off) for all vehicles
Serial.begin (9600);
pinMode(RelayPin, INPUT_PULLUP);//define laser relay input pin
digitalWrite (RelayPin, HIGH);
attachInterrupt(digitalPinToInterrupt (RelayPin), isr, RISING);
Serial.println ("Waiting for vehicle...");
}
//**********************Loop Function***************************
void loop()
{{ if (!triggered)//Wait for interrupt
return;//loop here until trigger is true (interrupt occurred), then execute:
}
noInterrupts();
unsigned long elapsed = triggerTime - lastTriggerTime;
lastTriggerTime = triggerTime;
triggered = false; // re-arm for next time
float seconds = elapsed / 1000000.000;
if (seconds < 0.3)
{ //printResult("Motorcycle ", seconds);//printing is only used for testing
lightLED(LEDCycle);
}
else if
(seconds > 0.3 && seconds < 0.450)
{ //printResult("Car ", seconds);
lightLED(LEDCar);
}
else if
(seconds > 0.450 && seconds < 0.530)
{// printResult("SUV ", seconds);
lightLED(LEDSUV);
}
else if
(seconds > 0.530 && seconds < 0.700)
{ //printResult("Pickup ", seconds);
lightLED(LEDPickup);
}
else if
(seconds > 0.700)
{ //printResult("Bus ", seconds);
lightLED(LEDBus);
}
interrupts();
}
//***************printResult Function********************
//for testing only
void printResult(String vehicle, float seconds)
{ Serial.print(vehicle);
Serial.println(seconds);
}
//***************lightLED Function***********************
void lightLED(byte vehicLED)
{ digitalWrite (vehicLED, ledon);
delay (500);//should run millis here
digitalWrite (vehicLED, ledoff);
delay (500);
}