Motivace :
Tchán léta jezdí Corsičkou a letos nastala štrapác, tachometr vypověděl službu, rafička splaskla k nule a hotovo. Pokusy nahradit čidlo v bloku motoru opakovaně selhaly a tak nastoupila alternativa satelitního měření rychlosti a analogového zobrazení aktuální rychlosti na tachometru. Vzorkování rychlosti v rozsahu 1 ~ 5 Hz bezpečně vyhoví potřebám analogového sledovače a postačí i bez nutnosti měnit uloženou defaultní konfiguraci GPS přijímače u-blox Neo-6M. Prototypové řešení volně zobrazuje aktuálně poslední přečtený údaj o rychlosti a tento pasivní mód je možné dále rozšiřovat zařazením aktivního filtru a vyhlazováním údajů pomocí modelovaného systému druhého řádu ( rychlost, zrychlení ).
obrázek
BoM ( Bill-of-Material ) :
1x mikrokontrolér Arduino Nano, klon CH340 (+5V)
1x přijímač GPS u-blox Neo-6M (+5V)
1x zobrazovací tachometr na bázi servomotoru SG90 (+5V)
1x USB-napaječ z palubní zásuvky (+5V)
1x USB-USB kabel napájení desky a přijímače GPS
1x sada propojovacích kabelů
Použité knihovny :- standardní knihovna Arduino IDE SoftwareSerial- standardní knihovna Arduino IDE Servo- standardní knihovna Arduino IDE TinyGPS++ viz: [file:TinyGPSPlus-1.0.2b.zip]Zdrojový kód :/* ARDUINO NANO [doc:https://dratek.cz/arduino/1069-eses-klon-arduino-nano-ch340.html] Rx_DATA from u-Blox GPS-6M [doc:https://web.archive.org/web/20200610071942/https://www.u-blox.com/sites/default/files/products/documents/u-blox6_ReceiverDescrProtSpec_(GPS.G6-SW-10018)_Public.pdf] -----+5V-> o-Vcc_GPS-6M [+ https://dratek.cz/arduino/1510-gps-neo-6m-gyneo6mv2-modul-s-antenou.html] ---TxPin-> o--Rx_GPS-6M o-GND_GPS-6M PWM_out to SERVO SG90 [doc:https://www.peckamodel.cz/jix-sg90-1-9g-mini-servo-sg90] servoPin-> o--------SG90-PWM-(orange/yellow)-- -----+5V-> o--------SG90-Vcc-(red)------------ -----GND-> o--------SG90-GND-(brown)---------- */ //----------------------------------------------------------- #include <TinyGPS++.h> // GPS toolkit used for NMEA-messages decodes, ref.[doc:Pg.63/210] #include <Servo.h> // SERVO toolkit used to drive SG90 #include <SoftwareSerial.h> // UART RS-232 from the GPS-6M device //----------------------------------------------------------- #define GPSBaud 9600 // UART GPS-6M device default port speed is 9600-8-1-none [doc:Pg.7/210] #define RxPin 2 // UART [2]_Rx Rx_GPS-6M #define servoPin 9 // PWM [9]_PWM-----> SERVO-SG90_PWM_signal_IN #define servoOnExit 0 // //----------------------------------------------------------- TinyGPSPlus gps; // new TinyGPS++ object for DECODEs SoftwareSerial gpsSerial( RxPin, TxPin ); // new SERIAL instance for connection to the u-blox GPS-6M device Servo meTachometroveSERVO; // new SERVO instance int servoKMH = 0; // new int-variable to store GPS-reported speed [km/h].. [ToDo] as aRotatingBUFFER[3] in a 2nd-Order PDE speed-approximator //----------------------------------------------------------- void setup() { Serial.begin( 9600 ); // Start the Arduino hardware TTY port at 9600 baud gpsSerial.begin( GPSBaud ); // Start the software SERIAL port at the GPS's baud (u-blox default value [fine for serving at about ~1 Hz GPS update messages] ) meTachometroveSERVO.attach( servoPin ); // Set the Arduino hardware PIN[servoPIN] dedicated to PWM driving SG90-servo } //----------------------------------------------------------- void loop() { while ( gpsSerial.available() > 0 ) // every time a new sentence is correctly encoded if ( gps.encode( gpsSerial.read() ) ) { // READ it displayDATA(); // TTY report [via USB to PC-host, if present] .... [ToDo] could be removed for a headless, production code if ( gps.speed.isValid() ) update(); // TEST / UPD if .isValid() ...................... [ToDo] could be extended with a 2nd-Order PDE speed-approximator meTachometroveSERVO.write( servoKMH ); // SET SG90-servo ( Corsa will never fly > 140 )... [ToDo] could be constrain()-fused for non-Corsa vehicles like UL-s readGpsWhileInDELAY( 800 ); // WAIT read-feeding the gps-object for about 800 [ms] (ref. about the 1 Hz GPS-update) } //FUSE/////////////////////////------------------------------------------------------------------------------------- FUSE if ( millis() > 5000 // soft-timeout 5[s] ~ if 5000 milliseconds pass and there are no characters coming in & gps.charsProcessed() < 10 ) { // and too few CHARs came Serial.println("No GPS detected"); // show "No GPS detected" on TTY port [via USB to PC, if present] meTachometroveSERVO.write( servoOnExit ); // SET delay( 1000 ); // meTachometroveSERVO.detach(); // fuse SERVO out while ( true ); // _______________________________________________________________________________________________________________ FOREVER _EndOfGame_STATE_LOCKOUT__ } } //----------------------------------------------------------- static void update() { // UPD if .isValid() ............................ [ToDo] could be extended with a 2nd-Order PDE speed-approximator servoKMH = map( (int)gps.speed.kmph(), // map int( .kmph() ) 0, // mapFromLo ~ 0 km/h ....... (? dead zone around a walking speed ? :o) 160, // mapFromHi ~ 160 km/h ....... (a speed Opel Corsa ought never get ;) 4, // mapToLo ~ 4 of 180 steps 176 // mapToHi ~ 176 of 180 steps ); // } //----------------------------------------------------------- static void displayDATA() { Serial.println(); Serial.println(); if ( gps.location.isValid() ) { Serial.print( "Latitude: " ); Serial.println( gps.location.lat(), 6 ); Serial.print( "Longitude: " ); Serial.println( gps.location.lng(), 6 ); Serial.print( "Altitude: " ); Serial.println( gps.altitude.meters() ); } else Serial.println( "Location: Not Available" ); if ( gps.date.isValid() ) { Serial.print( "Date: " ); Serial.print( gps.date.month() ); Serial.print( "/" ); Serial.print( gps.date.day() ); Serial.print( "/" ); Serial.println( gps.date.year() ); } else Serial.println( "Date: Not Available" ); if ( gps.time.isValid() ) { Serial.print( "Time: " ); if ( gps.time.hour() < 10 ) Serial.print( F( "0" ) ); Serial.print( gps.time.hour() ); Serial.print( ":" ); if ( gps.time.minute() < 10 ) Serial.print( F( "0" ) ); Serial.print( gps.time.minute() ); Serial.print( ":" ); if ( gps.time.second() < 10 ) Serial.print( F( "0" ) ); Serial.print( gps.time.second() ); Serial.print( "." ); if ( gps.time.centisecond() < 10 ) Serial.print( F( "0" ) ); Serial.println( gps.time.centisecond() ); } else Serial.println( "Time: Not Available" ); } //----------------------------------------------------------- static void readGpsWhileInDELAY( unsigned long ms ) { unsigned long start = millis(); do { while ( gpsSerial.available() ) gps.encode( gpsSerial.read() ); } while ( millis() - start < ms ); }
a