Hall Sensor(KY003) generates random values during read cycle

Greetings to all,

As I would like to get better in making projects and at the same time challenge myself to make something different, I'm trying to make a Bicycle Speedometer using these following components

a) Sparkfun's Transparent OLED display

b) ESP32 DOIT DEVKIT V1 (WiFi+BT module)

c)KY-003 Hall Effect Sensor

I got a sample code from Youtube, which is this. And it works perfectly when I'm using ONLY ESP and the Hall Effect Sensor while giving me satisfactory result.

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1;

int hall_sensor = 19;
int magnetSense = 0;
int counter= 0;
int lastState= 1;

float bikeSpeed;
float radius=0.000207;
float pi=3.142;
float circumference=2*radius*pi;

void setup() {

Serial.begin(115200);
startMillis=millis();
  pinMode(hall_sensor, INPUT);

}

void loop() {

currentMillis=millis();
magnetSense=digitalRead(hall_sensor);
if(magnetSense==0 && lastState==1) {
  lastState=0;

  if(currentMillis-startMillis>=period && lastState==0) {
    bikeSpeed=circumference/(currentMillis-startMillis)*3600000;
    startMillis=currentMillis;      
      counter++;
      Serial.println(String(bikeSpeed)+"km/h");

  }

}

else {
  if(currentMillis-startMillis>=period && lastState==0) {
    startMillis=currentMillis;    
    lastState=1;
  
    
  }
}

}

But, when I try to include the display, I get unreliable random values instead of the consistent values that I got with the previous script. I am not sure what I'm doing wrong as I am still new to coding. Some roasting and pointers would be appreciated.

#include <WiseChipHUD.h> // Including Transparent OLED Display's library

unsigned long startMillis; //For storing Internal Clock time of ESP when it starts
unsigned long currentMillis; // For Storing Current Clock time of ESP
const unsigned long period = 1; //Unsigned Long is used to store large variables, for some reason the tutorial I followed used "1"

int hall_sensor = 19; // Pin where the Hall Sensor is connected to
int magnetSense =0; // Usually Magnet won't sense anything, so it's set to 0
int counter = 0; // Counter should be 0 at start
int lastState= 1; // Last known state has to be high for it to continue, or that's what I would like to think

float bikeSpeed; //Using float to store values with Decimal
float radius = 0.000207; //Radius of my Cycle's tire
float pi=3.142; // Do I really need to explain this??
float circumference = 2*radius*pi; // Basic Math

WiseChipHUD myHUD; //Just assiging a short name for the WiseChip HUD

void setup() {

 
Serial.begin(115200); //General baud rate for ESP32 Communication
startMillis=millis(); //Starting internal clock of ESP to start counting time
  pinMode(hall_sensor, INPUT); //Letting ESP know that hall sensor is an Input device, Microcontrollers can be dumb....

   myHUD.begin(); //Initializing OLED Display


}

void loop(){


currentMillis=millis();//Current time of the ESP get's stored here
magnetSense=digitalRead(hall_sensor); //Read the values from hall_sensor as digital input
if (magnetSense==0 && lastState==1) { //When magnet is sensed but it's 0, and lastState is 1, then proceed with calculation
  lastState=0;

  if(currentMillis-startMillis>=period && lastState ==0) { 
    bikeSpeed=circumference/(currentMillis-startMillis)*3600000; //Speed = Distance/ Time, so the amount of time taken by the tire circumference for 1 revolution can be used to calculate speed...
    startMillis=currentMillis;
      counter++;
      Serial.println(String(bikeSpeed)+"km/h");
      myHUD.speedometerUnits(1);
      myHUD.setSpeedometer(String(bikeSpeed).toInt());
      

  }
}
else {
  if(currentMillis-startMillis>=period && lastState==0) {
    startMillis=currentMillis;
    lastState=1;
  }
  
}



}


Here's a link to my videos, showing what's actually happening...

Link To Videos

That sensor is active LOW so it may just be floating when not activated. This means you should declare that pin as INPUT_PULLUP or have an external pull-up resistor

I cannot view your videos :frowning:

Most probably the display update takes too long so that you measure multiple wheel revolutions. If so start the next cycle with the next sensor pulse.

It may help to remove the excess update of startmillis after the display update.

Thank You for taking your time to reply back to me. I really appreciate it. I will try what you suggested and get back to you. Meanwhile, here's a link to my videos.

DropBox Link

Hi @dear_rstanb .

I did some modifications to your sketch.
I also posted some observations and comments.

