├── .gitignore ├── Arduino_Garage_Breadboard.pdf ├── README.md ├── TODO.txt └── src ├── Arduino Garage.ino └── ledring.ino /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | .pioenvs 6 | .piolibdeps 7 | .ini 8 | .yml 9 | -------------------------------------------------------------------------------- /Arduino_Garage_Breadboard.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rvrickv/Arduino-Garage/7ad4ce1c6bad06ad1f63b194e5100ddd98a2ddfc/Arduino_Garage_Breadboard.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino-Garage 2 | Parking distance sensor using ESP8266, HC-SR04, and Addressable LED strips/rings 3 | 4 | I started this project to solve a personal issue -- parking the car just right so that I have space to walk around it in the garage while leaving a reasonable gap to the garage door. 5 | 6 | It started as a Python/Pi Zero project and now I have decided to port it to Arduino/ESP8266. Eventually I plan to move it to an ATTiny85 for an even smaller footprint/power profile. 7 | 8 | Two important notes: 9 | 1) I've got very limited coding skills 10 | 2) I have no idea what I'm doing 11 | 12 | So if you have a better way of doing some of this stuff, I'm totally open to suggestions. 13 | 14 | The biggest challenge so far is "noise" in the sensor data. They are rock solid with large/flat objects. But can struggle with curvy car shapes and especially with empty spaces or cluttered garages. I've tried many techniques to smooth the data but now am running into performance issues with the MCUs. It will likely be magnified with the ATTiny85. 15 | 16 | The code uses a few awesome libraries that made this project super easy. Among them: 17 | 18 | NewPing // sensor library. Much more flexible than the UltraSonic library in Arduino 19 | 20 | FastLED // library for controlling individually addressable LEDs 21 | 22 |

Usage

