"STOP!!" Said the Sensor to the Car.
4361 Views, 17 Favorites, 0 Comments
"STOP!!" Said the Sensor to the Car.
![20171123_111918.jpg](/proxy/?url=https://content.instructables.com/FC4/UWRQ/JAMTWETM/FC4UWRQJAMTWETM.jpg&filename=20171123_111918.jpg)
![20171114_193116.jpg](/proxy/?url=https://content.instructables.com/F58/U9R1/JASJLHI1/F58U9R1JASJLHI1.jpg&filename=20171114_193116.jpg)
![STOP!! Sensor Concept Video](/proxy/?url=https://content.instructables.com/FMA/9LKM/JASJNERF/FMA9LKMJASJNERF.jpg&filename=STOP!! Sensor Concept Video)
![Version 7 STOP!! Sensor](/proxy/?url=https://content.instructables.com/FLD/YEER/JASJNFGW/FLDYEERJASJNFGW.jpg&filename=Version 7 STOP!! Sensor)
Motivation:
There are many car sensor projects available online utilizing code that I don't thoroughly understand as of December 2017. Thus I took it upon myself to better learn arduino and apply logic operators to construct a code that could assist a person in parking a vehicle. If you don't own an autonomous self parking vehicle, here's a much cheaper way to park your car in your garage or driveway. Perhaps while you're waiting for your Tesla you could make this.
This project is also devoted to my parents who drive me to school and back every week. This should make their tiring routine a bit easier.
This is my attempt at constructing the simplest software and hardware package to help park a car.
Approach:
To accomplish my goal, I decided to divide the project into four steps.
- Sense car
- Detect accurate distance to car
- Orient lights in a way that a person can understand their proximity to the wall
- Put microprocessor into a low power mode
Only 2 LEDs, one 200ohm resistor, 4 jumper wires, an arduino, a breadboard and an ultrasonic sensor are needed for this project.
I'm also selling fully assembled STOP Sensors as well here: Link
Materials Needed:
Sense Car and Detect Accurate Distance to Car
Out of simplicity, I decided to use an ultrasonic sensor to detect the car and detect its distance to the car.
Ultrasonic Sensor: HC-SR04 Sensor or HC_SR04 Sensor
My code for this step is based on this arduino site: http://playground.arduino.cc/Code/NewPing
However, I found that the ultrasonic sensor gave occasionally erroneous readings. Therefore I had to average the distance values outputted from the sensor in order to "smoothen" the distance values.
My code for smoothing is based on this arduino site: https://www.arduino.cc/en/Tutorial/Smoothing
When the sensor detects that no car is present, it will check to see if there's an incoming vehicle once a second by sending 1 ping.
Below is the segmented code that I constructed when integrating both distance detection and smoothing.
The full code and the arduino sketch are provided at the end of the instructable.
<p>#include <NewPing.h> //http://playground.arduino.cc/Code/NewPing<br>#include <LowPower.h> //added low power library from sparkfun <a href="https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption" rel="nofollow"> https://learn.sparkfun.com/tutorials/reducing-ard...> #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. #define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters). was 400, max 500 was 500/2 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. // Define the number of samples to keep track of. The higher the number, // the more the readings will be smoothed, but the slower the output will // respond to the input. Using a constant rather than a normal variable lets // use this value to determine the size of the readings array. const int numReadings = 10; //was 10 int readings[numReadings]; // the readings from the analog input int readIndex = 0; // the index of the current reading int total = 0; // the running total int average = 0; // the average int LED_STOP = 6; //Declare stop light int LED_Yield = 7;// the number of the LED pin int dist = 0; //Declare dist variable int stopdist = 17; //declare stopping distance in cm (dist when red LED turns on) int stopdist_plus_7 = stopdist+7; //declare distance when yellow LED stops blinking and becomes solid int ultrasonic_power = 3; // Variables will change : int ledState = LOW; // ledState used to set the LED // Generally, you should use "unsigned long" for variables that hold time // The value will quickly become too large for an int to store unsigned long previousMillis = 0; // will store last time LED was updated unsigned long previousMillis_2 = 0; // constants won't change : const long interval = average; //was 850/3 // interval at which to blink (milliseconds) const long interval_2 = 1; // was 1000/2interval for turning off LEDs divide by 2 for 8mhz clock speed, else dont for 16, decreased interval_2 size to 100 to account for walking in front of sensor unsigned long time; void setup() { Serial.begin(57600); // Open serial monitor at 115200 baud to see ping results. // set the digital pin as output: pinMode(ultrasonic_power, OUTPUT); } void loop() { const long interval = average/1; digitalWrite(ultrasonic_power, HIGH); delay(50); // subtract the last reading: total = total - readings[readIndex]; // read from the sensor: readings[readIndex] = dist; // add the reading to the total: total = total + readings[readIndex]; // advance to the next position in the array: readIndex = readIndex + 1; // if we're at the end of the array... if (readIndex >= numReadings) { // ...wrap around to the beginning: readIndex = 0; } // calculate the average: average = (total / numReadings); // send it to the computer as ASCII digits // Serial.println(average); delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range) dist = uS / US_ROUNDTRIP_CM; //did div by 2 in prescaler update Serial.println("cm"); // Serial.print(average); // check to see if it's time to blink the LED; that is, if the // difference between the current time and last time you blinked // the LED is bigger than the interval at which you want to // blink the LED.</p>
Orient Lights in a Way That a Person Can Understand Their Proximity to the Wall
![20170525_144228.jpg](/proxy/?url=https://content.instructables.com/FLF/SJA3/JASJLHI0/FLFSJA3JASJLHI0.jpg&filename=20170525_144228.jpg)
Here, is code that tells the LED lights what to do when the car is a certain distance away from the wall.
I used red and yellow LED lights such as these: LED lights
I found it neat that I could utilize code from the arduino website for blinking an LED to make the yellow LEDs in the project blink faster as the car gets closer to the wall. When the stop distance is reached, the red LEDs turn on. After 15 seconds, the red and yellow LEDs turn off to conserve power.
The site where this code came from is here: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
All other code is based off of if/else, and statements and for loops.
See Arduino if/else statements and for loop tutorials here:
https://www.arduino.cc/reference/en/language/structure/control-structure/else/
Notice that I turn off the LEDs and the ultrasonic sensor when the average distance is less than 10cm. This is to account for obstacles in the garage or irregular shapes that may "confuse" the sensor into thinking that an object is present. I found that this correction prevented the LEDs from turning on when no car was present.
The code is versatile. You can change the stop distance (in cm) by changing the variable stopdist. This will change the distance at which the red LEDs turn on. You can change the distance when the yellow LEDS become solid be changing the variable stopdist_plus_7. By changing the const long interval variable before setup, you can change the frequency in which the device blinks as seen here in the latest version that is running this code:
<p>if (average > 10 && average <= stopdist) //added if/else structure was average > 10, removed average <=<br> { if (average < stopdist && (currentMillis - previousMillis_2 < 10000))//if less than 17cm (default stopdist) and close to wall for less than 10 s turn on light { if (average > 10) // was 10 { digitalWrite(LED_STOP, HIGH); delay(1000); //changed, was 2500 } else { digitalWrite(LED_STOP, LOW); } } if ((currentMillis - previousMillis_2) > 15000) //was 7500 { for (byte i = 0; i < 1; ++i) //wait to check every ~20 s { digitalWrite(ultrasonic_power, LOW); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); digitalWrite(LED_STOP, LOW); digitalWrite(LED_Yield, LOW); } Serial.println("just left low power jeelib"); } } else { //Following code in if statement modified from <a href="https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay" rel="nofollow"> <a href="https://www.arduino.cc/en/Tutorial/BlinkWithoutDe...</a"> https://www.arduino.cc/en/Tutorial/BlinkWithoutDe...>> //if (average > 65) //added nested if statement if (average > stopdist_plus_7) // { if (average < 390) //was 390 then 300 was 450/2 { if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } // set the LED with the ledState of the variable: digitalWrite(LED_Yield, ledState); } } } //Serial.println("prevmill is"); //Serial.println(previousMillis); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println(currentMillis-previousMillis); //this if statement means we are within range of wall (< 390 cm) for interval_2 time, "lights are blinking" if ((currentMillis - previousMillis_2 >= interval_2) && average >= stopdist+3) { //changed average >= stopdist to > stopdist //if 17 cm (default stopdist or farther from wall for 1 second, prev becomes current, added +3 due to issue of light turning on when car parked previousMillis_2 = currentMillis; } //Serial.println("prevmill_2 is"); //Serial.println(previousMillis_2); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println("prevmill_2 is"); //Serial.println(previousMillis_2); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println(currentMillis - previousMillis_2); if (average > stopdist) // { // if (average < 65) if (average < stopdist_plus_45) { digitalWrite(LED_Yield, HIGH); } } if (average >= stopdist) { digitalWrite(LED_STOP, LOW); } } if (average < 10) //was 10/2 { digitalWrite(ultrasonic_power, LOW); digitalWrite(LED_Yield, LOW); digitalWrite(LED_STOP, LOW); delay(950); //works, added 11/8/17 digitalWrite(ultrasonic_power, HIGH); delay(50); } }</p>
Enter Low Power Mode
I used a low power library found on the sparkfun website in order to put the arduino to sleep and conserve power.
https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption
No analog pins are used in this sketch, so I disabled the analog pins using code found from this site:
http://www.fiz-ix.com/2012/11/save-power-by-disabling-arduino-peripherals/
<p>if ((currentMillis - previousMillis_2) > 15000) //was 7500<br> { for (byte i = 0; i < 1; ++i) //wait to check every ~20 s { digitalWrite(ultrasonic_power, LOW); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); digitalWrite(LED_STOP, LOW); digitalWrite(LED_Yield, LOW); } Serial.println("just left low power"); }</p>
In further attempt to save power, I turn the ultrasonic pin which powers the ultrasonic sensor off, when not in use as seen above and below here:
<p>if (average < 10) //was 10/2<br> { digitalWrite(ultrasonic_power, LOW); digitalWrite(LED_Yield, LOW); digitalWrite(LED_STOP, LOW); delay(950); //works, added 11/8/17 digitalWrite(ultrasonic_power, HIGH); delay(50); }</p>
Now That All the Steps Are Completed, We Need to Integrate the Code
Integrated Code:
I used an arduino nano to run this code. Watch out for some arduino clones as they may consume more power than genuine arduinos. Make sure the NewPing and LowPower libraries are installed and copy and paste this code into Arduino IDE!
If you're unsure how to get Arduino IDE, follow the tutorial here: https://learn.sparkfun.com/tutorials/installing-arduino-ide
/*By Patrick B. Contributors/Sources used in Code: http://playground.arduino.cc/Code/NewPing https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption http://www.fiz-ix.com/2012/11/save-power-by-disabling-arduino-peripherals/ https://www.arduino.cc/en/Tutorial/Smoothing https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */ #include <NewPing.h> //http://playground.arduino.cc/Code/NewPing #include <LowPower.h> //added low power library from sparkfun https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. #define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters). was 400, max 500 was 500/2 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. // Define the number of samples to keep track of. The higher the number, // the more the readings will be smoothed, but the slower the output will // respond to the input. Using a constant rather than a normal variable lets // use this value to determine the size of the readings array. const int numReadings = 10; //was 10 int readings[numReadings]; // the readings from the analog input int readIndex = 0; // the index of the current reading int total = 0; // the running total int average = 0; // the average int LED_STOP = 6; //Declare stop light int LED_Yield = 7;// the number of the LED pin int dist = 0; //Declare dist variable int stopdist = 17; //declare stopping distance in cm (dist when Red LED turns on) int stopdist_plus_7 = stopdist+7; //declare distance when yellow LED stops blinking and becomes solid int ultrasonic_power = 3; //add 1.5 in to desired distance in order to account for casing // 1in --> 2.5 in --> 6 cm // 2in --> 3.5 in --> 9 cm // 3in --> 4.5 in --> 11 cm // 4in --> 5.5 in --> 14 cm // 5in --> 6.5 in --> 17 cm // 6in --> 7.5 in --> 19 cm // 7in --> 8.5 in --> 22 cm // 8in --> 9.5 in --> 24 cm // 9in --> 10.5 in -->27 cm // 10in -->11.5 in -->29 cm // 11in -->12.5 in -->32 cm // 12in -->13.5 in -->34 cm // 13in -->14.5 in -->37 cm // 14in -->15.5 in -->39 cm // 15in -->16.5 in -->42 cm // 16in -->17.5 in -->44 cm // Variables will change : int ledState = LOW; // ledState used to set the LED // Generally, you should use "unsigned long" for variables that hold time // The value will quickly become too large for an int to store unsigned long previousMillis = 0; // will store last time LED was updated unsigned long previousMillis_2 = 0; // constants won't change : const long interval = average; //was 850/3 // interval at which to blink (milliseconds) const long interval_2 = 1; // was 1000/2interval for turning off LEDs divide by 2 for 8mhz clock speed, else dont for 16, decreased interval_2 size to 100 to account for walking in front of sensor unsigned long time; void setup() { Serial.begin(57600); // Open serial monitor at 115200 baud to see ping results. // set the digital pin as output: pinMode(ultrasonic_power, OUTPUT); pinMode(LED_Yield, OUTPUT); pinMode(LED_STOP, OUTPUT); digitalWrite(LED_Yield, HIGH); //Yellow LED WORKS digitalWrite(LED_STOP, HIGH); //Red LED WORKS delay(1000); digitalWrite(LED_Yield, LOW); digitalWrite(LED_STOP, LOW); delay(500); digitalWrite(LED_Yield, HIGH); digitalWrite(LED_STOP, HIGH); delay(1000); //low power measures 11/8/17 //from http://www.fiz-ix.com/2012/11/save-power-by-disabling-arduino-peripherals/ // Disable the ADC by setting the ADEN bit (bit 7) of the // ADCSRA register to zero. ADCSRA = ADCSRA & B01111111; // Disable the analog comparator by setting the ACD bit // (bit 7) of the ACSR register to one. ACSR = B10000000; // Disable digital input buffers on all analog input pins // by setting bits 0-5 of the DIDR0 register to one. // Of course, only do this if you are not using the analog // inputs for your project. DIDR0 = DIDR0 | B00111111; } void loop() { const long interval = average/1; //yellow LED blinking interval digitalWrite(ultrasonic_power, HIGH); delay(50); digitalWrite(ultrasonic_power, HIGH); //sensor smoothing code: https://www.arduino.cc/en/Tutorial/Smoothing // subtract the last reading: total = total - readings[readIndex]; // read from the sensor: readings[readIndex] = dist; // add the reading to the total: total = total + readings[readIndex]; // advance to the next position in the array: readIndex = readIndex + 1; // if we're at the end of the array... if (readIndex >= numReadings) { // ...wrap around to the beginning: readIndex = 0; } // calculate the average: average = (total / numReadings); // send it to the computer as ASCII digits // Serial.println(average); delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range) dist = uS / US_ROUNDTRIP_CM; //did div by 2 in prescaler update Serial.println("cm"); // Serial.print(average); // check to see if it's time to blink the LED; that is, if the // difference between the current time and last time you blinked // the LED is bigger than the interval at which you want to // blink the LED. unsigned long currentMillis = millis(); if (average > 10 && average <= stopdist) // { if (average < stopdist && (currentMillis - previousMillis_2 < 10000))//was 4500 //if less than 17cm (default stopdist) and close to wall for less than 10 s turn on light { if (average > 10) // was 10 { digitalWrite(LED_STOP, HIGH); delay(1000); //changed, was 2500 } else { digitalWrite(LED_STOP, LOW); } } if ((currentMillis - previousMillis_2) > 15000) //was 7500 { for (byte i = 0; i < 1; ++i) //wait to start detection again ~20s after car left parking spot { //digitalWrite(ultrasonic_power, LOW); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); digitalWrite(LED_STOP, LOW); digitalWrite(LED_Yield, LOW); } Serial.println("just left low power"); } } else { //Following code in if statement modified from https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay //if (average > 65) //added nested if statement if (average > stopdist_plus_7) //was 45 then 45/2 { if (average < 390) //was 390 then 300 was 450/2 { if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } // set the LED with the ledState of the variable: digitalWrite(LED_Yield, ledState); } } } //Serial.println("prevmill is"); //Serial.println(previousMillis); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println(currentMillis-previousMillis); //this if statement means we are within range of wall (< 390 cm) for interval_2 time, lights are blinking if ((currentMillis - previousMillis_2 >= interval_2) && average >= stopdist+3) { //changed average >= stopdist to > stopdist //if 17 cm (default stopdist) or farther from wall for 1 second, prev becomes current, added +3 due to issue of light turning on when car parked previousMillis_2 = currentMillis; } //Serial.println("prevmill_2 is"); //Serial.println(previousMillis_2); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println("prevmill_2 is"); //Serial.println(previousMillis_2); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println(currentMillis - previousMillis_2); if (average > stopdist) // { // if (average < 65) if (average < stopdist_plus_7) { digitalWrite(LED_Yield, HIGH); } } if (average >= stopdist) { digitalWrite(LED_STOP, LOW); } } if (average < 10) //was 10/2 { //digitalWrite(ultrasonic_power, LOW); digitalWrite(LED_Yield, LOW); digitalWrite(LED_STOP, LOW); delay(950); //works, added 11/8/17 digitalWrite(ultrasonic_power, HIGH); delay(50); } }
Nuances:
Delays are needed after the ultrasonic sensor is turned on and off.
Hardware Checks/Casing and Circuitry
![20170823_115018.jpg](/proxy/?url=https://content.instructables.com/FEA/CS7I/JASJLHHK/FEACS7IJASJLHHK.jpg&filename=20170823_115018.jpg)
![20171205_143104.jpg](/proxy/?url=https://content.instructables.com/FNH/AO8T/JASJPXNA/FNHAO8TJASJPXNA.jpg&filename=20171205_143104.jpg)
![20171205_154153.jpg](/proxy/?url=https://content.instructables.com/F5T/3IGZ/JASJPYD1/F5T3IGZJASJPYD1.jpg&filename=20171205_154153.jpg)
![20171205_153048.jpg](/proxy/?url=https://content.instructables.com/F7V/UKLV/JASJPXZ3/F7VUKLVJASJPXZ3.jpg&filename=20171205_153048.jpg)
![20171205_151440.jpg](/proxy/?url=https://content.instructables.com/FKG/GKB9/JASJPXPF/FKGGKB9JASJPXPF.jpg&filename=20171205_151440.jpg)
![20171205_154023.jpg](/proxy/?url=https://content.instructables.com/FOI/XZV1/JASJPY7W/FOIXZV1JASJPY7W.jpg&filename=20171205_154023.jpg)
Make sure that the ultrasonic sensor is exactly parallel to the incoming surface of the car. I've also done a bit of prototyping to find a casing that looks nice and supports the sensor and arduino. For the casing, I used foam board. I've added 1.5 in (~3.81 cm) to the stop distance in order to account for the thickness of the casing surrounding the ultrasonic sensor.
Only 2 LEDs, one 200ohm resistor, 4 jumper wires, an arduino, a breadboard and an ultrasonic sensor are needed for this project.
Ultrasonic Sensor to Arduino Pin Assignments:
Trigger Pin ---> Pin 12
Echo Pin ------> Pin 11
Vcc--------------> Pin 3
GND ------------> GND
LED Pin Assignments: (Using a breadboard connect the GND Pin of the Red and Yellow LEDs to GND of the arduino to use only one ground pin in the arduino and reserve the other for the ultrasonic sensor)
Use a 220 ohm resistor for many 2 V LEDs as seen here: https://www.arduino.cc/en/Tutorial/Blink?from=Tutorial.BlinkingLED
Red LED-------> Pin 6
Yellow LED ---> Pin 7
I used a 200 ohm resistor for 2V, 20mA LEDs and it worked fine. Please see my photo for more detailed circuitry and calculations. Given that an LED is not ohmic, I wasn't 100% sure how to account for the dimming I noticed when both LEDs connected to the same ground are on at the same time. I hypothesize that it could be (I^2)R heating losses due to increased current coming from each LED since the current would pass through the same resistor. If anyone could provide insight on this, that would be appreciated. If this is the case, then the mimimum resistance needed is 3V/.04A = 75 ohms. This is less than the 150 ohm resistance that was needed for 1 LED to operate at its rated amperage.
Once this is done, make sure the NewPing and LowPower libraries are installed, upload the code and you're on your way to using a cool simple automated parking device! Perhaps you too could make it for your family or friends! I'd love to see others make this device too!
If you know how to make efficient plastic or cardboard casing or custom designed circuits, please let me know. I know that the arduino is a prototyping board so it would be neat to see what the next level of boards looks like.
Thank you Instructables for allowing the world wide sharing of ideas!
Updates
![20180224_133944.jpg](/proxy/?url=https://content.instructables.com/F3Y/CO3F/JE4KLNPB/F3YCO3FJE4KLNPB.jpg&filename=20180224_133944.jpg)
![3D Printing Casing](/proxy/?url=https://content.instructables.com/F6R/2BMU/JE4KLNQE/F6R2BMUJE4KLNQE.jpg&filename=3D Printing Casing)
The new STOP Sensor code is more power efficient and easier to use. The casing is also sturdier. More details soon...
Updated Code V7.1
/*
By Patrick B. Contributors/Sources used in Code: http://playground.arduino.cc/Code/NewPing https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption http://www.fiz-ix.com/2012/11/save-power-by-disabling-arduino-peripherals/ https://www.arduino.cc/en/Tutorial/Smoothing https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */ #include <NewPing.h> //http://playground.arduino.cc/Code/NewPing #include <LowPower.h> //added low power library from sparkfun https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. #define MAX_DISTANCE 500 // Maximum distance we want to ping for (in centimeters). was 400, max 500 was 500/2, works best at 500 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. // Define the number of samples to keep track of. The higher the number, // the more the readings will be smoothed, but the slower the output will // respond to the input. Using a constant rather than a normal variable lets // use this value to determine the size of the readings array. const int numReadings = 5; //was 10 int readings[numReadings]; // the readings from the analog input int readIndex = 0; // the index of the current reading int total = 0; // the running total int average = 0; // the average int LED_STOP = 6; //Declare stop light int LED_Yield = 7;// the number of the LED pin int dist = 0; //Declare dist variable int stopdist = 17; //declare stopping distance in cm (dist when Red LED turns on) int stopdist_plus_7 = stopdist+7; //declare distance when yellow LED stops blinking and becomes solid int ultrasonic_power = 3; //add 1.5 in to desired distance in order to account for casing // 1in --> 2.5 in --> 6 cm // 2in --> 3.5 in --> 9 cm // 3in --> 4.5 in --> 11 cm // 4in --> 5.5 in --> 14 cm // 5in --> 6.5 in --> 17 cm // 6in --> 7.5 in --> 19 cm // 7in --> 8.5 in --> 22 cm // 8in --> 9.5 in --> 24 cm // 9in --> 10.5 in -->27 cm // 10in -->11.5 in -->29 cm // 11in -->12.5 in -->32 cm // 12in -->13.5 in -->34 cm // 13in -->14.5 in -->37 cm // 14in -->15.5 in -->39 cm // 15in -->16.5 in -->42 cm // 16in -->17.5 in -->44 cm // Variables will change : int ledState = LOW; // ledState used to set the LED // Generally, you should use "unsigned long" for variables that hold time // The value will quickly become too large for an int to store unsigned long previousMillis = 0; // will store last time LED was updated unsigned long previousMillis_2 = 0; // constants won't change : const long interval = average; //was 850/3 // interval at which to blink (milliseconds) const long interval_2 = 1; // was 1000/2interval for turning off LEDs divide by 2 for 8mhz clock speed, else dont for 16, decreased interval_2 size to 100 to account for walking in front of sensor unsigned long time; void setup() { Serial.begin(57600); // Open serial monitor at 115200 baud to see ping results. // set the digital pin as output: pinMode(ultrasonic_power, OUTPUT); pinMode(LED_Yield, OUTPUT); pinMode(LED_STOP, OUTPUT); digitalWrite(LED_Yield, HIGH); //Yellow LED WORKS digitalWrite(LED_STOP, HIGH); //Red LED WORKS delay(1000); digitalWrite(LED_Yield, LOW); digitalWrite(LED_STOP, LOW); delay(500); digitalWrite(LED_Yield, HIGH); digitalWrite(LED_STOP, HIGH); delay(1000); //low power measures 11/8/17 //from http://www.fiz-ix.com/2012/11/save-power-by-disabling-arduino-peripherals/ // Disable the ADC by setting the ADEN bit (bit 7) of the // ADCSRA register to zero. ADCSRA = ADCSRA & B01111111; // Disable the analog comparator by setting the ACD bit // (bit 7) of the ACSR register to one. ACSR = B10000000; // Disable digital input buffers on all analog input pins // by setting bits 0-5 of the DIDR0 register to one. // Of course, only do this if you are not using the analog // inputs for your project. DIDR0 = DIDR0 | B00111111; } void loop() { const long interval = average/1; //yellow LED blinking interval digitalWrite(ultrasonic_power, HIGH); delay(100); // digitalWrite(ultrasonic_power, HIGH); //sensor smoothing code: https://www.arduino.cc/en/Tutorial/Smoothing // subtract the last reading: total = total - readings[readIndex]; // read from the sensor: readings[readIndex] = dist; // add the reading to the total: total = total + readings[readIndex]; // advance to the next position in the array: readIndex = readIndex + 1; // if we're at the end of the array... if (readIndex >= numReadings) { // ...wrap around to the beginning: readIndex = 0; } // calculate the average: average = (total / numReadings); // send it to the computer as ASCII digits // Serial.println(average); delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range) dist = uS / US_ROUNDTRIP_CM; //did div by 2 in prescaler update Serial.println("cm"); // Serial.print(average); // check to see if it's time to blink the LED; that is, if the // difference between the current time and last time you blinked // the LED is bigger than the interval at which you want to // blink the LED. unsigned long currentMillis = millis(); if (average > 10 && average <= stopdist) // { if (average < stopdist && (currentMillis - previousMillis_2 < 10000))//was 4500 //if less than 17cm (default stopdist) and close to wall for less than 10 s turn on light { if (average > 10) // was 10 { digitalWrite(LED_STOP, HIGH); delay(1000); //changed, was 2500 } else { digitalWrite(LED_STOP, LOW); } } if ((currentMillis - previousMillis_2) > 15000) //was 7500 { digitalWrite(ultrasonic_power, LOW); delay(100); for (byte i = 0; i < 2; ++i) //wait to start detection again ~20s after car left parking spot {LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); digitalWrite(LED_STOP, LOW); digitalWrite(LED_Yield, LOW); } Serial.println("just left low power"); digitalWrite(ultrasonic_power, HIGH); delay(100); } } else { //Following code in if statement modified from https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay //if (average > 65) //added nested if statement if (average > stopdist_plus_7) //was 45 then 45/2 { if (average < 390) //was 390 then 300 was 450/2 { if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } // set the LED with the ledState of the variable: digitalWrite(LED_Yield, ledState); } } } //Serial.println("prevmill is"); //Serial.println(previousMillis); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println(currentMillis-previousMillis); //this if statement means we are within range of wall (< 390 cm) for interval_2 time, lights are blinking if ((currentMillis - previousMillis_2 >= interval_2) && average >= stopdist+3) { //changed average >= stopdist to > stopdist //if 17 cm (default stopdist) or farther from wall for 1 second, prev becomes current, added +3 due to issue of light turning on when car parked previousMillis_2 = currentMillis; } //Serial.println("prevmill_2 is"); //Serial.println(previousMillis_2); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println("prevmill_2 is"); //Serial.println(previousMillis_2); //Serial.println("currentmill is"); //Serial.println(currentMillis); //Serial.println(currentMillis - previousMillis_2); if (average > stopdist) // { // if (average < 65) if (average < stopdist_plus_7) { digitalWrite(LED_Yield, HIGH); } } if (average >= stopdist) { digitalWrite(LED_STOP, LOW); } } if (average < 10) //was 10/2 { digitalWrite(ultrasonic_power, LOW); delay(100); digitalWrite(LED_Yield, LOW); digitalWrite(LED_STOP, LOW); delay(100); //works, added 11/8/17 was 300 LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //was not here before digitalWrite(ultrasonic_power, HIGH); delay(100); } }