My sugestion:
Use interrupt to count pulses coming from hall sensor.
If you have difficulty rewriting your sketch using interrupt, I can help you.

RV mineirin


  // Without display case
  unsigned long startMillis;
  unsigned long currentMillis;
  const unsigned long period = 1;

  int hall_sensor = 19;
  int magnetSense = 0;
  int counter = 0;
  boolean lastState = true;                // I changed to boolean type

  float bikeSpeed;
  float radius = 0.000207;
  float pi = 3.142;
  float circumference = 2 * radius * pi;
  //-----------------------------------------------------------
  void setup() {
  Serial.begin(115200);
  startMillis = millis();
  pinMode(hall_sensor, INPUT);
  }
  //-----------------------------------------------------------
  void loop() {
  currentMillis = millis();
  magnetSense = digitalRead(hall_sensor);
  if (magnetSense == 0 && lastState == true)
  {
    lastState = false;
    // if (currentMillis - startMillis >= period && lastState == 0)
    // No need to test lastState as it was set to 0 (false) in the previous statement
    if (currentMillis - startMillis >= period)
    {
      bikeSpeed = circumference / (currentMillis - startMillis) * 3600000;
      startMillis = currentMillis;
      counter++;
      Serial.println(String(bikeSpeed) + "km/h");
    }
  }
  else
  {
    // if (currentMillis - startMillis >= period && lastState == 0)
    // It was unnecessary to test laststate, because if I saw the else it was because it was 1 (true)
    if (currentMillis - startMillis >= period)
    {
      startMillis = currentMillis;
      lastState = true;
    }
  }
  }

/*
   If the bike is at a speed of 7.2 Km/H, the sensor will provide a pulse
     every 500 mSec.
     How The processing time in this sketch is relatively small, (except the use
     from serial.println()), risk of pulse loss and count error is small.
     But if the speed is, for example, 18 Km/H then the pulse will be 200 mSec,
     and pulses may be lost while the rest of the processing is done.
*/


//  With display case

#include <WiseChipHUD.h> // Including Transparent OLED Display's library

unsigned long startMillis; //For storing Internal Clock time of ESP when it starts
unsigned long currentMillis; // For Storing Current Clock time of ESP
const unsigned long period = 1; //Unsigned Long is used to store large variables, for some reason the tutorial I followed used "1"

int hall_sensor = 19; // Pin where the Hall Sensor is connected to
int magnetSense = 0; // Usually Magnet won't sense anything, so it's set to 0
int counter = 0; // Counter should be 0 at start
boolean lastState = true;                // I changed to boolean type // Last known state has to be high for it to continue, or that's what I would like to think

float bikeSpeed; //Using float to store values with Decimal
float radius = 0.000207; //Radius of my Cycle's tire
float pi = 3.142; // Do I really need to explain this??
float circumference = 2 * radius * pi; // Basic Math

WiseChipHUD myHUD; //Just assiging a short name for the WiseChip HUD
//-----------------------------------------------------------
void setup() {
  Serial.begin(115200); //General baud rate for ESP32 Communication
  startMillis = millis(); //Starting internal clock of ESP to start counting time
  pinMode(hall_sensor, INPUT); //Letting ESP know that hall sensor is an Input device, Microcontrollers can be dumb....
  myHUD.begin(); //Initializing OLED Display
}
//-----------------------------------------------------------
void loop() {
  currentMillis = millis(); //Current time of the ESP get's stored here
  magnetSense = digitalRead(hall_sensor); //Read the values from hall_sensor as digital input
  if (magnetSense == 0 && lastState == true)  //When magnet is sensed but it's 0, and lastState is 1, then proceed with calculation
  {
    lastState = false;

    if (currentMillis - startMillis >= period ) 
    {
      bikeSpeed = circumference / (currentMillis - startMillis) * 3600000; //Speed = Distance/ Time, so the amount of time taken by the tire circumference for 1 revolution can be used to calculate speed...
      startMillis = currentMillis;
      counter++;
      Serial.println(String(bikeSpeed) + "km/h");
      myHUD.speedometerUnits(1);
      myHUD.setSpeedometer(String(bikeSpeed).toInt());
    }
  }
  else {
    if (currentMillis - startMillis >= period ) 
    {
      startMillis = currentMillis;
      lastState = true;
    }
  }
}

/*
  If the bike is at a speed of 7.2 Km/H, the sensor will provide a pulse
    every 500 mSec.
    in this sketch processing time in this sketch is large, the risk of losing
    pulse and counting error is frequent and therefore failure in speed measurements
    even small ones.
*/