Created
August 18, 2017 00:17
-
-
Save tylerjw/2267672702ccf432e632822d3eef8258 to your computer and use it in GitHub Desktop.
Basic rally computer for use with Adafruit feathers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <TinyGPS++.h> | |
// Enable one of these two #includes and comment out the other. | |
// Conditional #include doesn't work due to Arduino IDE shenanigans. | |
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc. | |
//#include <TinyWireM.h> // Enable this line if using Adafruit Trinket, Gemma, etc. | |
#include "Adafruit_LEDBackpack.h" | |
#include "Adafruit_GFX.h" | |
Adafruit_7segment red = Adafruit_7segment(); | |
Adafruit_7segment white = Adafruit_7segment(); | |
static const uint32_t GPSBaud = 9600; | |
static const int lightPin = 5; | |
static const int lowLight = 300; | |
static const int highLight = 1000; | |
static const int lowBrightness = 0; | |
static const int highBrightness = 15; | |
static const int blackButtonPin = 12; | |
static const int clockOdoState = 0; | |
static const int speedOdoState = 1; | |
static const int brightnessState = 2; | |
static const int batteryState = 3; | |
static const int numStates = 4; | |
int state = speedOdoState; | |
boolean odoResetDisplay = false; | |
static double tripDistance = 0.0; // miles | |
#define VBATPIN A9 | |
// The TinyGPS++ object | |
TinyGPSPlus gps; | |
TinyGPSCustom fixQuality(gps, "GPGSA", 2); // fix | |
static const int timeout = 5000; | |
void setup() | |
{ | |
Serial.begin(9600); | |
Serial1.begin(GPSBaud); | |
red.begin(0x70); | |
white.begin(0x71); | |
pinMode(blackButtonPin, INPUT_PULLUP); // button | |
} | |
void loop() | |
{ | |
// This sketch displays information every time a new sentence is correctly encoded. | |
while (Serial1.available() > 0) | |
gps.encode(Serial1.read()); | |
// read photoresister | |
int light = constrain(analogRead(lightPin), lowLight, highLight); | |
int brightness = map(light, lowLight, highLight, lowBrightness, highBrightness); | |
red.setBrightness(brightness); | |
white.setBrightness(brightness); | |
// handle the button | |
odoButton(blackButtonPin); | |
// check to see if the gps was disconnected somehow | |
if (gps.time.age() < timeout) | |
{ | |
switch(state) { | |
case clockOdoState: | |
if(gps.time.isUpdated()) | |
displayClock(white); | |
break; | |
case speedOdoState: | |
if(gps.speed.isUpdated()) | |
displaySpeed(white); | |
break; | |
case brightnessState: | |
displayBrightness(white, brightness); | |
break; | |
case batteryState: | |
displayBatteryVoltage(white); | |
break; | |
} | |
if (gps.location.isUpdated()) { | |
if(odoResetDisplay == false) { | |
displayOdo(red); | |
} else { | |
red.printError(); | |
} | |
} | |
} else { | |
red.printError(); | |
white.printError(); | |
} | |
red.writeDisplay(); | |
white.writeDisplay(); | |
} | |
void displayBrightness(Adafruit_7segment &disp, int brightness) | |
{ | |
disp.print(brightness); | |
// display a B or 8 or whatever you want to call it | |
disp.writeDigitRaw(0, 0b11111111); | |
} | |
void displayBatteryVoltage(Adafruit_7segment &disp) | |
{ | |
float measuredvbat = analogRead(VBATPIN); | |
measuredvbat *= 2; // we divided by 2, so multiply back | |
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage | |
measuredvbat /= 1024; // convert to voltage | |
disp.print(measuredvbat); | |
} | |
void displayClock(Adafruit_7segment &disp) | |
{ | |
// assume clock is updated | |
int minutesecond = gps.time.minute() * 100 + gps.time.second(); | |
disp.print(minutesecond, DEC); | |
disp.drawColon(true); | |
} | |
void displayOdo(Adafruit_7segment &disp) | |
{ | |
// assume gps.location is updated | |
static TinyGPSLocation previousLocation; | |
if(previousLocation.isValid()) // not the first time | |
{ | |
double distance = gps.distanceBetween(gps.location.lat(), gps.location.lng(), | |
previousLocation.lat(), previousLocation.lng()) * _GPS_MILES_PER_METER; | |
if(gps.speed.isValid() && gps.speed.mph() > 1.0) | |
{ | |
// increment the trip distance | |
tripDistance += distance; | |
} | |
// display the distance | |
disp.print(tripDistance); | |
} | |
previousLocation = gps.location; | |
} | |
void displaySpeed(Adafruit_7segment &disp) | |
{ | |
// assume gps.speed.updated() | |
static int speed = 0; | |
if(gps.speed.isValid() && gps.speed.mph() != speed) | |
{ | |
speed = gps.speed.mph(); | |
} | |
disp.print(speed); | |
// display fix quality | |
static char mask = 0b01000000; | |
if( fixQuality.isUpdated() ) | |
{ | |
int fix = atoi(fixQuality.value()); | |
if( fix == 2 ) { | |
mask = 0b01001001; | |
} else if ( fix == 3 ) { | |
mask = 0b01001001; | |
} else { | |
mask = 0b01000000; | |
} | |
} | |
disp.writeDigitRaw(0, mask); | |
} | |
void odoButton(int pin) | |
{ | |
static long button_timer = 0; | |
static const long longpress_time = 500; | |
static const long shortpress_time = 50; | |
static boolean button_active = false; | |
static boolean longpress_active = false; | |
if(digitalRead(pin) == LOW) { | |
// button pressed | |
if (button_active == false) { | |
button_active = true; | |
button_timer = millis(); | |
} | |
if ((millis() - button_timer > longpress_time) && (longpress_active == false)) { | |
longpress_active = true; | |
odoResetDisplay = true; | |
// reset trip distance | |
tripDistance = 0.0; | |
} | |
} else { | |
// button not pressed | |
if(button_active == true) { | |
if(longpress_active == true) { | |
odoResetDisplay = false; | |
longpress_active = false; | |
} else if(millis() - button_timer > shortpress_time) { | |
// switch state | |
state = (state + 1) % numStates; | |
} | |
button_active = false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment