Hello-
Having an issue with a fairly simple (I think) project that keeps track of the time a pump is either on or off (controlled by a float switch). Right now the switch is represented by two wires connected to ground and pin 7, and I short them together to represent the float switch being "on" and disconnect them to represent the float switch being off.
The LCD display is not incrementing the seconds properly, but minutes appears to work. The numbers are incrementing properly in the serial printout. I've created a number of subroutines to help process a "seconds" value into a more readable "HH:MM:SS.T" format, and I'm pretty sure the issue lies in those. I've been over it many times but you know how it is trying to debug your own code sometimes... I'm sure I'm missing something. Thanks!
#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); // Change to (0x27,20,4) for 20x4 LCD.
int period=100; //time between increments- currently set to tenths of a second
float secondCounter = 0; //counts number of times the pump comes on- not currently implemented
int floatSwitchPin = 7; //which pin the float switch is connected to
boolean pumpOn=false; // State of the pump- starts as "off" (False) and switches to "on" (True when pin7 is shorted to ground)
boolean lastPumpState=false;
float onTimeAccumulator=0; // total amount of time the pump is on
float offTimeAccumulator=0; // total amount of time the pump is off
void setup() {
//start LCD screen
lcd.init();
lcd.backlight();
// Initialize sensor pin
pinMode(floatSwitchPin, INPUT_PULLUP);
// Open Serial monitor for debugging
Serial.begin(9600);
}
void loop() {
unsigned long time_now = millis();
if (pumpOn==true) { // Check to see if the pump is on
onTimeAccumulator=onTimeAccumulator + 0.1; //increase the onTimeAccumulator by 0.1 seconds each loop when pump is on
}
else { //pump is off
offTimeAccumulator=offTimeAccumulator + 0.1; //increase the offTimeAcccumulator by 0.1 seconds each loop when pump is off
}
//Debugging Serial Print Statements
printTime(0, 0, onTimeAccumulator);
printTime(0, 1, offTimeAccumulator);
Serial.print("onTimeAccumulator=");
Serial.print(onTimeAccumulator);
Serial.print(" offTimeAccumulator=");
Serial.print(offTimeAccumulator);
Serial.print(" pumpOn=");
Serial.println(pumpOn);
while(millis() < time_now + period) { //non blocking delay
pumpOn=!digitalRead(floatSwitchPin);
}
}
void printTime(int x, int y, float seconds) { //Convert Seconds into user friendly display of HH:MM:SS.T
if (secondsToHours(seconds) > 99) {
x = x + 1; //If Seconds is bigger than 99 move over one column
}
lcd.setCursor(x, y);
if (secondsToHours(seconds) < 10) { //if hours is less than 10 add a leading 0
lcd.print("0");
lcd.setCursor(x + 1, y); //move over one column
}
lcd.print(secondsToHours(seconds)); //print number of hours (using subroutine below)
lcd.setCursor(x + 2, y); //move over 2 columns
lcd.print(":"); //print the colon
lcd.setCursor(x + 3, y); //move over 3 columns
if (secondsToMinutes(seconds) - (secondsToHours(seconds) * 60) < 10) { //if number of minutes is less than 10 add a deading 0
lcd.print("0");
lcd.setCursor(x + 4, y); //move over
}
lcd.print(secondsToMinutes(seconds) - (secondsToHours(seconds) * 60)); //print number of minutes (minus minutes accounted for as hours)
lcd.setCursor(x + 5, y); //position cursor
lcd.print(":"); //print colon
lcd.setCursor(x + 6, y); // position cursor
if (secondCounter - ((secondsToMinutes(seconds) * 60) + secondsToHours(seconds) * 3600) < 10) { //if number of seconds (minus seconds accounted for as minutes and as hours) is less than 10 add a leading zero
lcd.print("0"); //add a leading zeor
lcd.setCursor(x + 7, y); //move the cursor over
}
lcd.print(secondCounter - (((secondsToMinutes(seconds) * 60) + secondsToHours(seconds) * 3600)), 1); //print number of seconds (minus seconds accounted for as hours and minutes)
}
int secondsToMinutes(float seconds) { //converts seconds into minutes
int minutes;
minutes = floor(seconds / 60);
return (minutes);
}
int secondsToHours(float seconds) { //converts seconds into hours
int hours;
hours = floor(seconds / 3600);
return (hours);
}
How exactly are the seconds not incrementing properly?
The problem may be caused by the back and forth conversion between float and int. Personally, I would use an unsigned long instead of float, with the value in 10th's of a second. Also consider that a float is only accurate to seven significant digits, limiting your time to a bit less than 278 hours.
That's not a non blocking delay, it's just a delay made using millis and is just as blocking as the standard delay. Please read the examples of how to use millis.
Hi- the seconds on the lcd screen aren’t incrementing. They just show zero, and then when the minutes go to 1 the seconds show “0-60”. At two minutes I get “0-120”.
They are incrementing just fine on the serial display. That’s why I’m pretty sure the issue is somewhere in the functions that format the time for display
have a look at the sample code I provided in #2 as an example of a non blocking code and how to extract hour, minutes and seconds from a counter based on millis()
Definitely will once I’m back in front of the computer (had to move to the phone for a while and reading code there is difficult). Appreciate the help with the overall program. Still wouldn’t mind seeing where the glitch is in my code just for my own benefit
I commented on some lines that I found unnecessary and made a comment on a part of your code that I didn't understand the purpose of.
It's about the last digits on the LCD.
PS; I put a value of 3599 in both time variables to facilitate debugging.
float onTimeAccumulator = 3599; // total amount of time the pump is on
float offTimeAccumulator = 3599; // total amount of time the pump is off
See my modifications here or in the simulator.
#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); // Change to (0x27,20,4) for 20x4 LCD.
int period = 100; //time between increments- currently set to tenths of a second
float secondCounter = 0; //counts number of times the pump comes on- not currently implemented
int floatSwitchPin = 7; //which pin the float switch is connected to
boolean pumpOn = false; // State of the pump- starts as "off" (False) and switches to "on" (True when pin7 is shorted to ground)
boolean lastPumpState = false;
float onTimeAccumulator = 3599; // total amount of time the pump is on
float offTimeAccumulator = 3599; // total amount of time the pump is off
void setup() {
//start LCD screen
lcd.init();
lcd.backlight();
// Initialize sensor pin
pinMode(floatSwitchPin, INPUT_PULLUP);
// Open Serial monitor for debugging
Serial.begin(9600);
}
void loop() {
unsigned long time_now = millis();
if (pumpOn == true) { // Check to see if the pump is on
onTimeAccumulator = onTimeAccumulator + 0.1; //increase the onTimeAccumulator by 0.1 seconds each loop when pump is on
}
else { //pump is off
offTimeAccumulator = offTimeAccumulator + 0.1; //increase the offTimeAcccumulator by 0.1 seconds each loop when pump is off
}
//Debugging Serial Print Statements
printTime(0, 0, onTimeAccumulator);
printTime(0, 1, offTimeAccumulator);
/* Serial.print("onTimeAccumulator=");
Serial.print(onTimeAccumulator);
Serial.print(" offTimeAccumulator=");
Serial.print(offTimeAccumulator);
Serial.print(" pumpOn=");
Serial.println(pumpOn);
*/
while (millis() < time_now + period) { //non blocking delay
pumpOn = !digitalRead(floatSwitchPin);
}
}
void printTime(int x, int y, float seconds) { //Convert Seconds into user friendly display of HH:MM:SS.T
if (secondsToHours(seconds) > 99) {
x = x + 1; //If Seconds is bigger than 99 move over one column
}
lcd.setCursor(x, y); // Set col 0
if (secondsToHours(seconds) < 10) { //if hours is less than 10 add a leading 0
lcd.print("0"); //After print move to col 1
//lcd.setCursor(x + 1, y); //move over one column Set col 1 (unnecessary)
}
lcd.print(secondsToHours(seconds)); //print number of hours (using subroutine below)
lcd.setCursor(x + 2, y); //move over 2 columns // Set col 2
lcd.print(":"); //print the colon //After print move to col 3
//lcd.setCursor(x + 3, y); //move over 3 columns Set col 3 (unnecessary)
if (secondsToMinutes(seconds) - (secondsToHours(seconds) * 60) < 10) { //if number of minutes is less than 10 add a deading 0
lcd.print("0"); //After print move to col 4
// lcd.setCursor(x + 4, y); //move over Set col 4 (unnecessary)
}
lcd.print(secondsToMinutes(seconds) - (secondsToHours(seconds) * 60)); //print number of minutes (minus minutes accounted for as hours)
lcd.setCursor(x + 5, y); //position cursor Set col 5
lcd.print(":"); //print colon //After print move to col 6
//lcd.setCursor(x + 6, y); // position cursor Set col 6 (unnecessary)
// I don't understand what should happen with this part.
// I have modify to avoid neg. numbers
// ==========================================================================
/*
if (secondCounter - ((secondsToMinutes(seconds) * 60) + secondsToHours(seconds) * 3600) < 10) { //if number of seconds (minus seconds accounted for as minutes and as hours) is less than 10 add a leading zero
lcd.print("0"); //add a leading zeor
lcd.setCursor(x + 7, y); //move the cursor over
}
lcd.print(secondCounter - (((secondsToMinutes(seconds) * 60) + secondsToHours(seconds) * 3600)), 1); //print number of seconds (minus seconds accounted for as hours and minutes)
*/
// ==========================================================================
float newSecondCounter = secondCounter - ((secondsToMinutes(seconds) * 60) + secondsToHours(seconds) * 3600);
if (newSecondCounter < 0 )
newSecondCounter = newSecondCounter * -1;
if (newSecondCounter < 10) { //if number of seconds (minus seconds accounted for as minutes and as hours) is less than 10 add a leading zero
lcd.print("0"); //add a leading zeor //After print move to col 7
// lcd.setCursor(x + 7, y); //move the cursor over Set col 7 (unnecessary)
}
lcd.setCursor(x + 6, y); //move the cursor over
lcd.print(newSecondCounter, 1); //print number of seconds (minus seconds accounted for as hours and minutes)
// ===========================================================================
}
int secondsToMinutes(float seconds) { //converts seconds into minutes
int minutes;
minutes = floor(seconds / 60);
return (minutes);
}
int secondsToHours(float seconds) { //converts seconds into hours
int hours;
hours = floor(seconds / 3600);
return (hours);
}