Hello, I have an arduino board with a Garmin v4 LiDAR sensor connected. My project includes a 5VDC to 120VAC relay switch that turns on and off 3 bulbs in a standard stoplight. It is used to show the distance a vehicle pulls in the garage, and when the light turns red, the vehicle should stop and park.
Everything works great, but... right now It will just leave the red light on when it's reached it's final distance. I'd like to figure out how to turn off the red light after 30 seconds once the motion basically stops (there may be a small bit of flutter from the LiDAR sensor). And then I want the light to start working against once it detects the vehicle in motion again. I'm not exactly sure how to achieve this. Here's the code I have so far:
#include "LIDARLite_v4LED.h"
LIDARLite_v4LED myLIDAR; //Click here to get the library: http://librarymanager/All#SparkFun_LIDARLitev4 by SparkFun
#define PIN_RELAY_1 6 // the Arduino pin, which connects to the IN1 pin of relay module
#define PIN_RELAY_2 7 // the Arduino pin, which connects to the IN2 pin of relay module
#define PIN_RELAY_3 8 // the Arduino pin, which connects to the IN3 pin of relay module
void setup() {
//Serial.begin(115200);
Serial.begin(9600);
Serial.println("Qwiic LIDARLite_v4 examples");
Wire.begin(); //Join I2C bus
//check if LIDAR will acknowledge over I2C
if (myLIDAR.begin() == false) {
Serial.println("Device did not acknowledge! Freezing.");
while(1);
}
Serial.println("LIDAR acknowledged!");
// initialize digital pin as an output.
pinMode(PIN_RELAY_1, OUTPUT);
pinMode(PIN_RELAY_2, OUTPUT);
pinMode(PIN_RELAY_3, OUTPUT);
}
void loop() {
float newDistance;
//getDistance() returns the distance reading in cm
newDistance = myLIDAR.getDistance();
//Print to Serial port
Serial.print("New distance: ");
Serial.print(newDistance/100);
Serial.println(" m");
if (newDistance > 710) {
Serial.println("Turn all lights off");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, LOW);
} else if (newDistance <= 710 && newDistance >= 360) {
Serial.println("Turn Green On");
digitalWrite(PIN_RELAY_1, HIGH);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, LOW);
} else if (newDistance < 360 && newDistance >= 250) {
Serial.println("Turn Yellow On");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, HIGH);
digitalWrite(PIN_RELAY_3, LOW);
} else if (newDistance < 250 && newDistance > 188) {
Serial.println("Turn Yellow and Red On");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, HIGH);
digitalWrite(PIN_RELAY_3, HIGH);
} else {
Serial.println("Turn Red On");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, HIGH);
}
delay(20); //Don't hammer too hard on the I2C bus
}
The millis() timer is good for this. Start by collecting a time stamp and in the loop function, check whether motion is detected. If so, reset the time stamp, otherwise, if timeout occurs, perform action.
In outline
unsigned long start = millis();
...
// in loop()
if (motion_is_detected) start = millis();
...
if (millis() - start > timeout) perform_actions();
For analysing if the car is still moving and to distuingish this from sensor-measuring fluttering
you have to compare the actual measuring with a measuring that happend maybe 1-3 seconds in the past by substracting them
Then check if the absolute of this difference is bigger than a threshold-value that filters out the fluttering
This means car ist still moving
if not car stands still start a timer
if timer has elapsed switch off the lights
Thanks everyone! I did get it to work with millis(), although I'm sure this isn't the most elegant way - but it does the job and works exactly as I need it to. Sharing for others who might need something similar in the future, and also in case anyone wants to share a better way.
/******************************************************************************
Reads the distance something is in front of LIDAR and prints it to the Serial port
Priyanka Makin @ SparkX Labs
Original Creation Date: Sept 30, 2019
This code is Lemonadeware; if you see me (or any other SparkFun employee) at the
local, and you've found our code helpful, please buy us a round!
Hardware Connections:
Plug Qwiic LIDAR into Qwiic RedBoard using Qwiic cable.
Set serial monitor to 115200 baud.
Distributed as-is; no warranty is given.
******************************************************************************/
#include "LIDARLite_v4LED.h"
LIDARLite_v4LED myLIDAR; //Click here to get the library: http://librarymanager/All#SparkFun_LIDARLitev4 by SparkFun
#define PIN_RELAY_1 6 // the Arduino pin, which connects to the IN1 pin of relay module
#define PIN_RELAY_2 7 // the Arduino pin, which connects to the IN2 pin of relay module
#define PIN_RELAY_3 8 // the Arduino pin, which connects to the IN3 pin of relay module
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 15000;
void setup() {
//Serial.begin(115200);
Serial.begin(9600);
Serial.println("Qwiic LIDARLite_v4 examples");
Wire.begin(); //Join I2C bus
//check if LIDAR will acknowledge over I2C
if (myLIDAR.begin() == false) {
Serial.println("Device did not acknowledge! Freezing.");
while(1);
}
Serial.println("LIDAR acknowledged!");
// initialize digital pin as an output.
pinMode(PIN_RELAY_1, OUTPUT);
pinMode(PIN_RELAY_2, OUTPUT);
pinMode(PIN_RELAY_3, OUTPUT);
startMillis = millis(); //initial start time
}
void loop() {
float newDistance;
//getDistance() returns the distance reading in cm
newDistance = myLIDAR.getDistance();
//Print to Serial port
Serial.print("New distance: ");
Serial.print(newDistance/100);
Serial.println(" m");
if (newDistance > 800) {
startMillis = millis(); //initial start time
Serial.println("Turn all lights off");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, LOW);
} else if (newDistance <= 800 && newDistance >= 380) {
startMillis = millis(); //initial start time
Serial.println("Turn Green On");
digitalWrite(PIN_RELAY_1, HIGH);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, LOW);
} else if (newDistance < 380 && newDistance >= 250) {
startMillis = millis(); //initial start time
Serial.println("Turn Yellow On");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, HIGH);
digitalWrite(PIN_RELAY_3, LOW);
} else if (newDistance < 250 && newDistance > 188) {
startMillis = millis(); //initial start time
Serial.println("Turn Yellow and Red On");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, HIGH);
digitalWrite(PIN_RELAY_3, HIGH);
} else {
currentMillis = millis();
Serial.println("Turn Red On");
//Serial.print("Start Millis:");
//Serial.println(startMillis);
//Serial.print("Current Millis:");
//Serial.println(currentMillis);
//Serial.print("period:");
//Serial.println(period);
//Serial.println("subtraction:");
//Serial.println(currentMillis - startMillis);
if (currentMillis - startMillis >= period) {
Serial.println("Timed Out");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, LOW);
} else {
Serial.println("Not Timed Out");
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, LOW);
digitalWrite(PIN_RELAY_3, HIGH);
}
}
delay(20); //Don't hammer too hard on the I2C bus
}