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...
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
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.
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.
*/
Thank You for your taking your time to post a reply. I used an external pull-up resistor, but that problem is still there. I am still trying to debug it, I assume maybe it's something to do with power distribution as the screen and the sensor is running directly from 3.3V of the ESP.
Thank You for taking your time to reply, so sorry to get back so late. Was caught up with some personal issues of my own. Anyway, thank you for simplifying my code though it's not working and I'm not getting any output. But I can take it from here and add my own mix to it. But yes, any sort of help will be very appreciated.