Go Down

Topic: GPS EM 406 A - Arduino Demi. (Read 893 times) previous topic - next topic

hippo

ich habe eine box nach newbrightidea.com/?p=15 nachgebaut mit arduino, GPS EM 406 A, LCD, 2 Servos, welche die Schublade zum öffnen freigibt , wenn man im Umkreis von 5 km von den Zielkoordinaten ist. Mein Problem:
Mein Garmin GPS Emfänger zeigt am Standort:
49.45728 N 006.38368E an
Die Box zeigt an:
49.762241 N 006.639300E
Ist das ein Technische Fehler oder ein Einheiten Fehler oder sonst was?
Vielleicht hat jemand Erfahrung und kennt eine Antwort.

hippo

Der Code v. Herrn Weeks mit anderen Zielkoordinaten Zeile 25/26 ist:
001 #include <TinyGPS.h>  
002 #include <NewSoftSerial.h>  
003 #include <LiquidCrystal.h>  
004 #include <SoftwareServo.h>  
005 #include <math.h>  
006 #include <EEPROM.h>  
007 #include <avr/interrupt.h>  
013 #define RXPIN 2  
014 #define TXPIN 3  
016 #define POLULUPIN 5  
018 #define LIDPIN 6  
019 #define DRAWERPIN 4  
020 #define IRPINA 0  
022 #define EARTH_RADIUS 6378.1f  
023 #define DEG_TO_RAD 0.0174532925f  
025 #define TOFINO_LAT 49.122444f  
026 #define TOFINO_LON 125.900871f  
028 #define XXXX_LAT 0.0f  
029 #define XXXX_LON 0.0f  
031 #define HOME_LAT 64.0f  
032 #define HOME_LON 128.0f  
034 #define GPS_DELAY_MS 60000  
036 /* 5km is pretty generous, but  better safe than sorry, right? */
038 #define DIST_THRESHOLD 5.0f  
040 #define ADDR_TRIES 0  
041 #define ADDR_STAGE1 1  
042 #define ADDR_STAGE2 2  
043 #define ADDR_BACKDOOR 3  
045 TinyGPS gps;  
046 SoftwareServo drawerServo;  
047 SoftwareServo lidServo;  
049 /* Set up the NewSoftSerial to talk to the GPS */
050 NewSoftSerial nss(RXPIN,TXPIN);  
052 LiquidCrystal lcd(7, 8, 9, 10, 11, 12);  
054 unsigned long waitUntil;  
055 int attemptsRemaining;  
057 void setup() {  
058   pinMode(POLULUPIN, OUTPUT);  
059   Serial.begin(9600);  
060   Serial.print( "In setup.\n" );  
061   nss.begin(4800);  
062   lcd.begin(2,16);  
063   lcd.clear();  
064   lcd.setCursor(0,0);  
066   /* Check how many tries are left */
067   attemptsRemaining = EEPROM.read(ADDR_TRIES);  
068   Serial.print( "Attempts Remaining: " );  
069   Serial.print( attemptsRemaining, DEC );  
070   Serial.print("\n");  
071   if ( attemptsRemaining == 0xFF )  
072   {  
073     // First time through  
074 Serial.print( "First time through, initializing EEPROM\n" );  
075     initializeEEPROM();  
076     Serial.print( "Locking lid\n" );  
077     lockLid();  
078     shutdown();  
079   }  
080   lcd.print( " ...Loading..." );  
081 }  
083 void loop()  
084 {  
085   waitUntil = millis() + 2000;  
086   if ( waitForBackdoor() )  
087   {  
088     /* If we get here, then the backdoor was triggered */
089     unlockLid();  
090     shutdown();  
091   }  
092   else if ( EEPROM.read( ADDR_BACKDOOR ) != 0 )  
093 {  
094     // clear the backdoor flag, if it was set from a previous  
095     // run.  this lets us try to unlock the backdoor multiple times  
096     // in case the first try jammed or something.  
097     lockLid();  
098     EEPROM.write( ADDR_BACKDOOR, 0 );  
099     shutdown();  
100   }  
102   if ( attemptsRemaining <= 0 )  
103   {  
104     lcd.clear();  
105     lcd.setCursor(0,0);  
106     lcd.print( " No More Tries!" );  
107     delay(5000);  
108     lcd.clear();  
109     lcd.setCursor(0,0);  
110     lcd.print( "   Return to" );  
111     lcd.setCursor(0,1);  
112     lcd.print( "     Russ" );  
113     delay(5000);  
114     shutdown();  
115   }  
117   // ... Normal Operation begins here  
118   bool stage1Complete = (EEPROM.read(ADDR_STAGE1) != 0);  
119   bool stage2Complete = (EEPROM.read(ADDR_STAGE2) != 0);  
121   waitUntil = millis() + 120000;  
122   if ( !stage1Complete )  
123   {  
124     lcd.clear();  
125     lcd.setCursor(0,0);  
126     lcd.print( " Searching  for " );  
127     lcd.setCursor(0,1);  
128     lcd.print( "     Signal     " );  
129     float stage1Dist = 100.0f;  
130     if ( distanceTo( TOFINO_LAT, TOFINO_LON, &stage1Dist ) )  
131     {  
132  /* If we get here, we received a valid distance measurement */
133       if ( stage1Dist < DIST_THRESHOLD )  
134       {  
135         EEPROM.write( ADDR_STAGE1, 0xFF );  
136         lcd.clear();  
137         lcd.setCursor(0,0);  
138         lcd.print( "Stage One" );  
139         lcd.setCursor(0,1);  
140         lcd.print( "Complete!");  
141         unlockDrawer();  
142       }  
143       else
144       {  
145         /* Sorry, try again */
146         decrAttemptsRemaining();  
147         lcd.clear();  
148         lcd.setCursor(0,0);  
149         lcd.print( "Access Denied!" );  
150         lcd.setCursor(0,1);  
151         lcd.print( attemptsRemaining );  
152         lcd.print( " tries left" );  
153         delay(25000);  
154         lcd.clear();  
155         lcd.setCursor(0,0);  
156         lcd.print( "Out of Range" );  
157         lcd.setCursor(0,1);  
158         lcd.print( stage1Dist );  
159         lcd.print( " km" );  
160       }  
161       delay(25000);  
162       shutdown();  
163     }  
164     else
165     {  
166       /* We never received a good GPS signal */
167       failNoSignal();  
168     }  
169   }  
170   else if ( !stage2Complete )  
171   {  
172     /* This chunk of code is just different enough from stage 1  
173        to make it awkward to write in a loop. */
174     lcd.clear();  
175     lcd.setCursor(0,0);  
176     lcd.print( " Searching  for " );  
177     lcd.setCursor(0,1);  
178     lcd.print( "     Signal     " );  
179     float stage2Dist = 100.0f;  
180     if ( distanceTo( XXXX_LAT, XXXX_LON, &stage2Dist ) )  
181     {  
182       if ( stage2Dist < DIST_THRESHOLD )  
183       {  
184         EEPROM.write( ADDR_STAGE2, 0xFF );  
185         lcd.clear();  
186         lcd.setCursor(0,0);  
187         lcd.print( "Stage Two" );  
188         lcd.setCursor(0,1);  
189         lcd.print( "Complete!" );  
190         unlockLid();  
191       }  
192       else
193       {  
194         decrAttemptsRemaining();  
195         lcd.clear();  
196         lcd.setCursor(0,0);  
197         lcd.print( "Access Denied!" );  
198         lcd.setCursor(0,1);  
199         lcd.print( attemptsRemaining );  
200         lcd.print( " tries left" );  
201         delay(25000);  
202         lcd.clear();  
203         lcd.setCursor(0,0);  
204         lcd.print( "Out of Range" );  
205         lcd.setCursor(0,1);  
206         if ( stage2Dist < 10 )  
207         {  
208           lcd.print( "? km" );  
209         }  
210         else if ( stage2Dist < 100 )  
211         {  
212           lcd.print( "?? km" );  
213         }  
214         else if (stage2Dist < 1000 )  
215         {  
216           lcd.print( "??? km" );  
217         }  
218         else
219         {  
220           lcd.print( "???? km" );  
221         }  
222       }  
223       delay(25000);  
224       shutdown();  
225     }  
226     else
227     {  
228       failNoSignal();  
229     }  
230   }  
231   else
232   {  
233     // Game Over!  
234     lcd.clear();  
235     lcd.setCursor(0,0);  
236     lcd.print( "      Game" );  
237     lcd.setCursor(0,1);  
238     lcd.print( "      Over!" );  
239     delay(10000);  
240     shutdown();  
241   }  
242   // We should never get here, but just in case...  
243   shutdown();  
244 }  
246 /*  
247  * Tries to calculate the distance to the specified lat+lon, using the GPS sensor.  
248  * Returns true iff the sensor returned a valid reading.  
249  * On successful return, result will hold the great circle distance to the specified point.  
250  */
251 bool distanceTo( float targetLat, float targetLon, float* result)  
252 {  
253   int numFixes = 0;  
254   while ( millis() < waitUntil )  
255   {  
256     if (nss.available())  
257     {  
258       int c = nss.read();  
259       if (gps.encode(c))  
260       {  
261         unsigned long fix_age;  
262         float flat,flon;  
263         gps.f_get_position(&flat, &flon, &fix_age);  
264         if ( fix_age > 60000 ) continue;  
265         if ( numFixes < 5 )  
266         {  
267           numFixes++;  
268           continue;  
269         }  
270         flat = fabs(flat);  
271         flon = fabs(flon);  
273         float dist = gcd( flat * DEG_TO_RAD, flon * DEG_TO_RAD, targetLat * DEG_TO_RAD, targetLon * DEG_TO_RAD );  
274         *result = dist;  
275         return true;  
276       }  
277     }  
278   }  
279   return false;  
280 }  
282 /*  
283  * This is a super-kludge to turn off all pin-change interrupts. 284  * It will disable all serial functionality.  Pretty much the  285  * only way to restore the Arduino to a usable state after calling this  286  * function is to cut the power and reboot.  Which is a little tricky to do  287  * if you're running on USB _and_ a battery pack.  288  *  
289  * I use this as a hack to get NewSoftSerial and SoftwareServo to play nice  290  * with each other, but I think that the latest version of NewSoftSerial has  291  * a much cleaner fix for this.  292  */
293 void disablePCI()  
294 {  
295   PCICR = 0;  
296   PCMSK2 = 0;  
297   PCMSK0 = 0;  
298   PCMSK1 = 0;  
299 }  
301 // Blocks until IR code received  302 // or expiry is reached (returns true iff code received)  303 // reads the waitUntil variable to determine how long  304 // to wait for the backdoor

