Issue above certain speed - hall effect speedometer for bike

Hi, ill try my best to keep this as short as possible.
I'm trying to get an arduino based speedometer for my electric bike working.

This is the code I have written: (ik it is probably poorly written - i only do coding stuff occasionally :slight_smile: )

//--------------------------------------------------------------------------------------------//
//                        ELECTRIC BIKE SPEEDOMETER (KM/H) & ODOMETER                         //
//                            Written by Darcy Johnson Dec. 2021                              //
//--------------------------------------------------------------------------------------------//
//                                                                                            //
//    For Use With/Notes:                                                                     //
//     *ATMega328p Arduino Based Microcontroller (e.g. Arduino Uno)                           //
//     *Nokia Type 5110 Monochrome LCD Display                                                //
//     *Hall Effect Sensor                                                                    //
//     *Use of EEPROM for storing total distance (odo.) and total on time.                    //
//                                                                                            //
//--------------------------------------------------------------------------------------------//

//Adapted RPM Code by James Rovere 



//DISPLAY-CONFIGURATION-----------------------------------------------------------------------//
#include "U8glib.h"  //Include U8glib Library

// Create display and set pins: (Using Nokia LCD for Arduino)
U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);   // (CLK=13, DIN=11, CE=10, DC=9, RST=8)
//--------------------------------------------------------------------------------------------//

//EEPROM-CONFIGURATION------------------------------------------------------------------------//
//Note: EEPROM is coded to count to 1020km travelled on odo (can add more addr. for more dist.)
#include <EEPROM.h> //Include EEPROM Library
//Addresses we will write to EEPROM with:

//Odo. Addresses:
const int EEPROMaddr1 = 0; //255km block 1
const int EEPROMaddr2 = 1; //255km block 2
const int EEPROMaddr3 = 2; //255km block 3
const int EEPROMaddr4 = 3; //255km block 4
const int EEPROMaddr5 = 4; //0.99km block


//Time Addresses:
const int EEPROMaddr6 = 5; //Ride Hours
const int EEPROMaddr7 = 6; //Ride Minutes

//How often writes to eprom occurs (half e.g. an interval of 10 would equal 20seconds)
const int EEPROMwriteInterval = 10; //Must be a multiple of 2. This x2 is how long it waits.
//--------------------------------------------------------------------------------------------//

//CONFIGURATION-------------------------------------------------------------------------------//
const int wheel_circumference = 2062; //The circumference of the wheel in mm (including tyre)
String unitText = "kph"; //Change if you want to change kph to KPH or something like that.
//--------------------------------------------------------------------------------------------//


float kph = 0;
int speedy;
float value = 0;
float detected = 0;
int rpm;
int oldtime = 0;        
int time;
int topspeed = 0; //Top Speed Achieved 
float distance; //Total Distance travelled
float newdistance; //Distance travelled in sample time in km
int timepassed; //Time passed to check if odometer write (EEPROM) is due
bool checked; //First check for error in calculation on startup
int decimalwrite;
int hours;
int minutes;
int seconds;

void detection()
{
    //Runs everytime the magnet on wheel is detected.
    detected = detected + 1;
}

void setup()
{
    Serial.begin(9600); //Debug Only
    u8g.setRot180(); //Rotate Display by 180 degrees

    //LOAD ALL ODO. VALUES FROM EEPROM
    int eepromread1 = EEPROM.read(EEPROMaddr1);
    int eepromread2 = EEPROM.read(EEPROMaddr2);
    int eepromread3 = EEPROM.read(EEPROMaddr3);
    int eepromread4 = EEPROM.read(EEPROMaddr4);
    float eepromread5 = EEPROM.read(EEPROMaddr5);
    float eepromdecimal = eepromread5/100; //Convert EEPROM decimal block (e.g. 12) to decimal (0.12)
    distance = eepromread1 + eepromread2 + eepromread3 + eepromread4 + eepromdecimal; //Add all blocks together

    //LOAD ALL TIME VALUES FROM EEPROM
    int eepromread6 = EEPROM.read(EEPROMaddr6);
    int eepromread7 = EEPROM.read(EEPROMaddr7);
    hours = eepromread6;
    minutes = eepromread7;
    
    Serial.print("DISTANCE EEPROM READ: ");
    Serial.println(distance);
    Serial.print("DECIMAL EEPROM READ: ");
    Serial.println(eepromread5);
    Serial.println(eepromdecimal);
    
    checked = false;
    
    attachInterrupt(0, detection, RISING);  //Attach Interrupt to Digital Pin 2
}

void loop()
{
    delay(2000); // 2 Second Delay
    detachInterrupt(0); //Detach Interupt

    seconds = seconds + 2;
    if (seconds == 60)
    {
      minutes = minutes + 1;
      seconds = 0;
    }
    if (minutes == 60)
    {
       hours = hours + 1;
       minutes = 0;
    }
    Serial.println(hours);
    Serial.println(minutes);
    Serial.println(seconds);

    timepassed = timepassed + 2; //INCREASE TIMEPASSED FOR EEPROM WRITE
    

    time=millis()-oldtime;        //finds the time 
    rpm=(detected/time)*60000;         //calculates rpm
    Serial.println("  ");
    Serial.println("  ");
    Serial.println(detected);
    Serial.print(time);
    Serial.println("  ");
    Serial.println("  ");
    oldtime=millis();             //saves the current time
    detected=0;
    
    
    //Calculate Speed (kph)
    int kph = (((wheel_circumference/10)/3.14)*rpm*0.001855);

    //Block out first interupt:
    //(is sometimes triggered on power up)
    if (checked == false)
    {
      if (kph > 0)
      {
        kph = 0;
        checked = true;
      }
      else
      {
        checked = true;
      }
    }

    
    if (kph > topspeed) //If current speed is greater than past logged topspeed
    {
      topspeed = kph; //Amends topspeed with new topspeed
    }
    
    speedy = ((int)kph); 

    
    //Calculate distance travelled in those 2 seconds
    /*int sampletime = 2; //Time = 2 seconds
    int wheel_circumference_km = wheel_circumference/1000000;
    newdistance = wheel_circumference_km*sampletime*rpm; //D = C x T x RPM */

    newdistance = ((kph/3.6)*2)/1000; //Convert kph to m/s, m/s x sample time (2s), divide by 1000 (m -> km)

    Serial.print("New Distance: ");
    Serial.print(newdistance);
    Serial.println("km");

    
    if (newdistance > 0)
    {
      distance = distance + newdistance;
    }
    
    
    
    
    Serial.print("TIME: ");
    Serial.println(timepassed);

    /*Check if EEPROMwriteInterval/2 seconds has passed, if so write
     *distance to EEPROM splitting distance into 4 address capable
     *of 0-255 per address.*/
    if (timepassed == EEPROMwriteInterval) // t/2 IT WAITS EACH TIME FOR EEPROM TO WRITE
    {
      timepassed = 0; //reset time that has passed for EEPROM write check
      
      //Checking Distance Value to split between addresses:
      if (distance > 0 && distance < 255) //Only uses EEPROMaddr1
      {
        
        int EEPROMwrite1 = distance;
        int EEPROMwrite2 = 0;
        int EEPROMwrite3 = 0;
        int EEPROMwrite4 = 0;
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }

        
      } else if (distance > 255 && distance < 510) //Uses EEPROMaddr1 and EEPROMaddr2
      {
        int EEPROMwrite1 = 255;
        int EEPROMwrite2 = distance - 255;
        int EEPROMwrite3 = 0;
        int EEPROMwrite4 = 0;
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }
      } else if (distance > 510 && distance < 765) //Uses EEPROMaddr1, EEPROMaddr2 and EEPROMaddr3
      {
        int EEPROMwrite1 = 255;
        int EEPROMwrite2 = 255;
        int EEPROMwrite3 = distance - (255*2);
        int EEPROMwrite4 = 0;
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }
      } else if (distance > 765 && distance < 1020) //Uses all 4 EEPROMaddr
      {
        int EEPROMwrite1 = 255;
        int EEPROMwrite2 = 255;
        int EEPROMwrite3 = 255;
        int EEPROMwrite4 = distance - (255*3);
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }
      }

        //CALCULATE AND STORE DECIMAL OF DISTANCE
        int distanceint = distance;
        //convert decimals to whole numbers (*100)
        float decimals = (distance - distanceint)*100; 
        //remove decimal places of the new whole number (float -> int)
        int decimalwrite = decimals; 
        
        /*Serial.print("Decimals: ");
        Serial.println(decimals);
        Serial.println(decimalwrite);*/

        //WRITE TO EEPROM
        if (EEPROM.read(EEPROMaddr5) != decimalwrite)
        {
           EEPROM.write(EEPROMaddr5, decimals);
           Serial.println("WRITTEN");
        }


        //TIME
        int EEPROMwrite6 = hours;
        int EEPROMwrite7 = minutes;
        EEPROM.write(EEPROMaddr6, EEPROMwrite6);
        EEPROM.write(EEPROMaddr7, EEPROMwrite7);
        
        
        /*Serial.println("");
        Serial.println(EEPROM.read(EEPROMaddr1));
        Serial.println(EEPROM.read(EEPROMaddr2));
        Serial.println(EEPROM.read(EEPROMaddr3));
        Serial.println(EEPROM.read(EEPROMaddr4));
        Serial.println(EEPROM.read(EEPROMaddr5));*/
    }
    
    
  
    //DEBUG SERIAL
    Serial.println("Speed:");
    Serial.print(kph);
    Serial.println("kph");
    Serial.println("RPM:");
    Serial.println(rpm);

    
    
  
    //DISPLAY STUFF----
    u8g.firstPage();
  
    do
    {
      draw();
    }
    while(u8g.nextPage());

    attachInterrupt(0, detection, RISING); //Reattach Interrupt to Digital Pin 2
}


