Hello - this is my first post here.
I have been working on a GPS speedometer based on instructions and code in a YouTube video. So far it's working well, thanks to the helpful video and a few additional searches on this forum!
My GPS is a Neo 6M, my OLED is a DEVMO 12864 0.96 Inch I2c, and I am using an ELEGOO Nano board. I believe the GPS is 1 hertz, so I get 1 speed reading per second.
I would like my OLED to "show" each mile-per-hour as it goes from one number to another. For example, if a reading is 30 mph, and then the next reading is 35 mph, I would like the display to show 31, 32, 33, and 34, before showing the 35 mph.
I have produced some code which tries to calculate the difference in mph from two readings, then divide 1 second into that many intervals, and then update the mph by +1 for each of those intervals. In the example above, it would (I think) do 35 - 30 = 5, so it would divide 1 second into 5 parts of 200ms each, and it would show 31, 32, 33, 34, 35 with a 200 ms delay between each.
The challenge is that there appears to be some latency in the updates on the OLED, sometimes. For example, if it's going from 40 to 50, it might do: 40-41-42-43-44-45-46--------47-48-49-50. I don't know how to tell if this latency is coming from the Nano processing, or if it's coming from the OLED display. (If the latter, I guess this latency would not be there if I removed the display and was just passing the mph number to another device).
My code is below, but just figured I'd ask in case there is an obvious cause of the random latency that experienced coders know of. Thank you!
#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <TinyGPS++.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
//On an arduino UNO: A4(SDA), A5(SCL)
#define OLED_RESET -1 //Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C //See datasheet for Address
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define rxPin 2
#define txPin 3
SoftwareSerial neogps(rxPin, txPin);
TinyGPSPlus gps;
int displaySpeed = 0;
int currentSpeed = 0;
int diff = 0;
int msdelay = 250;
void setup() {
Serial.begin(115200);
//Begin serial communication Arduino IDE (Serial Monitor)
//Begin serial communication Neo6mGPS
neogps.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.display();
delay(2000);
}
void loop() {
boolean newData = false;
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (neogps.available())
{
if (gps.encode(neogps.read()))
{
newData = true;
}
}
}
//If newData is true
if (newData == true)
{
newData = false;
print_speed();
}
else
{
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.setTextSize(3);
display.print(F("No Data"));
display.display();
}
}
void print_speed()
{
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
if (gps.location.isValid() == 1)
{
currentSpeed = currentSpeed + random(0, 40) - 10 ; // set it back to this for actual car testing: currentSpeed = int(gps.speed.mph()) ;
diff = currentSpeed - displaySpeed;
msdelay = abs((1000 / abs(diff)) - 50);
for (int i = 1; i < abs(diff) + 1; i++) {
displaySpeed = (displaySpeed + (diff / abs(diff))) ;
Serial.print("displaySpeed = "); Serial.println(displaySpeed);
display.clearDisplay();
//String gps_speed = String(gps.speed.mph());
display.setCursor(0, 0);
display.setTextSize(3);
display.print(currentSpeed); //display.print(gps.speed.mph());
display.setCursor(80, 13);
display.setTextSize(1);
display.print(F("mph"));
//String gps_speed = String(gps.speed.mph());
display.setCursor(0, 35);
display.setTextSize(3);
display.print(displaySpeed);
display.setCursor(80, 48);
display.setTextSize(1);
display.print(F("avg mph"));
display.display();
delay(msdelay);
}
}
}