Ok, this is my first time posting for help on a code which should be simple. But, I simply can't get it.
What I want to do is while using ultra sonic sensor (HC-SR04), determine if car is parked, moving or away based on it's distance. When the car has gone from parked, to moving, then away, trigger relay to simulate pushing garage door opener button.
The code I used is from 'newping with median', which works well. Then I tried using a classic switch case example to create the 3 stages:
- range 1/ case 0: car is parked (more than 0 but less than ~25).
- range 2/ case 1: car is moving (more than 25 but less than ~50).
- range 3/ case 2: car is away (more than 50 to end of range).
But what I can't do is use flags to determine that the car did indeed transition from parked->moving->away.
If I can get that phase, it will be good, then when car is away, something cannot simply block the sensor, like a insect or something random and trigger the garage door to open. It has to go through the stages (parked, moving, away).
I hope I have explained my desire well enough. Here is the code at hand:
// ---------------------------------------------------------------------------
// Calculate a ping median using the ping_timer() method.
// ---------------------------------------------------------------------------
#include <NewPing.h>
#define ITERATIONS 5 // Number of iterations.
#define TRIGGER_PIN 5 // Arduino pin tied to trigger pin on ping sensor.
#define ECHO_PIN 4 // Arduino pin tied to echo pin on ping sensor.
#define MAX_DISTANCE 150 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).
#define ledPin 10
unsigned long pingTimer[ITERATIONS]; // Holds the times when the next ping should happen for each iteration.
unsigned int cm[ITERATIONS]; // Where the ping distances are stored.
uint8_t currentIteration = 0; // Keeps track of iteration step.
const int sensorMin = 0; // sensor minimum, discovered through experiment
const int sensorMax = 50; // sensor maximum, discovered through experiment
static bool parked = false;
int flag = 0;
int lastflag = 0;
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
void setup() {
Serial.begin(115200);
pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting.
for (uint8_t i = 1; i < ITERATIONS; i++) // Set the starting time for each iteration.
pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
digitalWrite (10, LOW);
}
void loop() {
for (uint8_t i = 0; i < ITERATIONS; i++) { // Loop through all the iterations.
if (millis() >= pingTimer[i]) { // Is it this iteration's time to ping?
pingTimer[i] += PING_INTERVAL * ITERATIONS; // Set next time this sensor will be pinged.
if (i == 0 && currentIteration == ITERATIONS - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
sonar.timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance).
currentIteration = i; // Sensor being accessed.
cm[currentIteration] = 0; // Make distance zero in case there's no ping echo for this iteration.
sonar.ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
}
}
}
void echoCheck() { // If ping received, set the sensor distance to array.
if (sonar.check_timer())
cm[currentIteration] = sonar.ping_result / US_ROUNDTRIP_CM;
}
void oneSensorCycle() { // All iterations complete, calculate the median.
unsigned int uS[ITERATIONS];
uint8_t j, it = ITERATIONS;
uS[0] = NO_ECHO;
for (uint8_t i = 0; i < it; i++) { // Loop through iteration results.
if (cm[i] != NO_ECHO) { // Ping in range, include as part of median.
if (i > 0) { // Don't start sort till second ping.
for (j = i; j > 0 && uS[j - 1] < cm[i]; j--) // Insertion sort loop.
uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion.
} else j = 0; // First ping is sort starting point.
uS[j] = cm[i]; // Add last ping to array in sorted position.
} else it--; // Ping out of range, skip and don't include as part of median.
}
int sensorReading = uS[it >> 1];
int range = map(sensorReading, sensorMin, sensorMax, 0, 2);
Serial.println(sensorReading);
lastflag=flag;
switch (range) {
case 0: // car is parked
Serial.print("parked");
flag=0;
Serial.print(flag);
Serial.println(lastflag);
break;
case 1: // car is moving out of garage
Serial.println("moving");
flag=1;
Serial.print(flag);
Serial.println(lastflag);
break;
case 2: // car is past garage door, close door
Serial.println("away");
flag=2;
Serial.print(flag);
Serial.println(lastflag);
break;
}
delay(1); // delay in between reads for stability
// only allow relay to trigger if car goes from parked to moving and then to away.
// when car returns, only allow to go from away, then moving, then parked.
// this way something can't simply block and unblock the sensor triggering relay, since it didn't go through all the stages of moving car out of garage.
if (flag != lastflag) // something changed
{
if ((flag=2) || (lastflag=1)) // changed from moving to away, trigger relay.
{
Trigger_Relay();
}
}
}
void Trigger_Relay()
{
Serial.println ("garage door toggle"); // will be replace with closing relay for 2 seconds and release, emulating garage door opener being pressed.
}