//DRAW EVERYTHING ON THE DISPLAY
void draw()
{
    //Small Font
    u8g.setFont(u8g_font_6x10);

    //Title Text
    u8g.drawStr(0, 7, "DARCYS BIKE v1");

    //Top Speed Text
    u8g.setPrintPos(4, 35);
    String hourUnitText = "h";
    String spacer;
    if (topspeed < 10)
    {
      spacer = "   ";
    } else {
      spacer = "  ";
    }
    
    //Running Time Text
    String minuteUnitText = "m";
    String topTimerPrint = topspeed + unitText + spacer + hours + hourUnitText + minutes + minuteUnitText;
    u8g.print(topTimerPrint);

    //Total Distance Text (Odometer)
    u8g.setPrintPos(20, 45);
    String odoText = "Odo: ";
    String odoUnitText = "km";
    String odoPrint = String(distance) + odoUnitText;
    u8g.print(odoPrint);
    
    //Large Font
    u8g.setFont(u8g_font_10x20);

    //Speed Text (Speedometer)
    if (kph < 10) //Ensures that text is somewhat centred
    {
      u8g.setPrintPos(21, 23);
    }
    else
    {
      u8g.setPrintPos(19, 23);
    }

    String speedy2 = String(speedy) + unitText;
    u8g.print(speedy2);
}

I have setup an ATmega328p IC flashed with the arduino bootloader, 16mhz crystal, etc all on a proto board. I'm using one of those nokia 5110 LCD displays as well. I'm using a generic hall effect sensor with a 10K resistor between 5v and the signal pin. It's using an interrupt pin on the arduino to detect the magnet 'triggering' the hall effect sensor.

The issue is that whenever i surpass around 40kph (it can be +- 10kph really though), the kph displayed jumps around randomly between -2000 and +2000kph. I'm not really sure what's happening. There is quite a bit of vibration >35kph on the bike. Just so you know it does work perfectly fine and as intended up until these speeds.

I understand the code is probably not very clear but i'll really appreciate any help and suggestions and i'll try my best to help if it is not clear.

Code is also attached:
Main.ino (13.1 KB)

I can post pictures if need be.

Thanks!
Darcy

Getting whacky values, especially negative ones, suggests that you're getting integer overflow in your RPM variable. Try making it unsigned long.

The detected variable doesn't need to be float, but it does need to be volatile since it is touched in an interrupt.

Your baud rate is glacial and you're doing a lot of printing - try 115200 instead.

Your interrupt is off for a long time. Usually, the procedure is to turn them off, copy detected, zero it and turn them back on.

1 Like