hippo

und weiter gehts mit zeile 305:
305 bool waitForBackdoor()  
306 {  
307   uint8_t pulseCount = 0;  
308   unsigned long pulseStart;  
309   bool pulseActive;  
311   while ( millis() < waitUntil )  
312   {  
313     int irval = analogRead(IRPINA);  
314     if (irval < 0x0F)  
315     {  
316       // pulse started  
317       if ( !pulseActive )  
318       {  
319         pulseActive = true;  
320         pulseStart = millis();  
321       }  
322     }  
323     else
324     {  
325       if ( pulseActive )  
326       {  
327         pulseActive = false;  
328         unsigned long duration = millis() - pulseStart;  
329         if ( (duration > 5) && (duration < 15) )  
330         {  
331           pulseCount++;  
332         }  
333       }  
334     }  
335   }  
336   /* 4 or more pulses within the duration specified by waitUntil will unlock the backdoor. */
337   if (pulseCount >= 4)  
338   {  
339     EEPROM.write( ADDR_BACKDOOR, 0xFF );  
340     return true;  
341   }  
342   return false;  
343 }  
344    
345 /*  
346  * This function only works when the Arduino is running off a battery pack.  
347  * When running on USB, maybe stick an infinite loop at the end?  
348  */
349 void shutdown()  
350 {  
351   lcd.clear();  
352   lcd.setCursor(0,0);  
353   lcd.print( " Shutting Down.");  
354   delay(2000);  
355   digitalWrite( POLULUPIN, HIGH );  
356 }  
357    
358 void unlockDrawer()  
359 {  
360   // disablePCI _MUST_ be called prior to any servo operations!  
361   disablePCI();  
362   drawerServo.attach(DRAWERPIN);  
363   // this "stepping" is only necessary due to limitations of the Software Servo library,  364   // which is an obsolete version of the Servo library that I used before  365   // I diagnosed the problem with the pin change interrupts and never  366   // had time to replace.  
367   for ( int i = 150; i >= 5; i-- )  
368   {  
369     drawerServo.write(i);  
370     SoftwareServo::refresh();  
371     delay(15);  
372   }  
373   drawerServo.detach();  
374 }  
376 void rotateLidServo(bool lock, int steps)  
377 {  
378   disablePCI();  
379   // In my setup, the lid servo is a continuous rotation servo and so writing an angular  380   // value to it makes it go a little crazy.  
381   lidServo.attach(LIDPIN);  
382   lidServo.write((lock) ? 0 : 180);  
383   for ( int i = 0; i < steps; i++ )  
384   {  
385     SoftwareServo::refresh();  
386     delayMicroseconds(15000);  
387   }  
388   lidServo.detach();  
389 }  
391 void unlockLid()  
392 {  
393   // give it a bit more juice on the "unlock" just in case  
394   rotateLidServo(false, 10);  
395 }  
397 void lockLid()  
398 {  
399   rotateLidServo(true, 7);  
400 }  
402 /*  
403  * Great Circle Distance calculation.  If anyone knows a fixed-point version  404  * of this function I'd love to see it.  405  */
406 float gcd(float lat_a, float lon_a, float lat_b, float lon_b)  
407 {  
408   float d = acos(sin(lat_a)*sin(lat_b)+cos(lat_a)*cos(lat_b)*cos(lon_a-lon_b));  
409   return fabs(EARTH_RADIUS * d);  
410 }  
412 void decrAttemptsRemaining()  
413 {  
414   attemptsRemaining--;  
415   // save the new state.  
416   EEPROM.write(ADDR_TRIES, attemptsRemaining);  
417 }  
419 void failNoSignal()  
420 {  
421   decrAttemptsRemaining();  
422   lcd.clear();  
423   lcd.setCursor(0,0);  
424   lcd.print( "Access Denied!" );  
425   lcd.setCursor(0,1);  
426   lcd.print( attemptsRemaining );  
427   lcd.print( " tries left" );  
428   delay(5000);  
429   lcd.clear();  
430   lcd.setCursor(0,0);  
431   lcd.print( "No Signal!" );  
432   delay(5000);  
433   shutdown();  
434 }  
436 /* This function resets the box to its original state. */
437 void initializeEEPROM()  
438 {  
439   // 101 Tries remaining  
440   EEPROM.write(ADDR_TRIES, 101);  
441   EEPROM.write(ADDR_STAGE1, 0);  
442   EEPROM.write(ADDR_STAGE2, 0);  
443   EEPROM.write(ADDR_BACKDOOR, 0);  
444 }

Martin Gerken

Ja, ist ein Einheitenproblem (0,639300 dezimal = 0,38 Minuten/Sekunden...)

hippo


Go Up