Hello everyone,
Spent the last couple of hours to try and figure this one out, but I can't.
I am designing a speedometer for an electric motorcycle conversion.
I have a working code that that displays what I want and, at a press of a button, switches the display between the different information I want it to show - that part works great.
However, because this is an evolving project I now want to add a feature where the TRIP display gets reset to zero when you hold the button for a longer period - and I cannot figure out how to do it.
The long press code is based on this one shown in the video:
https://www.youtube.com/watch?v=TD7vjJy0w8U
Basically what happens now is the moment I press the button for a longer period, the counter already increases to a next number, my display changes and I would like to avoid that. Basically, I tried an if statement that if the counter is at a given number and the button is being pressed for a longer time, an action (zeroing the trip) should take place, but like I said, I can't even get to that stage because the counter goes up...
Anyway, here's my code, hoping someone can point me in the right direction.
// Below is the OLED definition code - this is responsible for setting up the screen only.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Below is the speedometer background code - this is responsible for calculating speed, distance
#include <EEPROM.h>
unsigned long period_pulse = 0;
unsigned long last_pulse = 0;
int speed_kmph = 0;
float distance = 0;
float old_distance = 0;
float old_distance2 = 0;
float rev_distance = 0;
unsigned long revolution_count = 0;
unsigned long rev_new, rev_old, check_pulse;
float eeprom_trip_dist_read;
float eeprom_total_dist_read;
float Trip_distance;
float Total_distance;
float Trip_distance_multiplied;
float Total_distance_multiplied;
char read_get_eeprom = 0;
char write_eeprom = 0;
unsigned long Millis = 0;
unsigned long eeprom_interval = 600000;
unsigned long eeprom_oldMillis = 0;
#define circum 2.19
// Below is the code responsible for measuring the battery percentage.
// #define batt_pin A0
// #define volt_multiplier 19 // from voltage divider 88V to 4.63148V
// #define batt_min 60 // min=60 volt
// #define batt_max 92 //max= 92 volt
// int batt_analog=0;
// float batt_voltage=0;
// int batt_percent=0;
// Below is the code responsible for button setup
const int buttonPin = 7; // the number of the pushbutton pin
int buttonPushCounter = 0; // counter for the number of button presses
boolean buttonState = LOW; // current state of the button
boolean lastButtonState = LOW; // previous state of the button
// Below is the code responsible for long button press setup
int buttonStatePrevious = LOW; // previousstate of the switch
unsigned long minButtonLongPressDuration = 3000; // Time we wait before we see the press as a long press
unsigned long buttonLongPressMillis; // Time in ms when we the button was pressed
bool buttonStateLongPress = false; // True if it is a long press
const int intervalButton = 50; // Time between two readings of the button state
unsigned long previousButtonMillis; // Timestamp of the latest reading
unsigned long buttonPressDuration; // Time the button is pressed in ms
unsigned long currentMillis; // Variabele to store the number of milleseconds since the Arduino has started
void setup() {
Serial.begin(115200);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
// Below is the setup code for the screen only along with the welcome message
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
delay(2000);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 10);
// Display static text
display.println("eOsa wita");
display.display();
delay(2000);
display.clearDisplay();
display.display();
// Below is the setup code for the speed etc calculations
pinMode(2, INPUT);
attachInterrupt(digitalPinToInterrupt(2), Hall_sensor, RISING); // Enable interruption pin 2 when going from LOW to HIGH.
eeprom_trip_dist_read = EEPROM.read(0);
eeprom_total_dist_read = EEPROM.read(3);
}
// Function for reading the button state
void ButtonStateRead() {
// If the difference in time between the previous reading is larger than intervalButton
if (currentMillis - previousButtonMillis > intervalButton) {
// Read the digital value of the button (LOW/HIGH)
int buttonState = digitalRead(buttonPin);
// If the button has been pushed AND
// If the button wasn't pressed before AND
// IF there was not already a measurement running to determine how long the button has been pressed
if (buttonState == HIGH && buttonStatePrevious == LOW && !buttonStateLongPress) {
buttonLongPressMillis = currentMillis;
buttonStatePrevious = HIGH;
Serial.println("Button pressed");
}
// Calculate how long the button has been pressed
buttonPressDuration = currentMillis - buttonLongPressMillis;
// If the button is pressed AND
// If there is no measurement running to determine how long the button is pressed AND
// If the time the button has been pressed is larger or equal to the time needed for a long press
if (buttonState == HIGH && !buttonStateLongPress && buttonPressDuration >= minButtonLongPressDuration) {
buttonStateLongPress = true;
Serial.println("Button long pressed");
}
// If the button is released AND
// If the button was pressed before
if (buttonState == LOW && buttonStatePrevious == HIGH) {
buttonStatePrevious = LOW;
buttonStateLongPress = false;
Serial.println("Button released");
// If there is no measurement running to determine how long the button was pressed AND
// If the time the button has been pressed is smaller than the minimal time needed for a long press
// Note: The video shows:
// if (!buttonStateLongPress && buttonPressDuration < minButtonLongPressDuration) {
// since buttonStateLongPress is set to FALSE on line 75, !buttonStateLongPress is always TRUE
// and can be removed.
if (buttonPressDuration < minButtonLongPressDuration) {
Serial.println("Button pressed shortly");
}
}
// store the current timestamp in previousButtonMillis
previousButtonMillis = currentMillis;
}
}
void loop() {
currentMillis = millis(); // store the current time
ButtonStateRead(); // read the button state
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// Define buffer for printing in dynamic text
char buffer[10];
// Step 1 - fetching already saved distances from EEPROM
if (read_get_eeprom == 0)
{
Trip_distance_multiplied = eeprom_trip_dist_read;
Total_distance_multiplied = eeprom_total_dist_read;
read_get_eeprom = 1;
}
// Step 2 - calculate speed based on pulses
speed_kmph = ceil((circum * 3600) / period_pulse); //km/h
// Step 3 - calculate distance travelled
old_distance = distance;
distance = revolution_count * (circum / 10); //Km, but I change to m for now so it's easy to see if this is working
rev_distance = distance - old_distance;
Trip_distance_multiplied = Trip_distance_multiplied + rev_distance;
Total_distance_multiplied = Total_distance_multiplied + rev_distance;
Trip_distance = Trip_distance_multiplied / 100;
Total_distance = Total_distance_multiplied / 100;
// Step 4 - write new distance to EEPROM
if ((distance - old_distance2) > 1)
{
EEPROM.write(0, Trip_distance_multiplied);
EEPROM.write(3, Total_distance_multiplied);
old_distance2 = distance;
write_eeprom = 1;
}
// Step 5 - not sure what happens here, I don't really follow this part of the code
rev_new = revolution_count;
check_pulse = millis() - last_pulse;
if (check_pulse > 3000)
{
if (rev_new == rev_old)
{
speed_kmph = 0;
if (write_eeprom == 0)
{
EEPROM.write(0, Trip_distance_multiplied);
EEPROM.write(3, Total_distance_multiplied);
write_eeprom = 1;
}
}
}
rev_old = revolution_count;
// This is the battery code, suppressed for now.
//batt_analog = analogRead(batt_pin);
//batt_voltage=((batt_analog*5)/1024)*volt_multiplier;
//batt_percent = ((batt_voltage - batt_min) / (batt_max - batt_min)) * 100;
// This is the display code setting, that switches over at a button press
switch (buttonPushCounter) // choose what to display based on buttonPushCounter value
{
case 0:
display.setCursor(0, 10);
display.setTextColor(WHITE, BLACK);
sprintf(buffer, "V %d km/h", speed_kmph);
display.print(buffer);
display.display();
break;
case 1:
display.setCursor(0, 10);
display.setTextColor(WHITE, BLACK);
sprintf(buffer, "Trp %d.%02d", (int)Trip_distance, (int)(Trip_distance * 100) % 100);
display.print(buffer);
display.display();
break;
case 2:
display.setCursor(0, 10);
display.setTextColor(WHITE, BLACK);
sprintf(buffer, "Ttl %d.%02d", (int)Total_distance, (int)(Total_distance * 100) % 100);
display.print(buffer);
display.display();
break;
}
// compare the buttonState to its previous state
if (buttonState != lastButtonState)
{
if (buttonState == HIGH)
{
// if the current state is HIGH then the button
// went from off to on:
buttonPushCounter++; // add one to counter
display.clearDisplay();
display.display();
if (buttonPushCounter > 2)
{
buttonPushCounter = 0;
}
}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
}
// This section is a code that zero's trip value if the button is held for more than 2 seconds
}
void Hall_sensor()
{
period_pulse = millis() - last_pulse;
last_pulse = millis();
revolution_count++;
}