Wow thank you so much for the quick reply!
I'll try doing what you've said tonight and test tomorrow morning (i live in western australia).
Thanks again - I really appreciate it!
I'll post back results tomorrow :slight_smile:

Hi again,
I tried what you suggested and when I test it by lifting up the bike and running the motor at max power, it display kph perfectly fine - reaches 60-70kph depending on when i tested (probably due to different battery charge) - This is without the bike actually moving, only the wheel.

When I go for a ride, the error still persists, even more prevalent now than before?
Here the adjusted code:

//--------------------------------------------------------------------------------------------//
//                        ELECTRIC BIKE SPEEDOMETER (KM/H) & ODOMETER                         //
//                            Written by Darcy Johnson Dec. 2021                              //
//--------------------------------------------------------------------------------------------//
//                                                                                            //
//    For Use With/Notes:                                                                     //
//     *ATMega328p Arduino Based Microcontroller (e.g. Arduino Uno)                           //
//     *Nokia Type 5110 Monochrome LCD Display                                                //
//     *Hall Effect Sensor                                                                    //
//     *Use of EEPROM for storing total distance (odo.) and total on time.                    //
//                                                                                            //
//--------------------------------------------------------------------------------------------//

//Adapted RPM Code by James Rovere 

//Help from Arduino Forum user wildbill
//https://forum.arduino.cc/u/wildbill


//DISPLAY-CONFIGURATION-----------------------------------------------------------------------//
#include "U8glib.h"  //Include U8glib Library

// Create display and set pins: (Using Nokia LCD for Arduino)
U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);   // (CLK=13, DIN=11, CE=10, DC=9, RST=8)
//--------------------------------------------------------------------------------------------//

//EEPROM-CONFIGURATION------------------------------------------------------------------------//
//Note: EEPROM is coded to count to 1020km travelled on odo (can add more addr. for more dist.)
#include <EEPROM.h> //Include EEPROM Library
//Addresses we will write to EEPROM with:

//Odo. Addresses:
const int EEPROMaddr1 = 0; //255km block 1
const int EEPROMaddr2 = 1; //255km block 2
const int EEPROMaddr3 = 2; //255km block 3
const int EEPROMaddr4 = 3; //255km block 4
const int EEPROMaddr5 = 4; //0.99km block


//Time Addresses:
const int EEPROMaddr6 = 5; //Ride Hours
const int EEPROMaddr7 = 6; //Ride Minutes

//How often writes to eprom occurs (half e.g. an interval of 10 would equal 20seconds)
const int EEPROMwriteInterval = 10; //Must be a multiple of 2. This x2 is how long it waits.
//--------------------------------------------------------------------------------------------//

//CONFIGURATION-------------------------------------------------------------------------------//
const int wheel_circumference = 2062; //The circumference of the wheel in mm (including tyre)
String unitText = "kph"; //Change if you want to change kph to KPH or something like that.
//--------------------------------------------------------------------------------------------//


float kph = 0;
int speedy;
float value = 0;
volatile float detected = 0;
unsigned long rpm;
int oldtime = 0;        
int time;
int topspeed = 0; //Top Speed Achieved 
float distance; //Total Distance travelled
float newdistance; //Distance travelled in sample time in km
int timepassed; //Time passed to check if odometer write (EEPROM) is due
bool checked; //First check for error in calculation on startup
int decimalwrite;
int hours;
int minutes;
int seconds;

void detection()
{
    //Runs everytime the magnet on wheel is detected.
    detected = detected + 1;
}

void setup()
{
    Serial.begin(115200); //Debug Only
    u8g.setRot180(); //Rotate Display by 180 degrees

    //LOAD ALL ODO. VALUES FROM EEPROM
    int eepromread1 = EEPROM.read(EEPROMaddr1);
    int eepromread2 = EEPROM.read(EEPROMaddr2);
    int eepromread3 = EEPROM.read(EEPROMaddr3);
    int eepromread4 = EEPROM.read(EEPROMaddr4);
    float eepromread5 = EEPROM.read(EEPROMaddr5);
    float eepromdecimal = eepromread5/100; //Convert EEPROM decimal block (e.g. 12) to decimal (0.12)
    distance = eepromread1 + eepromread2 + eepromread3 + eepromread4 + eepromdecimal; //Add all blocks together

    //LOAD ALL TIME VALUES FROM EEPROM
    int eepromread6 = EEPROM.read(EEPROMaddr6);
    int eepromread7 = EEPROM.read(EEPROMaddr7);
    hours = eepromread6;
    minutes = eepromread7;
    
    Serial.print("DISTANCE EEPROM READ: ");
    Serial.println(distance);
    Serial.print("DECIMAL EEPROM READ: ");
    Serial.println(eepromread5);
    Serial.println(eepromdecimal);
    
    checked = false;
    
    attachInterrupt(0, detection, RISING);  //Attach Interrupt to Digital Pin 2
}

