I wrote a code to assist in parking my car in garage.
The ultrasonic sensor I have outputs in "inches" for each time through the loop.
Conditions:
if inches>200 then I want no LED on
if inches<200 and >120 I want red LED on
if inches<120 I want green LED on
On top of this, I want the sensor to turn off after 1 minute of inactivity. My code does not
currently do this.
My code so far meets the first three conditions:
const int trigPin = 7;
const int echoPin = 8;
void setup() {
// initialize serial communication:
Serial.begin(9600);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
pinMode(13,OUTPUT);
pinMode(4,OUTPUT);
}
void loop() {
long duration, inches, cm;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
if((inches>200)){
digitalWrite(13,LOW);
digitalWrite(4,LOW);
}
if((inches<200)&&(inches>110)){
digitalWrite(13,HIGH);
digitalWrite(4,LOW);
}
if((inches<110)){
digitalWrite(13,LOW);
digitalWrite(4,HIGH);
}
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
}
long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are 73.746
// microseconds per inch (i.e. sound travels at 1130 feet per second).
// This gives the distance travelled by the ping, outbound and return,
// so we divide by 2 to get the distance of the obstacle.
// See: https://www.parallax.com/package/ping-ultrasonic-distance-sensor-downloads/
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the object we
// take half of the distance travelled.
return microseconds / 29 / 2;
}
How do I have it timeout? Seems simple but just not sure how to implement.
Have you worked with millis() (a timer)? If not, search "arduino blink without delay()" and "arduino multiple events" to get some working knowledge.
For now... let's assume you are there... (1) identify the time motion has stopped, (2) wait one minute, (3) turn off the LEDs.
While you were parking, the sensor was showing a decrease in time of flight of the echoes (translated to a decrease in distance). I imagine if you monitored "distance" (or time of flight), and when it stopped changing [give or take an inch (few cm)], then you will start a timer. Once that timer has reached your one-minute timeout, write LOW to each LED.
Does that sound right? Give it an adjustment if not? Give it a try if it looks good.
This is what I tried implementing but the LED's now don't turn on at all:
const int trigPin = 7;
const int echoPin = 8;
unsigned long lastActiveTime = 0;
const int timeoutDuration = 10000;
void setup() {
// initialize serial communication:
Serial.begin(9600);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
pinMode(13,OUTPUT);
pinMode(4,OUTPUT);
}
void loop() {
long inches_prior;
long duration, inches, cm;
bool timingInProgress=false;
unsigned long timeout_duration;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
if((inches==inches_prior)){
timingInProgress==true;
timeout_duration=millis();
}
if(timeout_duration>10000){
digitalWrite(13,LOW);
digitalWrite(4,LOW);
}
if((inches>=200)){
digitalWrite(13,LOW);
digitalWrite(4,LOW);
}
if((inches<200)&&(inches>110)&&(timeout_duration<=10000)){
digitalWrite(13,HIGH);
digitalWrite(4,LOW);
}
if((inches<110)&&(timeout_duration<=10000)){
digitalWrite(13,LOW);
digitalWrite(4,HIGH);
}
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
inches_prior=inches;
}
long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are 73.746
// microseconds per inch (i.e. sound travels at 1130 feet per second).
// This gives the distance travelled by the ping, outbound and return,
// so we divide by 2 to get the distance of the obstacle.
// See: https://www.parallax.com/package/ping-ultrasonic-distance-sensor-downloads/
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the object we
// take half of the distance travelled.
return microseconds / 29 / 2;
}
distance is (the closest distance you want) - a measurement
distance has not changed - requires "distanceOld"
time (ten seconds for testing)
Something like...
if (distance > distanceOld - 1 && distance < distanceOld + 1) // two inch deadband - distance will never be static
start the one minute/tenseconds timer
Write a "one minute" (or ten seconds) timeout sketch. Start with an LED on. Press a button to start the timer. Wait for the timeout. Turn the LED off. The button press will eventually be your "close enough" distance.
Not sure where you get 300 from. As shown in the code above I have inches_prior saved as the old measurement for the distance. I just want the timer to start when there is no change between the old and new value of "inches". For some reason the LED's do not turn on at all.
Constantly read distance and compare with a stored distance. A change (of greater than a normal error) means movement. You are trying to solve three things. Solve one at a time.
The HC-SR04 is not omnidirectional It has a 15 degree cone.
What I have so far. I do not have this working yet.
I want to turn off both LED's during periods of inactivity, like when the car is parked or the car is not in garage. That is why I compare old value with new and if old == new then it will start timer.
// this constant won't change. It's the pin number of the sensor's output:
const int trigPin = 7;
const int echoPin = 8;
unsigned long lastActiveTime = 0;
void setup() {
// initialize serial communication:
Serial.begin(9600);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
pinMode(13,OUTPUT);
pinMode(4,OUTPUT);
}
void loop() {
long inches_prior;
long duration, inches, cm;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
unsigned long timeout_duration;
if((inches>inches_prior-1)&&(inches<inches_prior+1)){
timeout_duration=millis();
}
if(timeout_duration>10000){
digitalWrite(13,LOW);
digitalWrite(4,LOW);
}
if((inches>=200)){
digitalWrite(13,LOW);
digitalWrite(4,LOW);
}
if((inches<200)&&(inches>110)&&(timeout_duration<=10000)){
digitalWrite(13,HIGH);
digitalWrite(4,LOW);
}
if((inches<110)&&(timeout_duration<=10000)){
digitalWrite(13,LOW);
digitalWrite(4,HIGH);
}
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
inches_prior=inches;
}
long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are 73.746
// microseconds per inch (i.e. sound travels at 1130 feet per second).
// This gives the distance travelled by the ping, outbound and return,
// so we divide by 2 to get the distance of the obstacle.
// See: https://www.parallax.com/package/ping-ultrasonic-distance-sensor-downloads/
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the object we
// take half of the distance travelled.
return microseconds / 29 / 2;
}
All uses of timeout_duration in any posted sketches are incoherent.
Here's the simplest way to get you inactivity timeout going.
Use a static or global variable, here I use a global:
unsigned long lastActivity;
const unsigned long activityInterval = 30000UL; // how long, 30 seconds in this example
Any time there is activity to keep the thing alive, set that variable to the current time, viz:
lastActivity = millis();
Finally, Just once elsewhere in your loop where it will get execute frequently enough, see if the time has moved ahead of the activity time by enough to cause a timeout:
if (millis() - lastActivity >= activityInterval) {
// no activity for the activityInteravl so
// do whatever timing out means right here
}
Three parts. A timing variable and a time constant for how long to wait for activity. A reset of the timer variable whenever there is activity and finally a test for the time getting far enough ahead of the last activity to mean timeout should occru.
I have a simulation of that I'll try to find, but that's it nutshelled.