Skip to content

Commit a0c5ad6

Browse files
authored
Create Flora_GPS_Jacket.ino
1 parent 5218936 commit a0c5ad6

1 file changed

Lines changed: 346 additions & 0 deletions

File tree

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
// Flora GPS + LED Pixel Code
2+
//
3+
// This code shows how to listen to the GPS module in an interrupt
4+
// which allows the program to have more 'freedom' - just parse
5+
// when a new NMEA sentence is available! Then access data when
6+
// desired.
7+
//
8+
// Tested and works great with the Adafruit Flora GPS module
9+
// ------> http://adafruit.com/products/1059
10+
// Pick one up today at the Adafruit electronics shop
11+
// and help support open source hardware & software! -ada
12+
13+
#include <Adafruit_GPS.h>
14+
#include <SoftwareSerial.h>
15+
#include "Adafruit_FloraPixel.h"
16+
Adafruit_GPS GPS(&Serial1);
17+
18+
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
19+
// Set to 'true' if you want to debug and listen to the raw GPS sentences
20+
#define GPSECHO false
21+
22+
// this keeps track of whether we're using the interrupt
23+
// off by default!
24+
boolean usingInterrupt = false;
25+
26+
//--------------------------------------------------|
27+
// WAYPOINTS |
28+
//--------------------------------------------------|
29+
//Please enter the latitude and longitude of your |
30+
//desired destination: |
31+
#define GEO_LAT 44.995012
32+
#define GEO_LON -93.228967
33+
//--------------------------------------------------|
34+
35+
//--------------------------------------------------|
36+
// DISTANCE |
37+
//--------------------------------------------------|
38+
//Please enter the distance (in meters) from your |
39+
//destination that you want your LEDs to light up: |
40+
#define DESTINATION_DISTANCE 20
41+
//--------------------------------------------------|
42+
43+
44+
// Navigation location
45+
float targetLat = GEO_LAT;
46+
float targetLon = GEO_LON;
47+
48+
// Trip distance
49+
float tripDistance;
50+
51+
boolean isStarted = false;
52+
53+
// Set the first variable to the NUMBER of pixels. 25 = 25 pixels in a row
54+
Adafruit_FloraPixel strip = Adafruit_FloraPixel(2);
55+
56+
57+
uint8_t LED_Breathe_Table[] = { 80, 87, 95, 103, 112, 121, 131, 141, 151, 161, 172, 182, 192, 202, 211, 220,
58+
228, 236, 242, 247, 251, 254, 255, 255, 254, 251, 247, 242, 236, 228, 220, 211,
59+
202, 192, 182, 172, 161, 151, 141, 131, 121, 112, 103, 95, 87, 80, 73, 66,
60+
60, 55, 50, 45, 41, 38, 34, 31, 28, 26, 24, 22, 20, 20, 20, 20,
61+
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
62+
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 22, 24, 26, 28,
63+
31, 34, 38, 41, 45, 50, 55, 60, 66, 73 };
64+
65+
66+
#define BREATHE_TABLE_SIZE (sizeof(LED_Breathe_Table))
67+
#define BREATHE_CYCLE 5000 /*breathe cycle in milliseconds*/
68+
#define BREATHE_UPDATE (BREATHE_CYCLE / BREATHE_TABLE_SIZE)
69+
uint32_t lastBreatheUpdate = 0;
70+
uint8_t breatheIndex = 0;
71+
72+
void setup()
73+
{
74+
// connect at 115200 so we can read the GPS fast enough and echo without dropping chars
75+
// also spit it out
76+
Serial.begin(115200);
77+
78+
// 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
79+
GPS.begin(9600);
80+
81+
// uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
82+
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
83+
// uncomment this line to turn on only the "minimum recommended" data
84+
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
85+
// For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
86+
// the parser doesn't care about other sentences at this time
87+
88+
// Set the update rate
89+
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
90+
// For the parsing code to work nicely and have time to sort thru the data, and
91+
// print it out we don't suggest using anything higher than 1 Hz
92+
93+
delay(1000);
94+
// Ask for firmware version
95+
Serial1.println(PMTK_Q_RELEASE);
96+
97+
// Start up the LED strip
98+
strip.begin();
99+
100+
// Update the strip, to start they are all 'off'
101+
strip.show();
102+
}
103+
104+
uint32_t timer = millis();
105+
106+
void loop() // run over and over again
107+
{
108+
// read data from the GPS in the 'main loop'
109+
char c = GPS.read();
110+
// if you want to debug, this is a good time to do it!
111+
if (GPSECHO)
112+
if (c) Serial.print(c);
113+
114+
// if a sentence is received, we can check the checksum, parse it...
115+
if (GPS.newNMEAreceived()) {
116+
// a tricky thing here is if we print the NMEA sentence, or data
117+
// we end up not listening and catching other sentences!
118+
// so be very wary if using OUTPUT_ALLDATA and trytng to print out data
119+
//Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
120+
121+
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
122+
return; // we can fail to parse a sentence in which case we should just wait for another
123+
}
124+
125+
126+
if (GPS.fix) {
127+
//Serial.print("Location: ");
128+
//Serial.print(GPS.latitude, 2); Serial.print(GPS.lat);
129+
//Serial.print(", ");
130+
//Serial.print(GPS.longitude, 2); Serial.println(GPS.lon);
131+
132+
float fLat = decimalDegrees(GPS.latitude, GPS.lat);
133+
float fLon = decimalDegrees(GPS.longitude, GPS.lon);
134+
135+
if (!isStarted) {
136+
isStarted = true;
137+
tripDistance = (double)calc_dist(fLat, fLon, targetLat, targetLon);
138+
}
139+
140+
//Uncomment below if you want your Flora to navigate to a certain destination. Then modify the headingDirection function.
141+
/*if ((calc_bearing(fLat, fLon, targetLat, targetLon) - GPS.angle) > 0) {
142+
headingDirection(calc_bearing(fLat, fLon, targetLat, targetLon)-GPS.angle);
143+
}
144+
else {
145+
headingDirection(calc_bearing(fLat, fLon, targetLat, targetLon)-GPS.angle+360);
146+
}*/
147+
148+
headingDistance((double)calc_dist(fLat, fLon, targetLat, targetLon));
149+
//Serial.print("Distance Remaining:"); Serial.println((double)calc_dist(fLat, fLon, targetLat, targetLon));
150+
151+
}
152+
//}
153+
154+
}
155+
156+
int calc_bearing(float flat1, float flon1, float flat2, float flon2)
157+
{
158+
float calc;
159+
float bear_calc;
160+
161+
float x = 69.1 * (flat2 - flat1);
162+
float y = 69.1 * (flon2 - flon1) * cos(flat1/57.3);
163+
164+
calc=atan2(y,x);
165+
166+
bear_calc= degrees(calc);
167+
168+
if(bear_calc<=1){
169+
bear_calc=360+bear_calc;
170+
}
171+
return bear_calc;
172+
}
173+
174+
void headingDirection(float heading)
175+
{
176+
//Use this part of the code to determine which way you need to go.
177+
//Remember: this is not the direction you are heading, it is the direction to the destination (north = forward).
178+
if ((heading > 348.75)||(heading < 11.25)) {
179+
Serial.println(" N");
180+
//Serial.println("Forward");
181+
}
182+
183+
if ((heading >= 11.25)&&(heading < 33.75)) {
184+
Serial.println("NNE");
185+
//Serial.println("Go Right");
186+
}
187+
188+
if ((heading >= 33.75)&&(heading < 56.25)) {
189+
Serial.println(" NE");
190+
//Serial.println("Go Right");
191+
}
192+
193+
if ((heading >= 56.25)&&(heading < 78.75)) {
194+
Serial.println("ENE");
195+
//Serial.println("Go Right");
196+
}
197+
198+
if ((heading >= 78.75)&&(heading < 101.25)) {
199+
Serial.println(" E");
200+
//Serial.println("Go Right");
201+
}
202+
203+
if ((heading >= 101.25)&&(heading < 123.75)) {
204+
Serial.println("ESE");
205+
//Serial.println("Go Right");
206+
}
207+
208+
if ((heading >= 123.75)&&(heading < 146.25)) {
209+
Serial.println(" SE");
210+
//Serial.println("Go Right");
211+
}
212+
213+
if ((heading >= 146.25)&&(heading < 168.75)) {
214+
Serial.println("SSE");
215+
//Serial.println("Go Right");
216+
}
217+
218+
if ((heading >= 168.75)&&(heading < 191.25)) {
219+
Serial.println(" S");
220+
//Serial.println("Turn Around");
221+
}
222+
223+
if ((heading >= 191.25)&&(heading < 213.75)) {
224+
Serial.println("SSW");
225+
//Serial.println("Go Left");
226+
}
227+
228+
if ((heading >= 213.75)&&(heading < 236.25)) {
229+
Serial.println(" SW");
230+
//Serial.println("Go Left");
231+
}
232+
233+
if ((heading >= 236.25)&&(heading < 258.75)) {
234+
Serial.println("WSW");
235+
//Serial.println("Go Left");
236+
}
237+
238+
if ((heading >= 258.75)&&(heading < 281.25)) {
239+
Serial.println(" W");
240+
//Serial.println("Go Left");
241+
}
242+
243+
if ((heading >= 281.25)&&(heading < 303.75)) {
244+
Serial.println("WNW");
245+
//Serial.println("Go Left");
246+
}
247+
248+
if ((heading >= 303.75)&&(heading < 326.25)) {
249+
Serial.println(" NW");
250+
//Serial.println("Go Left");
251+
}
252+
253+
if ((heading >= 326.25)&&(heading < 348.75)) {
254+
Serial.println("NWN");
255+
//Serial.println("Go Left");
256+
}
257+
}
258+
259+
void headingDistance(float fDist)
260+
{
261+
//Use this part of the code to determine how far you are away from the destination.
262+
//The total trip distance (from where you started) is divided into five trip segments.
263+
Serial.println(fDist);
264+
if ((fDist >= DESTINATION_DISTANCE)) { // You are now within 5 meters of your destination.
265+
//Serial.println("Trip Distance: 1");
266+
//Serial.println("Arrived at destination!");
267+
int i;
268+
for (i=0; i < strip.numPixels(); i++) {
269+
strip.setPixelColor(i, 0, 0, 0);
270+
}
271+
strip.show(); // write all the pixels out
272+
}
273+
274+
275+
if ((fDist < DESTINATION_DISTANCE)) { // You are now within 5 meters of your destination.
276+
//Serial.println("Trip Distance: 0");
277+
//Serial.println("Arrived at destination!");
278+
breath();
279+
}
280+
281+
}
282+
283+
unsigned long calc_dist(float flat1, float flon1, float flat2, float flon2)
284+
{
285+
float dist_calc=0;
286+
float dist_calc2=0;
287+
float diflat=0;
288+
float diflon=0;
289+
290+
diflat=radians(flat2-flat1);
291+
flat1=radians(flat1);
292+
flat2=radians(flat2);
293+
diflon=radians((flon2)-(flon1));
294+
295+
dist_calc = (sin(diflat/2.0)*sin(diflat/2.0));
296+
dist_calc2= cos(flat1);
297+
dist_calc2*=cos(flat2);
298+
dist_calc2*=sin(diflon/2.0);
299+
dist_calc2*=sin(diflon/2.0);
300+
dist_calc +=dist_calc2;
301+
302+
dist_calc=(2*atan2(sqrt(dist_calc),sqrt(1.0-dist_calc)));
303+
304+
dist_calc*=6371000.0; //Converting to meters
305+
return dist_calc;
306+
}
307+
308+
// Convert NMEA coordinate to decimal degrees
309+
float decimalDegrees(float nmeaCoord, char dir) {
310+
uint16_t wholeDegrees = 0.01*nmeaCoord;
311+
int modifier = 1;
312+
313+
if (dir == 'W' || dir == 'S') {
314+
modifier = -1;
315+
}
316+
317+
return (wholeDegrees + (nmeaCoord - 100.0*wholeDegrees)/60.0) * modifier;
318+
}
319+
320+
void breath()
321+
{
322+
uniformBreathe(LED_Breathe_Table, BREATHE_TABLE_SIZE, BREATHE_UPDATE, 127, 127, 127);
323+
}
324+
325+
void uniformBreathe(uint8_t* breatheTable, uint8_t breatheTableSize, uint16_t updatePeriod, uint16_t r, uint16_t g, uint16_t b)
326+
{
327+
int i;
328+
329+
uint8_t breatheBlu;
330+
331+
if ((millis() - lastBreatheUpdate) > updatePeriod) {
332+
lastBreatheUpdate = millis();
333+
334+
335+
for (i=0; i < strip.numPixels(); i++) {
336+
breatheBlu = (b * breatheTable[breatheIndex]) / 256;
337+
strip.setPixelColor(i, 0, 0, breatheBlu);
338+
}
339+
strip.show();
340+
341+
breatheIndex++;
342+
if (breatheIndex > breatheTableSize) {
343+
breatheIndex = 0;
344+
}
345+
}
346+
}

0 commit comments

Comments
 (0)