void loop()
{
    delay(2000); // 2 Second Delay
    detachInterrupt(0); //Detach Interrupt

    //calulate rpm
    time=millis()-oldtime;        //finds the time 
    rpm=(detected/time)*60000;         //calculates rpm
    Serial.println("  ");
    Serial.println("  ");
    Serial.println(detected);
    Serial.print(time);
    Serial.println("  ");
    Serial.println("  ");
    oldtime=millis();             //saves the current time
    detected=0;

    //reattach interrupt
    attachInterrupt(0, detection, RISING);


    //time stuffs
    seconds = seconds + 2;
    if (seconds == 60)
    {
      minutes = minutes + 1;
      seconds = 0;
    }
    if (minutes == 60)
    {
       hours = hours + 1;
       minutes = 0;
    }
    Serial.println(hours);
    Serial.println(minutes);
    Serial.println(seconds);

    timepassed = timepassed + 2; //INCREASE TIMEPASSED FOR EEPROM WRITE
   
    
    
    //Calculate Speed (kph)
    int kph = (((wheel_circumference/10)/3.14)*rpm*0.001855);

    //Block out first interupt:
    //(is sometimes triggered on power up)
    if (checked == false)
    {
      if (kph > 0)
      {
        kph = 0;
        checked = true;
      }
      else
      {
        checked = true;
      }
    }

    
    if (kph > topspeed) //If current speed is greater than past logged topspeed
    {
      topspeed = kph; //Amends topspeed with new topspeed
    }
    
    speedy = ((int)kph); 

    
    //Calculate distance travelled in those 2 seconds
    /*int sampletime = 2; //Time = 2 seconds
    int wheel_circumference_km = wheel_circumference/1000000;
    newdistance = wheel_circumference_km*sampletime*rpm; //D = C x T x RPM */

    newdistance = ((kph/3.6)*2)/1000; //Convert kph to m/s, m/s x sample time (2s), divide by 1000 (m -> km)

    Serial.print("New Distance: ");
    Serial.print(newdistance);
    Serial.println("km");

    
    if (newdistance > 0)
    {
      distance = distance + newdistance;
    }
    
    
    
    
    Serial.print("TIME: ");
    Serial.println(timepassed);

    /*Check if EEPROMwriteInterval/2 seconds has passed, if so write
     *distance to EEPROM splitting distance into 4 address capable
     *of 0-255 per address.*/
    if (timepassed == EEPROMwriteInterval) // t/2 IT WAITS EACH TIME FOR EEPROM TO WRITE
    {
      timepassed = 0; //reset time that has passed for EEPROM write check
      
      //Checking Distance Value to split between addresses:
      if (distance > 0 && distance < 255) //Only uses EEPROMaddr1
      {
        
        int EEPROMwrite1 = distance;
        int EEPROMwrite2 = 0;
        int EEPROMwrite3 = 0;
        int EEPROMwrite4 = 0;
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }

        
      } else if (distance > 255 && distance < 510) //Uses EEPROMaddr1 and EEPROMaddr2
      {
        int EEPROMwrite1 = 255;
        int EEPROMwrite2 = distance - 255;
        int EEPROMwrite3 = 0;
        int EEPROMwrite4 = 0;
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }
      } else if (distance > 510 && distance < 765) //Uses EEPROMaddr1, EEPROMaddr2 and EEPROMaddr3
      {
        int EEPROMwrite1 = 255;
        int EEPROMwrite2 = 255;
        int EEPROMwrite3 = distance - (255*2);
        int EEPROMwrite4 = 0;
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }
      } else if (distance > 765 && distance < 1020) //Uses all 4 EEPROMaddr
      {
        int EEPROMwrite1 = 255;
        int EEPROMwrite2 = 255;
        int EEPROMwrite3 = 255;
        int EEPROMwrite4 = distance - (255*3);
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite1)
        {
          EEPROM.write(EEPROMaddr1, EEPROMwrite1);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite2)
        {
          EEPROM.write(EEPROMaddr2, EEPROMwrite2);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite3)
        {
          EEPROM.write(EEPROMaddr3, EEPROMwrite3);
          Serial.println("WRITTEN");
        }
        
        if (EEPROM.read(EEPROMaddr1) != EEPROMwrite4)
        {
          EEPROM.write(EEPROMaddr4, EEPROMwrite4);
          Serial.println("WRITTEN");
        }
      }

        //CALCULATE AND STORE DECIMAL OF DISTANCE
        int distanceint = distance;
        //convert decimals to whole numbers (*100)
        float decimals = (distance - distanceint)*100; 
        //remove decimal places of the new whole number (float -> int)
        int decimalwrite = decimals; 
        
        /*Serial.print("Decimals: ");
        Serial.println(decimals);
        Serial.println(decimalwrite);*/

        //WRITE TO EEPROM
        if (EEPROM.read(EEPROMaddr5) != decimalwrite)
        {
           EEPROM.write(EEPROMaddr5, decimals);
           Serial.println("WRITTEN");
        }


        //TIME
        int EEPROMwrite6 = hours;
        int EEPROMwrite7 = minutes;
        EEPROM.write(EEPROMaddr6, EEPROMwrite6);
        EEPROM.write(EEPROMaddr7, EEPROMwrite7);
        
        
        /*Serial.println("");
        Serial.println(EEPROM.read(EEPROMaddr1));
        Serial.println(EEPROM.read(EEPROMaddr2));
        Serial.println(EEPROM.read(EEPROMaddr3));
        Serial.println(EEPROM.read(EEPROMaddr4));
        Serial.println(EEPROM.read(EEPROMaddr5));*/
    }
    
    
  
    //DEBUG SERIAL
    Serial.println("Speed:");
    Serial.print(kph);
    Serial.println("kph");
    Serial.println("RPM:");
    Serial.println(rpm);

    
    
  
    //DISPLAY STUFF----
    u8g.firstPage();
  
    do
    {
      draw();
    }
    while(u8g.nextPage());
}