23 | 24 | Usage is simple. A parking distance is set by default (100cm). As the car approaches the sensor, the LED strip/ring fills with Green LEDs, until the parking position is reached, where the LEDs turn Red. 25 | 26 | After a few seconds parked (Red), the LEDs fade out. 27 | 28 | To change the distance, begin by parking your car at the intended parking distance. Put your hand over the sensor at about 5 cm. The LEDs will change to a rainbow pattern. Keep your hand over the sensor until a countdown starts. Move your hand out of the way, and the MCU will take several readings, and set the parking distance. The distance is written to EEPROM so it is not lost if power is cycled. 29 | 30 | That's it! 31 | 32 | I'll be adding schematics and more soon. 33 | 34 | Thanks for stopping by. 35 | 36 | rvrickv 37 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rvrickv/Arduino-Garage/7ad4ce1c6bad06ad1f63b194e5100ddd98a2ddfc/TODO.txt -------------------------------------------------------------------------------- /src/Arduino Garage.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "FastLED.h" 6 | #include "NewPing.h" 7 | 8 | //#include "QuickStats.h" // Used to calculate the mode if using Mode sampling. Slow, even on 8266 at 160 MHz. 9 | 10 | #define DATA_PIN D3 // Data pin for FastLED LED control 11 | #define TRIGGER D5 // Pin used to trigger HC-SR04 12 | #define ECHO D0 // Pin that receives unltrasound ping 13 | #define LED_TYPE NEOPIXEL // Type of LED pixels for FastLED 14 | #define NUM_LEDS 16 // Number of LEDs being used 15 | #define BRIGHTNESS 180 // How brignt will LESs appear. 16 | #define PARKING_DISTANCE 100 // Default parking distance 17 | #define MAX_DISTANCE 350 // Sensor is less precise at longer distances 18 | #define RESET_DISTANCE 5 // Distance that will trigger parking distance setting 19 | #define SAMPLE_READINGS 5 // Number of readings to increase precision 20 | #define TIME_TO_OFF 10000 // How long before LEDs go off 21 | 22 | CRGB leds[NUM_LEDS]; 23 | elapsedMillis timeElapsed; 24 | //QuickStats stats; 25 | 26 | bool parked = false; 27 | NewPing sensor(TRIGGER, ECHO, MAX_DISTANCE); 28 | 29 | uint16_t parking_distance = PARKING_DISTANCE; 30 | float readings[SAMPLE_READINGS]; 31 | 32 | void setup() { 33 | // Small delay to let eveerything get started 34 | delay(1000); 35 | 36 | FastLED.addLeds(leds, NUM_LEDS); 37 | FastLED.setBrightness(BRIGHTNESS); 38 | EEPROM.begin(2); 39 | Serial.begin(9600); 40 | Serial.println("Started"); 41 | led_off(); 42 | 43 | // Check to see if we have parking data in the eeprom 44 | uint16_t ee_distance = 0; 45 | 46 | // Query the parking distance from flash. If not 0, set 47 | // parking_distance to stored value. 48 | EEPROM.get(0,ee_distance); 49 | if (ee_distance){ parking_distance = ee_distance; Serial.println(parking_distance);} 50 | } 51 | 52 | 53 | void loop() { 54 | 55 | uint16_t distance = 0; 56 | 57 | // Mode sampling technique - slower but reduces outliers 58 | // Take n readings, store them in the array 59 | //for (int i=0; i 0 && distance <=RESET_DISTANCE) 92 | { 93 | parking_distance = reset_parking_distance(); 94 | //Serial.print("New Parking distance is: "); 95 | //Serial.println(parking_distance); 96 | } 97 | } 98 | else if (distance <= parking_distance) 99 | { 100 | if ((!parked) || (timeElapsed < TIME_TO_OFF)){ 101 | led_stop(); 102 | parked = true; 103 | } 104 | else if(parked && (timeElapsed >= TIME_TO_OFF) && leds[0].getLuma()) 105 | { 106 | led_fade_off(); //If lEDs are on after being parked for a few secs turn off 107 | } 108 | } 109 | else if (distance <= MAX_DISTANCE){ 110 | led_show_value(distance); 111 | parked = false; 112 | timeElapsed = 0; 113 | } 114 | delay(10); 115 | } 116 | 117 | uint16_t reset_parking_distance(){ 118 | 119 | led_countdown(); 120 | uint16_t new_distance = round_to_base(sensor.convert_cm(sensor.ping_median(25))); 121 | new_distance += 5; // a little buffer to ensure we're "Red" 122 | timeElapsed = 0; 123 | 124 | EEPROM.put(0,new_distance); // write the new distance to Flash 125 | EEPROM.commit(); 126 | 127 | return (new_distance); 128 | } 129 | 130 | uint16_t round_to_base(uint16_t value) 131 | { 132 | uint16_t base = 5; 133 | return uint16_t(base * round(float(value)/base)); 134 | } 135 | -------------------------------------------------------------------------------- /src/ledring.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void led_stop(){ 4 | //FastLED.showColor(CRGB::Red); 5 | fill_solid(&leds[0], 16,CRGB::Red); 6 | FastLED.show(); 7 | } 8 | 9 | void led_off(){ 10 | //FastLED.showColor(CRGB::Black); 11 | fill_solid(&leds[0], 16,CRGB::Black); 12 | FastLED.show(); 13 | } 14 | 15 | void led_show_value(uint16_t value){ 16 | uint8_t no_of_leds = map(value,parking_distance,MAX_DISTANCE,16,0); 17 | 18 | for (uint8_t led = 0; led<=no_of_leds; led++){leds[led] = CRGB::Green;} 19 | for (uint8_t led = NUM_LEDS - 1; led > no_of_leds; led--){leds[led] = CRGB::Black;} 20 | 21 | FastLED.show(); 22 | } 23 | 24 | void led_enter_setup() 25 | { 26 | // Blink 3 times 27 | for (int hue = 90; hue<255; hue++){ 28 | fill_rainbow( leds, NUM_LEDS, hue, 5); 29 | FastLED.show(); 30 | delay(20); 31 | } 32 | } 33 | 34 | void led_countdown() 35 | { 36 | fill_rainbow( leds, NUM_LEDS, 255, 5); 37 | FastLED.show(); 38 | delay(300); 39 | 40 | for (int i = NUM_LEDS-1; i>=0; i--) 41 | { 42 | leds[i] = CRGB::Black; 43 | FastLED.show(); 44 | delay(300); 45 | } 46 | } 47 | 48 | void led_fade_off(){ 49 | for (int i = 0; i < 255; i++){ 50 | for (int j = 0 ; j < NUM_LEDS; j++){leds[j].fadeToBlackBy(20);} 51 | FastLED.show(); 52 | if (!leds[0].getLuma()){ 53 | led_off(); 54 | break;} 55 | FastLED.delay(30); 56 | } 57 | 58 | } 59 | --------------------------------------------------------------------------------