I have recently discovered that I like tinkering with electronics.
I build entries, automatic gates, welded types of fencing, and railing. For some reason mechanical measuring wheels won't last. So I am building a digital measuring wheel as my first legit arduino project. I want it to measure in inches, feet, and mileage. I have the displayed inches resetting to 0 inches (the total inches keeps on incrementing in the background, verified by serial monitor) at every foot. I do not have any decimal places on the inches, nor do I want decimal places on the inches. I have my footage displaying to the hundredth of a foot, and the mileage displaying to the thousandth of a foot. Because why not?
Here is my issue. As far as I can tell, the inches increment correctly. The footage increments correctly. BUT the mileage refuses to increment correctly. One thousandth of a mile equals 5.28 feet. Right?? So I am expecting to see the mileage displayed as .001 when the footage rolls over to 5.28, or somewhere between 5.2 and 5.3 if only displaying to the tenth position. I have tried using footage to make the formula. I have tried using inches to make the formula. I have tried multiple different formulas. At least a dozen. I have tried different decimal places. No matter what, the mileage displays .001 when the footage hits about 2.8 feet. Given this, you would think the mileage would display .002 when the footage hits 5.6 feet, but that's not the case. The mileage incrementing seems to be exponential, not linear.
I have resorted to asking 3 different AI programs for help before asking you folks. But I get NOWHERE there.
I am using an elegoo arduino uno R3 and a Taiss encoder model #E38S6-600-240 off of amazon (which by the way has 2400 pulses per revolution, not 600. I think I understand why.) My lcd is a Hiletgo 2004 I2C from amazon.
Here is the last code I used. I know there is some coding for a button. I do not have it set up yet. I know there are also some variables for another encoder (a future menu selector) that is not programmed yet. I am just trying to figure the mileage math problem before I move on. I have verified that the display is the same on my LCD screen and in the serial monitor. The serial monitor returns the same results. I have also verified that the wheelEnc is giving 2400 pulses per revolution. I also get the proper inch and footage measurement per revolution, no matter what my variable wheel diameter is set to. So those seem to be working. It is just the mileage that is stubborn.
Any thoughts?
/* My Measuring Wheel Project. Calculations based off of
wheel diameter and pulses per revolution.
Adjust these two value based on actual products used.
*/
#include <Encoder.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Change these pin numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
// On Arduino UNO, pins 2 and 3 are interrupt pins
Encoder wheelEnc(2, 4);
//Encoder menuEnc(3,5);
volatile long wheelPulseCount;
float totalInches = 0.0;
static float lastTotalInches = 0.0;
float inchesDisplayed = 0.0;
float totalFootage = 0.0;
float footageDisplayed = 0.0;
float totalMileage = 0.0;
float mileageDisplayed = 0.0;
const float inchesPerMile=63360.0;
const float inchesPerFoot=12.0;
const float feetPerMile=5280.0;
int reset = 10;
// Wheel size variables
float diameter = 15.0;//Change as needed for whichever wheel size
float inchesPerPulse;
float wheelInches;
float pi=M_PI;
int pulsesPerRev = 2400;//Change as needed depending on encoder used
void setup() {
// Serial.begin(230400);
// Serial.println("Measurement:");
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(8,1);
lcd.print("CFG");
delay (3000);
lcd.clear();
lcd.setCursor (2,0);
lcd.print("READY TO MEASURE");
pinMode(reset, INPUT_PULLUP);
}
long wheelCountStart = 0;
void loop() {
wheelPulseCount = wheelEnc.read();//Read the pulses from encoder
wheelInches = diameter * pi;//Calculate the circumference of wheel.
inchesPerPulse = wheelInches / pulsesPerRev;//Used to calculate inches covered per pulse.
if (wheelPulseCount != wheelCountStart) {//Starts the counting process
wheelCountStart = wheelPulseCount;
}
totalInches = wheelPulseCount * inchesPerPulse;//Calculate total inches covered
totalFootage = floor(totalInches/inchesPerFoot);//Calculate the footage
totalMileage = totalFootage/feetPerMile;//Calculate the mileage.
// Calculate the remaining inches within a foot
inchesDisplayed = abs(static_cast<int>(totalInches)) % 12;/*The % sign uses float, but total
inches is an int, so static_cast<int>
turns it back to an integer. ABS means use
absolute value. Prevents incehs from being
displayed in negatives.*/
footageDisplayed = totalFootage + (inchesDisplayed / 12.0);//Displays footage
mileageDisplayed = totalMileage;//Displays mileage
if (totalFootage<0){
totalFootage=0;
}
if (totalMileage<0){
totalMileage=0;
}
if (totalFootage>99999 || totalFootage<-99999){
totalFootage=0;
}
if (lastTotalInches != totalInches) { /*This if statement prevents constant monitoring of the
serial monitor. It only displays new data when the data
changes*/
lastTotalInches = totalInches; // Resets if statements
lcd.setCursor (0,2);
lcd.print (" IN FT MI");
lcd.setCursor(0,3);
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print (inchesDisplayed,0);
lcd.setCursor (7,3);
lcd.print(" ");
lcd.setCursor(7,3);
lcd.print(footageDisplayed,2);
lcd.setCursor(15,3);
lcd.print(" ");
lcd.setCursor(15,3);
lcd.print(mileageDisplayed,3);
}
if (digitalRead(reset) == LOW) {//If RESET button is pressed
delay(100);//debounce. Could change to millis()
Serial.print("RESET");
wheelEnc.write(0);//Resets encoder counts to zero and displays all zeros on serial monitor
}
}