//DRAW EVERYTHING ON THE DISPLAY
void draw()
{
    //Small Font
    u8g.setFont(u8g_font_6x10);

    //Title Text
    u8g.drawStr(0, 7, "DARCYS BIKE v1");

    //Top Speed Text
    u8g.setPrintPos(4, 35);
    String hourUnitText = "h";
    String spacer;
    if (topspeed < 10)
    {
      spacer = "   ";
    } else {
      spacer = "  ";
    }
    
    //Running Time Text
    String minuteUnitText = "m";
    String topTimerPrint = topspeed + unitText + spacer + hours + hourUnitText + minutes + minuteUnitText;
    u8g.print(topTimerPrint);

    //Total Distance Text (Odometer)
    u8g.setPrintPos(20, 45);
    String odoText = "Odo: ";
    String odoUnitText = "km";
    String odoPrint = String(distance) + odoUnitText;
    u8g.print(odoPrint);
    
    //Large Font
    u8g.setFont(u8g_font_10x20);

    //Speed Text (Speedometer)
    if (kph < 10) //Ensures that text is somewhat centred
    {
      u8g.setPrintPos(21, 23);
    }
    else
    {
      u8g.setPrintPos(19, 23);
    }

    String speedy2 = String(speedy) + unitText;
    u8g.print(speedy2);
}

Any suggestions?

Thanks so much again, Happy New Year.
Darcy.

That seems to suggest a hardware problem...

1 Like

Hmmm, maybe I should try with a different Arduino. I was just using an AtMega328p IC on a protoboard but I've got an actual Arduino Mega 2560 board, ill try that - i might have to change the interrupt pin but im not sure - ill just look it up.
If that doesn't change it, maybe its my hall effect sensor.
Thanks for the help!

Hi,

