mirror of
https://github.com/stevenhowes/MX5-Arduino-Speed.git
synced 2026-05-27 00:03:36 +01:00
Code
This commit is contained in:
@@ -0,0 +1,363 @@
|
||||
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include <EEPROM.h>
|
||||
#include <math.h>
|
||||
|
||||
//Define SPI Connections:
|
||||
#define OLED_MOSI 9
|
||||
#define OLED_CLK 10
|
||||
#define OLED_DC 11
|
||||
#define OLED_CS 12
|
||||
#define OLED_RESET 13
|
||||
|
||||
#define LOGO_HEIGHT 64
|
||||
#define LOGO_WIDTH 64
|
||||
const unsigned char PROGMEM logo_bmp [] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0xF0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x37, 0xE0, 0x07, 0xE8, 0x00, 0x00,
|
||||
0x00, 0x00, 0xF7, 0xC0, 0x07, 0xEE, 0x00, 0x00, 0x00, 0x01, 0xEF, 0x80, 0x03, 0xEF, 0x80, 0x00,
|
||||
0x00, 0x03, 0xEF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x00, 0x07, 0xCF, 0xC0, 0x03, 0xF7, 0xC0, 0x00,
|
||||
0x00, 0x07, 0xC7, 0xF8, 0x1F, 0xE3, 0xE0, 0x00, 0x00, 0x17, 0x87, 0xFE, 0x7F, 0xE3, 0xEC, 0x00,
|
||||
0x00, 0x37, 0x83, 0xFE, 0x7F, 0xC1, 0xEC, 0x00, 0x00, 0x77, 0xF9, 0xF0, 0x1F, 0xBF, 0xEC, 0x00,
|
||||
0x00, 0xF7, 0xFE, 0x00, 0x00, 0xFF, 0xCE, 0x00, 0x00, 0xF3, 0xFE, 0x00, 0x00, 0x7F, 0xCF, 0x00,
|
||||
0x00, 0xF1, 0xF8, 0x00, 0x00, 0x3F, 0x0F, 0x00, 0x00, 0xF0, 0xC0, 0x00, 0x00, 0x02, 0x07, 0x00,
|
||||
0x03, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFE, 0xC0,
|
||||
0x07, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFE, 0xE0, 0x0F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xE0,
|
||||
0x0F, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x39, 0xF0, 0x0F, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x39, 0xF0,
|
||||
0x0F, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xF0, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0,
|
||||
0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0,
|
||||
0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0xFF, 0xCE, 0xF3, 0xBC, 0x7D, 0xFD, 0xC7, 0x7F, 0xDF, 0xDE, 0xE3, 0xBE, 0xFB, 0xFF, 0xC7,
|
||||
0x7F, 0xFB, 0xDE, 0xE3, 0xFF, 0xFB, 0xFF, 0xCF, 0x1E, 0x3B, 0xDD, 0xE7, 0xFF, 0xFB, 0x9F, 0xFF,
|
||||
0x1E, 0x3F, 0xDD, 0xE7, 0xFF, 0xFB, 0xFF, 0xFE, 0x1C, 0x3F, 0xBD, 0xC7, 0xFF, 0xF7, 0xFF, 0xFE,
|
||||
0x1C, 0x7F, 0x3D, 0xC7, 0xFF, 0xF7, 0xF7, 0x9E, 0x3C, 0x77, 0x39, 0xCF, 0xEF, 0xF7, 0x07, 0x1E,
|
||||
0x3C, 0x77, 0xB9, 0xFE, 0xEF, 0xEF, 0x07, 0x1C, 0x38, 0x77, 0xF9, 0xFE, 0xEE, 0xEF, 0x07, 0x1C,
|
||||
0x38, 0x73, 0xF8, 0x78, 0xEE, 0xEE, 0x0F, 0x1C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
||||
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00,
|
||||
0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x18, 0x1C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x78,
|
||||
0x1F, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xF8, 0x1F, 0xBA, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0,
|
||||
0x0F, 0xFB, 0x00, 0x00, 0x00, 0x01, 0xDF, 0xF0, 0x0F, 0xF3, 0x80, 0x00, 0x00, 0x03, 0xCF, 0xE0,
|
||||
0x03, 0xE3, 0xC0, 0x00, 0x00, 0x03, 0xC7, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00,
|
||||
0x00, 0xE3, 0xD8, 0x00, 0x00, 0x1B, 0xC7, 0x00, 0x00, 0xFB, 0xDE, 0x00, 0x00, 0x7B, 0xDF, 0x00,
|
||||
0x00, 0xFF, 0xDF, 0x00, 0x00, 0xF3, 0xFE, 0x00, 0x00, 0x7F, 0x8F, 0x70, 0x0F, 0xF3, 0xFC, 0x00,
|
||||
0x00, 0x3F, 0x8F, 0xFC, 0x7F, 0xF1, 0xFC, 0x00, 0x00, 0x1F, 0x0F, 0xBE, 0xFD, 0xF0, 0xFC, 0x00,
|
||||
0x00, 0x00, 0x0F, 0xBF, 0xF9, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x9F, 0xF9, 0xFF, 0xC0, 0x00,
|
||||
0x00, 0x03, 0xFF, 0x0F, 0xF1, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0x07, 0xE0, 0xFF, 0x80, 0x00,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0xFE, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
|
||||
|
||||
// Boot graphics and screen refresh
|
||||
int prettylinecount = 64;
|
||||
byte screenrefresh = 0;
|
||||
|
||||
byte mode = 0; //(0 = bootlogo, 1 = running, 2 = calibrate)
|
||||
|
||||
// Pulse counting / pin state
|
||||
unsigned long pulsecount = 0;
|
||||
byte lastspeedstate = 0;
|
||||
bytespeedstate = 0;
|
||||
|
||||
// Odometer and current mile pulses
|
||||
unsigned long odometer = 0;
|
||||
unsigned long currentmile = 0;
|
||||
|
||||
// Calibration settings
|
||||
unsigned long pulsepermile = 0;
|
||||
byte calmultiplier = 2;
|
||||
|
||||
void bootlogo(void)
|
||||
{
|
||||
display.clearDisplay();
|
||||
display.drawBitmap((display.width() - LOGO_WIDTH ) / 2, (display.height() - LOGO_HEIGHT) / 2, logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
|
||||
display.display();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void prettyline()
|
||||
{
|
||||
display.clearDisplay();
|
||||
display.drawLine(prettylinecount, 45, 128 - prettylinecount, 45, WHITE);
|
||||
display.display();
|
||||
prettylinecount--;
|
||||
prettylinecount--;
|
||||
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(10);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println("---- stevehowes/MX5-Arduino-Speed ----");
|
||||
|
||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Initialize with the I2C address 0x3C.
|
||||
|
||||
// Beeper
|
||||
pinMode(2, OUTPUT);
|
||||
|
||||
// Speed Input
|
||||
pinMode(4, INPUT);
|
||||
|
||||
|
||||
// Do wanky Triumph Logo
|
||||
bootlogo();
|
||||
|
||||
// POST beep
|
||||
digitalWrite(2, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(2, LOW);
|
||||
|
||||
// Get calibrated data and odometer from EEPROM
|
||||
EEPROM.get(0, pulsepermile);
|
||||
EEPROM.get(4, odometer);
|
||||
|
||||
// Output debug data
|
||||
Serial.print("PPM Calibration: ");
|
||||
Serial.println(pulsepermile);
|
||||
Serial.print("Start Odometer: ");
|
||||
Serial.println(odometer);
|
||||
Serial.print("Calibration multiplier: ");
|
||||
Serial.print(calmultiplier);
|
||||
Serial.print(" (");
|
||||
Serial.print(1.0/calmultiplier);
|
||||
Serial.println(" miles)");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (mode == 0) // Boot mode
|
||||
{
|
||||
// Boot styling, when it expires default to run
|
||||
if (prettylinecount > 0)
|
||||
{
|
||||
prettyline();
|
||||
return;
|
||||
} else {
|
||||
mode = 1;
|
||||
}
|
||||
}
|
||||
else if (mode == 1) // Run mode
|
||||
{
|
||||
// If we have serial
|
||||
if (Serial.available() > 0)
|
||||
{
|
||||
String input = Serial.readString();
|
||||
// See if it's a cal request
|
||||
if (input == "CAL\n")
|
||||
{
|
||||
// Change to calibrate mode
|
||||
mode = 2;
|
||||
|
||||
// Notify user
|
||||
Serial.println("---- Calibration Mode ----");
|
||||
digitalWrite(2, HIGH);
|
||||
delay(500);
|
||||
digitalWrite(2, LOW);
|
||||
|
||||
// Draw the calibration screen
|
||||
screenrefresh = 1;
|
||||
|
||||
}
|
||||
else if (input == "PPM\n")
|
||||
{
|
||||
// Notify user
|
||||
Serial.print("Enter PPM: ");
|
||||
digitalWrite(2, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(2, LOW);
|
||||
|
||||
while (Serial.available() <= 0)
|
||||
{}
|
||||
|
||||
pulsepermile = Serial.parseInt();
|
||||
Serial.println(pulsepermile);
|
||||
EEPROM.put(0, pulsepermile);
|
||||
Serial.print(pulsepermile);
|
||||
Serial.println(" written to EEPROM at address 0");
|
||||
}
|
||||
else if (input == "ODO\n")
|
||||
{
|
||||
// Notify user
|
||||
Serial.print("Enter ODO: ");
|
||||
digitalWrite(2, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(2, LOW);
|
||||
|
||||
while (Serial.available() <= 0)
|
||||
{}
|
||||
|
||||
odometer = Serial.parseInt();
|
||||
Serial.println(odometer);
|
||||
EEPROM.put(4, odometer);
|
||||
Serial.print(odometer);
|
||||
Serial.println(" written to EEPROM at address 4");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
runmode();
|
||||
}
|
||||
}
|
||||
else if (mode == 2) // Calibration mode
|
||||
{
|
||||
calmode();
|
||||
}
|
||||
}
|
||||
|
||||
void calmode()
|
||||
{
|
||||
// If we're re-drawing the screen
|
||||
if (screenrefresh > 0)
|
||||
{
|
||||
// Clear display and re-draw our dividing line
|
||||
display.clearDisplay();
|
||||
display.drawLine(0, 45, 127, 45, WHITE);
|
||||
|
||||
// Display our last pulse count
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(10, 10);
|
||||
display.setTextSize(2);
|
||||
display.println(pulsecount);
|
||||
|
||||
// Mode
|
||||
display.setTextSize(1);
|
||||
display.setCursor(70, 48);
|
||||
display.println("Calibrate");
|
||||
|
||||
// Draw it and clear flag
|
||||
display.display();
|
||||
screenrefresh = 0;
|
||||
|
||||
// Save our count (will be multipied up later)
|
||||
pulsepermile = pulsecount;
|
||||
|
||||
// Reset counter
|
||||
pulsecount = 0;
|
||||
}
|
||||
|
||||
// until we get serial input, count as quickly as possible
|
||||
while (Serial.available() <= 0)
|
||||
{
|
||||
// Read pin
|
||||
speedstate = digitalRead(4);
|
||||
|
||||
// If it has changed
|
||||
if (speedstate != lastspeedstate)
|
||||
{
|
||||
// If we have gone high
|
||||
if (speedstate == 1)
|
||||
{
|
||||
pulsecount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Record recent state
|
||||
lastspeedstate = speedstate;
|
||||
}
|
||||
|
||||
|
||||
if (Serial.readString() == "RUN\n")
|
||||
{
|
||||
// Calibrate over distances other than one mile (half mile sensible)
|
||||
pulsepermile = pulsepermile * calmultiplier;
|
||||
EEPROM.put(0, pulsepermile);
|
||||
Serial.print(pulsepermile);
|
||||
Serial.println(" written to EEPROM at address 0");
|
||||
mode = 1;
|
||||
screenrefresh = 1;
|
||||
} else {
|
||||
screenrefresh = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void runmode()
|
||||
{
|
||||
screenrefresh = 1;
|
||||
|
||||
// If we're re-drawing the screen
|
||||
if (screenrefresh > 0)
|
||||
{
|
||||
// Used for any strings sent to screen
|
||||
char buf[16];
|
||||
|
||||
// Clear display and re-draw our dividing line
|
||||
display.clearDisplay();
|
||||
display.drawLine(0, 45, 127, 45, WHITE);
|
||||
|
||||
// Display our Speed, offset differently if > 100 (don't routely show third digit)
|
||||
display.setTextColor(WHITE);
|
||||
if((pulsecount * 2 * 3600 / pulsepermile) > 100)
|
||||
{
|
||||
display.setCursor(20, 10);
|
||||
display.setTextSize(4);
|
||||
sprintf(buf,"%03d",(pulsecount * 2 * 3600 / pulsepermile));
|
||||
}else{
|
||||
display.setCursor(42, 10);
|
||||
display.setTextSize(4);
|
||||
sprintf(buf,"%02d",(pulsecount * 2 * 3600 / pulsepermile));
|
||||
}
|
||||
display.println(buf);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(90, 32);
|
||||
display.println("mph");
|
||||
|
||||
// Display odometer as well
|
||||
display.setCursor(5, 48);
|
||||
display.setTextSize(1);
|
||||
sprintf(buf,"%06d miles",odometer);
|
||||
display.println(buf);
|
||||
|
||||
// Draw it and clear flag
|
||||
display.display();
|
||||
screenrefresh = 0;
|
||||
}
|
||||
|
||||
// Add measured pulses to current mile
|
||||
currentmile = currentmile + pulsecount;
|
||||
|
||||
// If we have completed a mile
|
||||
if (currentmile > pulsepermile)
|
||||
{
|
||||
// Bump up odometer
|
||||
odometer++;
|
||||
|
||||
// Take away a mile
|
||||
currentmile = currentmile - pulsepermile;
|
||||
|
||||
// Save to EEPROM
|
||||
EEPROM.put(4, odometer);
|
||||
}
|
||||
|
||||
// Reset count
|
||||
pulsecount = 0;
|
||||
|
||||
// Take samples for half a second
|
||||
unsigned long timestamp = micros();
|
||||
while (micros() < (timestamp + 500000))
|
||||
{
|
||||
// Read pin
|
||||
speedstate = digitalRead(4);
|
||||
|
||||
// If it has changed
|
||||
if (speedstate != lastspeedstate)
|
||||
{
|
||||
// If we have gone high
|
||||
if (speedstate == 1)
|
||||
{
|
||||
pulsecount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Record recent state
|
||||
lastspeedstate = speedstate;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user