Components and supplies
Battery, 3.7 V
Directional Antenna, GNSS Active Patch Antenna with LNA
Pushbutton Switch, Momentary
Adafruit Ultimate GPS FeatherWing
Any Feather microcontroller
Adafruit Ultimate GPS Breakout
SSD1306 128x64 OLED Display
Arduino Nano R3
Tools and machines
Soldering iron (generic)
Project description
Code
Code (GPSSP)
arduino
Main code for the speedcoach.
1#include <Adafruit_SSD1306.h> 2#include <splash.h> 3#include <Wire.h> 4#include <Adafruit_GFX.h> 5#include <SPI.h> 6#include <SandTimer.h> 7#include <SD.h> 8#include <millisDelay.h> 9#include <Adafruit_GPS.h> //Libraries 10#define GPSSerial Serial1 11#define SCREEN_WIDTH 128 12#define SCREEN_HEIGHT 64 13#define OLED_RESET -1 14#define PAUSE 1000 15Adafruit_GPS GPS(&GPSSerial); 16File myFile; 17SandTimer timer1; 18#define GPSECHO false 19Adafruit_SSD1306 display(SCREEN_WIDTH,SCREEN_HEIGHT,&Wire,OLED_RESET); 20uint32_t timer = millis(); 21const int chipSelect = 4; 22float ms = 0; //Meters/Second variable 23float avems = 0; //Average M/S variable 24float mscounter = 0; //Speed total (for average) 25int integcounter = 0; //Counts half-seconds 26float meterstraveled = 0; //Total meters 27int splittotal = 0; //Split total (in seconds) (Essential to be an integer) 28int splitseconds = 0; //Seconds on split display (Essential to be an integer) 29int splitminutes = 0; //Minutes on split display (Essential to be an integer) 30int seconds = 0; 31int minutes = 0; 32int hours = 0; //Self-explanatory (for timers) 33int splitaveragetotal = 0; //All split seconds added together (for average split) 34int splitaverageseconds = 0; //Split average seconds 35int splitaverageminutes = 0; //Split average minutes 36int splitaverage = 0; //Split average 37int splitaveragesecondsdisp = 0; //Display variables, fixes a bug 38int splitaverageminutesdisp = 0; 39int splitmdisp = 0; 40int splitsdisp = 0; //Display Variables 41int tc = 0; //Counter variable 42int dp = 0; //Data-point variable 43int dpave = 0; //Average of the data-points 44int dprec = 0; //Counter variable 45float knot = 0;//Speed in knots recorded from GPS 46float aveknots = 0; //Speed in knots averaged over 1/2 second (equal to 1 data point and 5 knot readings) 47int knotcounter = 0; //Counter variable 48int sensorValue = analogRead(A3); //For the data write switch 49float msfm = 0; //M/S for the meters calculation 50float checkBattery(){ 51 //Function to check battery voltage 52 float measuredvbat = analogRead(9); 53 measuredvbat *= 2; // we divided by 2, so multiply back 54 measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage 55 measuredvbat /= 1024; // convert to voltage 56 57 58 return measuredvbat;} 59 millisDelay secdelay; //Timing delay (for timer) 60void setup() { 61 float voltage = sensorValue * (5.0 / 1023.0); //Converts A3 reading into a 5v equivalent 62 Wire.begin(); 63 Wire.setClock(400000L); 64 Serial.begin(115200); 65 GPS.begin(9600); 66GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); 67GPS.sendCommand(PGCMD_ANTENNA); 68GPSSerial.println(PMTK_Q_RELEASE); 69int realhours = GPS.hour - 8; 70if(realhours < 0) {realhours = realhours+24;} //For SD timestamp (24 hour format) 71if (voltage == 5) {if (!SD.begin(chipSelect)) { //Begins SD card startup 72 Serial.println("Card failed, or not present"); 73 } 74 } 75 uint32_t m = micros(); //Main timer initialization 76display.begin(SSD1306_SWITCHCAPVCC,0x3C); 77display.fillScreen(0); 78display.display(); 79display.fillRect(0,26,26,8,1); 80 display.fillTriangle(20,32,24,32,24,55,1); 81 display.fillTriangle(20,26,80,13,80,26,1); 82 display.fillTriangle(80,13,100,26,80,26,1); 83 display.fillRect(25,26,76,31,1); 84 display.fillTriangle(80,64,128,40,128,64,0); 85 display.setCursor(32,25); 86 display.setTextColor(0); 87 display.setTextSize(4); 88 display.print("RTI"); 89 display.setCursor(0,0); 90 display.setTextColor(1); 91 display.setTextSize(1); 92 display.print("RTI Development"); 93 display.setCursor(0,8); 94 display.print("v. 3.0.0"); 95 display.display(); 96 delay(2000); 97 secdelay.start(1000); //Start secondary timer delay (1 Second) 98File dataFile = SD.open("storage.txt", FILE_WRITE); //Opens SD card, prints initial piece introduction + timestamp 99 if (dataFile) { 100 Serial.println("Writing to SD"); 101 dataFile.println("PIECE BEGIN - - -"); 102 dataFile.print(realhours); 103 dataFile.print("/"); 104 dataFile.println(GPS.minute); 105 dataFile.close();} 106 timer1.start(100); 107 108} 109 110void loop() { 111 112 sensorValue = analogRead(A3); 113 float voltage = sensorValue * (5.0 / 1023.0); 114 115 float batVoltage = checkBattery(); //get battery voltage 116 if (secdelay.justFinished()) {seconds++; secdelay.repeat();} //Checks if 1 second has passed, updates seconds variable 117 if (seconds == 60) {seconds = 0; minutes++;} //Checks if 60 seconds have passed, resets seconds, increases minutes 118 if (minutes == 60) {minutes = 0; hours++;} //Checks if 60 minutes have passed, resets minutes, increases hours 119 char c = GPS.read(); 120 if (GPSECHO) 121 if (c) Serial.print(c); 122 if (GPS.newNMEAreceived()) { 123 Serial.println(GPS.lastNMEA()); 124 if (!GPS.parse(GPS.lastNMEA())); //Serial GPS info for debugging 125 } 126 127 if (timer > millis()) timer = millis(); //Restarts main timer 128 129 130 if (timer1.finished()) {knot = knot+GPS.speed; knotcounter++; 131 timer1.startOver();} 132 133 if (millis() - timer > 500) { //Runs every half-second (responsible for screen-flicker) 134 timer = millis(); // Resets timer 135 if (GPS.fix) { 136 aveknots = knot/knotcounter; 137 Serial.println(aveknots); 138 ms = (aveknots*0.5144444); //Converts knots to meters/second 139 Serial.println(ms); 140 knot = 0; 141 tc = 0; 142 knotcounter = 0; 143 aveknots = 0; 144 if (ms <= 0.75) {display.fillScreen(0); 145 146 display.setCursor(0,0); 147 display.setTextColor(1); 148 display.setTextSize(1); 149 150 display.print("Error: IDLE"); 151 display.setCursor(0,15); 152 display.print("T: "); 153 display.setCursor(10,15); 154 display.print(hours); 155 display.setCursor(16,15); 156 display.print(":"); 157 display.setCursor(22,15); 158 display.print(minutes); 159 display.setCursor(34,15); 160 display.print(":"); 161 display.setCursor(40,15); 162 display.print(seconds); 163 display.setCursor(0,30); 164 display.print("Battery: "); 165 display.setCursor(47,30); 166 display.print(batVoltage); 167 display.setCursor(0,45); 168 display.print("Meters: "); 169 display.setCursor(43,45); 170 display.print(meterstraveled); }//Idle screen 171 display.display(); 172 173 174 if (ms > 0.75) 175 { 176 177 msfm = ms; 178 mscounter = (mscounter+msfm); //Continually adds speed to total (for averages) 179 integcounter = (integcounter+1); //Adds +1 to variable every half second (for averages) 180 avems = mscounter/integcounter; //Generates average meters/second (for total) 181 meterstraveled = avems*(integcounter/2); //Calculates total (meters/second divided by seconds) 182 splittotal = 500/(ms); //Generates seconds per 500m 183 dp = dp + splittotal; //Adds data-points for dpave variable 184 dprec++; 185 if (dprec >= 6) {dpave = dp/6; //Calculates average 186 dprec = 0; 187 dp = 0; //Resets data-points and counter variable 188 if(voltage > 4.5) {File dataFile = SD.open("storage.txt", FILE_WRITE); 189 //Opens SD card if write switch is on 190 191 if (dataFile) { 192 Serial.println("Writing to SD"); 193 dataFile.println("S: "); 194 dataFile.print(splitminutes); 195 dataFile.print(":"); 196 dataFile.println(splitseconds); 197 dataFile.print("Ave. S "); 198 dataFile.print(splitaverageminutes); 199 dataFile.print(":"); 200 dataFile.println(splitaverageseconds); 201 dataFile.print("M: "); 202 dataFile.println(meterstraveled); 203 dataFile.print(hours); 204 dataFile.print(":"); 205 dataFile.print(minutes); 206 dataFile.print(":"); 207 dataFile.println(seconds); 208 dataFile.println(); 209 dataFile.close();}} //Prints data to SD card 210 } 211 splitminutes = dpave/60; //Generates split minutes from split seconds 212 splitseconds = dpave - (splitminutes*60); //Displays remaining seconds 213 splitaveragetotal = splitaveragetotal+splittotal; //All split times (in seconds) added together 214 splitaverage = splitaveragetotal/(integcounter); //Averages out split times w/ seconds 215 splitaverageminutes = splitaverage/60; //Calculates split minutes 216 splitaverageseconds = splitaverage-splitaverageminutes*60; //Calculates split seconds 217 splitaverageminutesdisp = splitaverageminutes; 218 splitaveragesecondsdisp = splitaverageseconds; 219 splitmdisp = splitminutes; 220 splitsdisp = splitseconds; //Display variables 221 display.fillScreen(0); 222 display.setCursor(0,0); 223 display.setTextColor(1); 224 display.setTextSize(2); 225 display.print("M: "); 226 display.setCursor(20,0); 227 display.print(meterstraveled); //Displays total meters 228 display.setCursor(0,20); 229 display.print("S: "); 230 display.setCursor(20,20); 231 display.print(splitmdisp); 232 display.setCursor(35,20); 233 display.print(":"); 234 display.setCursor(45,20); 235 display.print(splitsdisp); 236 //oled.print(" AS: "); oled.print(splitaverageminutesdisp); oled.print(":"); oled.println(splitaveragesecondsdisp); 237 //Displays split and average split 238 display.setCursor(0,40); 239 display.print("T: "); 240 display.setCursor(22,40); 241 display.print(hours); 242 display.setCursor(33,40); 243 display.print(":"); 244 display.setCursor(42,40); 245 display.print(59); 246 display.setCursor(63,40); 247 display.print(":"); 248 display.setCursor(72,40); 249 display.print(seconds); //Displays timer 250 display.display(); 251 //if (voltage >= 4.5) {oled.print("SD Write ON");} 252 //if (voltage < 4.5) {oled.print("SD Write OFF");} //Shows write permission status 253 }}}} 254
Downloadable files
Schematics
Wire Diagram for the GPSSP
Schematics
Schematics
Wire Diagram for the GPSSP
Schematics
Comments
Only logged in users can leave comments
rowingtechinnovations
0 Followers
•0 Projects
Table of contents
Intro
6
0