No.
Can you post a picture of the Hall Effect setup on your bike?
What is the distance between the magnet and the device?

Can you please post link to data/spec of the Hall Effect?
How long is the lead from the sensor to the controller?
Can you please post a circuit diagram?

Tom... :grinning: :+1: :coffee: :australia:

1 Like

. . .

The variables time and oldtime should be unsigned long.

1 Like

Sure!
Sorry for poor pictures but here are a few:

Distance between magnet and hall effect sensor is approx. 5mm:
Hall effect sensor is covered by one layer of electrical tape.

This is the board:

The length of the wires for the hall effect sensor is approx 82cm (much longer than i thought!)

This is the hall effect sensor i'm using: (i removed the sensor off the pcb, but resoldered it with some wire so i could get the board away from the wheel but the sensor near the wheel - hope that makes sense).

Datasheet: https://www.jaycar.com.au/medias/sys_master/images/images/9594841661470/XC4434-dataSheetMain.pdf

It will take me a bit to draw a circuit diagram as I didn't really follow one or draw one before hand. Shouldn't take too long.

Thanks so much for the help,
Darcy.

Thanks!
I'll try changing that now.

Hi,
Thanks for the images.

Have you got any bypass capacitors on your board?
Have you got even a 100uF capacitor across the supply rails on your board.

The board looks pretty bare of essential noise filtering components.

What is the power supply?

What pin are you using to detect the HallEffect signal?
Have you declared your input pin as an input in the void setup()?

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

1 Like

Hi again Tom,
To be completely honest with you I don't know a whole lot about electronics but this is the details:

Capacitor wise, I have the following only:

  • 0.1uF ceramic cap between 5v and GND on the 328.
  • 0.1uF ceramic cap between RST on the 328 and DTR pin on USB-Serial converter.
  • No 100uF capacitor across the supply rails (i can do that though if need be)

Power is from the 5v USB output on electric bike battery.

Hall Effect Sensor Stuff:

  • Digital Pin 2 for Hall Effect Sensor

The only way i have declared the input pin in void setup is this:

attachInterrupt(0, detection, RISING);  //Attach Interrupt to Digital Pin 2

Thanks for your help :D,
Darcy.

Hi,
In this example they declare the interrupt pin.

Do you have the caps on the Crystal leads to gnd?

Tom... :grinning: :+1: :coffee: :australia:

1 Like

Ok ill take a look at the example and declare it.
Oh yep sorry forgot to mention that - yes two 22pF ceramic caps going from both crystal leads to gnd.

Thanks again!

Some observations on the code.

  1. 'detected' is not volatile, but is written in an interrupt routine and read in the main code. Must be declared volatile.

  2. 'detected' needs to be read in a critical section, since the ATmega chip is 8-bit and uses 4 instructions to read a float (32 bit). If the interrupt happens between any of those instructions you'll get nonsense.

Thus we use a critical section to protect from this:

  noInterrupts() ;
  float copy_detected = detected;  // no interrupts can happen during this line.
  interrupts () ;
  // now we can use copy_detected knowing its uncorrupted.
  1. Also why is 'detected' a float at all - its just a counter you add 1 to. floats are emulated on the ATmega (incredibly slow). Perhaps use an int, or long int.

60000 is not a valid integer constant value on the ATmega as it has 16 bit as the default integer size, and 16 bit integers only go from -32768 to +32767, best to specify a long constant:

    rpm=(detected/time)*60000L;         //calculates rpm

It probably works as is, but only because the compiler is being kind...

  1. Nearly all you code is in a big long chunk in the function loop().

This is hard to read and maintain - its wise to break out functionality into many, small, well-named functions, making the code readable, maintainable, flexible. If a function is longer than 10 lines, think seriously about whether its too complicated...

There's clearly a lot of repetition which could be greatly improved by the use of arrays (EEPROMaddrX, EEPROMwriteX.

Repetitive code maximizes the risk of bugs slipping in as there are so many copies the bug can lurk in. If you use arrays and loop through them, there is only one copy of the code that you have to get right, and much less code to write.

1 Like

Thanks so much for your reply.

I'll try out what you said. Sorry about my code - I don't do a whole lot of coding stuff so thanks for your help!

Darcy.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.