FinduCar: a Smart Car Key Guiding People to Where the Car Is Parked
by Songlin in Circuits > Electronics
3384 Views, 33 Favorites, 0 Comments
FinduCar: a Smart Car Key Guiding People to Where the Car Is Parked
In order to solve the problems above, this project proposes to develop a smart car key which could direct people to where they parked the car. And my plan is integrating a GPS into the car key. There is no need to use the smartphone app to track the car, all the guidance will just show on the car key.
Paper Sketch
When people press the button to lock the car, the location information could be recorded in the microcontroller automatically. Then, when people start to navigate to the car, the different LED is lighted up to direct to the position of the car and blinking frequency shows the distance to the car. They can easily follow the blinking LED and quickly find the car.
Hardware List
These are the components used in this project. Some are from the particle kits(breadboard, button, headers), others are purchased from Adafruit official website( Adafruit Feather M0, Adafruit Ultimate GPS module , Lpoly Battery and Coin Cell Battery) and Amazon( NeoPixel Ring - 12 RGB LED).
Circuit Design
Neopixel_LED is connected to the PIN 6 of Feather M0
Button_Unlock is connected to the PIN 12 of Feather M0
Button_Lock is connected to the PIN 13 of Feather M0
Hardware Connection
Solder the headers with Adafruit M0 Feather, Adafruit Ultimate GPS Featherwing. Stack the two boards together. The GPS FeatherWing plugs right into your Feather M0 board without any more wires.
Software Design
Test Components
- Read a FIX
void setup() { Serial.println("GPS echo test"); Serial.begin(9600); Serial1.begin(9600); // default NMEA GPS baud }
void loop() { if (Serial.available()) { char c = Serial.read(); Serial1.write(c); } if (Serial1.available()) { char c = Serial1.read(); Serial.write(c); } }
- Blink LED Ring
See Adafruit NeoPixel Examples.
GPS Calculation Functions
- Calculate the Azimuth
// Calculate the Azimuth
double azimuth(double lat_a, double lon_a, double lat_b, double lon_b) { double d = 0; lat_a = lat_a*PI/180; lon_a = lon_a*PI/180; lat_b = lat_b*PI/180; lon_b = lon_b*PI/180; d = sin(lat_a)*sin(lat_b)+cos(lat_a)*cos(lat_b)*cos(lon_b-lon_a); d = sqrt(1-d*d); d = cos(lat_b)*sin(lon_b-lon_a)/d; d = asin(d)*180/PI; return d; }
- Calculate the time on the LED clock, which is also the direction of the vehicle
// Calculate the time on LED clock
int led_time(double angle){ int flag = 0; if (angle < 0){ flag = 1; } angle = abs(angle); double angle_remainder = fmod(angle, 30); int angle_time = (int)angle/30; if (angle_remainder >= 15) { angle_time = angle_time + 1; } if (flag == 1){ angle_time = 12 - angle_time; } return angle_time; }
- Calculate the distance between the person and his vehicle
// Calculate the Distance<br>
double distance(double lat_a, double lon_a, double lat_b, double lon_b) { double EARTH_RADIUS = 6378137.0; double radLat1 = (lat_a * PI / 180.0); double radLat2 = (lat_b * PI / 180.0); double a = radLat1 - radLat2; double b = (lon_a - lon_b) * PI / 180.0; double s = 2 * asin(sqrt(pow(sin(a / 2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b / 2), 2))); s = s * EARTH_RADIUS / 10000000; return s; }
LED Display Functions
- Light up LEDs in a circle showing that it starts to navigate
// LED ring lighting one by one shows that the navigation begins
void colorWipe(uint32_t c, uint8_t wait) { for(uint16_t i=0; i strip.setPixelColor(i, c); strip.show(); delay(wait); } }
- Get the LED frequency on the basis of the distance
// Get LED Frequency
int frequency(double distance){ int f = (int)distance * 20; return f; }
- Blink the certain LED indicating the direction of the car
//Display on LED
strip.clear(); strip.show(); delay(frequency(car_person_distance)); // delay(500); strip.setPixelColor(angle_time, strip.Color(0, 0, 255)); strip.show(); delay(frequency(car_person_distance)); // delay(500);
//Disable LED
if (button_flag == 1 && car_person_distance < 5.0){ button_flag = 0; led_flag = 1; strip.clear(); strip.show(); }
Main
#include Adafruit_GPS.h<br>#include Adafruit_NeoPixel.h #include HardwareSerial.h #include Button.h #include math.h
#define Neopixel_LED_PIN 6 #define Neopixel_LED_NUM 12 #define Button_Lock_PIN 13 #define Button_Unlock_PIN 12 #define GPSSerial Serial1 <p>#define GPSECHO false</p>
Adafruit_GPS GPS(&GPSSerial);<br>Adafruit_NeoPixel strip = Adafruit_NeoPixel(Neopixel_LED_NUM, Neopixel_LED_PIN, NEO_GRB + NEO_KHZ800); Button button_lock(Button_Lock_PIN); Button button_unlock(Button_Unlock_PIN); int button_flag = 0; int led_flag = 1; uint32_t timer = millis(); double car_lat, car_lon; double car_person_distance; double move_direction; double car_azimuth; double car_person_angle; int angle_time;
void setup() { Serial.begin(115200); // Serial1.begin(9600); GPS.begin(9600); // default NMEA GPS baud strip.begin(); // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // Set the update rate GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate // Request updates on antenna status, comment out to keep quiet // GPS.sendCommand(PGCMD_ANTENNA); delay(1000);}
void loop() {// if (Serial.available()) { // char c = Serial.read(); // Serial1.write(c); // } // if (Serial1.available()) { char c = GPS.read(); if (GPSECHO) if (c) Serial.print(c); // if a sentence is received, we can check the checksum, parse it... if (GPS.newNMEAreceived()) { // a tricky thing here is if we print the NMEA sentence, or data // we end up not listening and catching other sentences! // so be very wary if using OUTPUT_ALLDATA and trytng to print out data Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false return; // we can fail to parse a sentence in which case we should just wait for another } // if millis() or timer wraps around, we'll just reset it if (timer > millis()) timer = millis(); if (millis() - timer > 2000) { timer = millis(); // reset the timer Serial.print("\nTime: "); Serial.print(GPS.hour, DEC); Serial.print(':'); Serial.print(GPS.minute, DEC); Serial.print(':'); Serial.print(GPS.seconds, DEC); Serial.print('.'); Serial.println(GPS.milliseconds); Serial.print("Date: "); Serial.print(GPS.day, DEC); Serial.print('/'); Serial.print(GPS.month, DEC); Serial.print("/20"); Serial.println(GPS.year, DEC); Serial.print("Fix: "); Serial.print((int)GPS.fix); Serial.print(" quality: "); Serial.println((int)GPS.fixquality); if (GPS.fix) { Serial.print("Location: "); Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); Serial.print(", "); Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); Serial.print("Location (in degrees, works with Google Maps): "); Serial.print(GPS.latitudeDegrees, 4); Serial.print(", "); Serial.println(GPS.longitudeDegrees, 4); Serial.print("Speed (knots): "); Serial.println(GPS.speed); Serial.print("Angle: "); Serial.println(GPS.angle); Serial.print("Altitude: "); Serial.println(GPS.altitude); Serial.print("Satellites: "); Serial.println((int)GPS.satellites); // Save the GPS of the vehicle if (button_lock.read()) { car_lat = GPS.latitudeDegrees; car_lon = GPS.longitudeDegrees; //for debug Serial.print("carLatitude: "); Serial.println(car_lat); Serial.print("carLongitude: "); Serial.println(car_lon); } // Start to find the car if (button_flag == 0){ button_flag = button_unlock.read(); } if(button_flag == 1 && led_flag == 1){ colorWipe(strip.Color(0, 255, 0), 500); led_flag = 0; } if (button_flag == 1) { car_person_distance = distance(GPS.latitudeDegrees, GPS.longitudeDegrees, car_lat, car_lon); //Calculate the distance //car_person_distance = distance(100.0005, 100.0005, 100.0, 100.0); //for debug Serial.println(car_person_distance); move_direction = GPS.angle;//Record the moving direction(angle) //move_direction = 100.0; // Record the Azimuth(angle) car_azimuth = azimuth(GPS.latitudeDegrees, GPS.longitudeDegrees, car_lat, car_lon); //car_azimuth = azimuth(100.0005, 100.0005, 100.0, 100.0); // Calculate the time on LED clock car_person_angle = car_azimuth - move_direction; angle_time = led_time(car_person_angle); //Display on LED strip.clear(); strip.show(); // delay(frequency(car_person_distance)); delay(500); strip.setPixelColor(angle_time, strip.Color(0, 0, 255)); strip.show(); // delay(frequency(car_person_distance)); delay(500); //Disable LED if (button_flag == 1 && car_person_distance < 5.0){ button_flag = 0; led_flag = 1; strip.clear(); strip.show(); } } } // } } }
Debug on Breadboard
Hardware Assembly
Electronics Housing Design in Adobe Illustrator
Cardboard Prototype
This step is used to confirm the size of the housing and every piece of the model, making sure the box size, and the button position, and LED position fit the assembled electronic components.
Birch Plywood Prototype
This was the initial prototype. A square hole for plugging into a charger was added to one of the pieces finally.