Im using an LM35 temperature sensor and an LCD display (not I2C). When you run the program, the current temperature in celsius will be displayed on the top line of the LCD. The bottom line will display the maximum and minimum temperatures recorded since the first run. Pressing the push button will change the value from Celsius to Fahrenheit. Pressing again returns to Celsius. Im using the EEPROM to store the maximum and minimum temperature values. If you press the button for more than 3 seconds, the maximum and minimum values are reset.
Id like help setting up the push botton, maybe its a dumb question but what did i do wrong? I want to set it for pull down. Looking for general feedback with the code too, thanks!
#include <LiquidCrystal.h>
#include <EEPROM.h>
#define TEMP_SENSOR_PIN A0
#define BUTTON_PIN 8
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
bool isCelsius = true;
unsigned long buttonPressTime = 0;
bool buttonPressed = false;
bool buttonLongPress = false;
const int maxAddress = 0; // EEPROM address for max temperature
const int minAddress = sizeof(float); // EEPROM address for min temperature
float currentTemp;
float maxTemp;
float minTemp;
void setup() {
lcd.begin(16, 2);
pinMode(BUTTON_PIN, INPUT);
// Read max and min temperatures from EEPROM
EEPROM.get(maxAddress, maxTemp);
EEPROM.get(minAddress, minTemp);
// If EEPROM is empty (initial value is NaN), set max and min to current temperature
if (isnan(maxTemp) || isnan(minTemp)) {
maxTemp = -1000.0; // Start with a very low initial max
minTemp = 1000.0; // Start with a very high initial min
}
lcd.print("Temp: ");
lcd.setCursor(0, 1);
lcd.print(maxTemp);
lcd.print(minTemp);
}
void loop() {
currentTemp = readTemperature();
if (isCelsius) {
lcd.setCursor(6, 0);
lcd.print(currentTemp);
lcd.print(" C ");
} else {
lcd.setCursor(6, 0);
lcd.print(currentTemp * 9 / 5 + 32);
lcd.print(" F ");
}
if (currentTemp > maxTemp) {
maxTemp = currentTemp;
EEPROM.put(maxAddress, maxTemp);
}
if (currentTemp < minTemp) {
minTemp = currentTemp;
EEPROM.put(minAddress, minTemp);
}
lcd.setCursor(0, 1);
lcd.print(maxTemp);
lcd.print(" -- ");
lcd.print(minTemp);
if (digitalRead(BUTTON_PIN) == LOW) {
if (!buttonPressed) {
buttonPressed = true;
buttonPressTime = millis();
} else if (millis() - buttonPressTime > 3000) {
buttonLongPress = true;
}
} else {
if (buttonPressed) {
if (buttonLongPress) {
maxTemp = -1000.0;
minTemp = 1000.0;
EEPROM.put(maxAddress, maxTemp);
EEPROM.put(minAddress, minTemp);
buttonLongPress = false;
} else {
isCelsius = !isCelsius;
}
buttonPressed = false;
}
}
delay(500);
}
float readTemperature() {
int sensorValue = analogRead(TEMP_SENSOR_PIN);
float voltage = sensorValue * 5.0 / 1024.0;
return voltage * 100.0;
}
I can't give the code any more than a glance, at which it looks plausible.
If you want you presses to pull the input down (LOW), you have to pull the input up otherwise.
The easiest would be
pinMode(BUTTON_PIN, INPUT_PULLUP);
You could also use a resisitor, not critical 4K7 to 33K range, between the input pin and Vcc 5 volts.
Add
Serial.beign(115200);
to the setup() function and use printing to the serial monitor to see the flow through your program and confirm the values of the variables that inform the flow and calculations.
The "PULL_DOWN" option for configuring pinMode is available on a few Arduinos, but not Nano or Uno. Which board do you have?
Your drawing would be god for using pinMode(buttonPin, INPUT_PULLUP);... which is HIGH when the button is NOT pressed and LOW when the button IS pressed.
If you want to hardware-wire your button for PULL_DOWN, follow this Arduino page... where you will see the pull-down resistor connecting the data pin, through the Normally Closed contacts of the button then to ground. The Normally Open contacts will be connected to Vcc. A button wired like this will give you LOW when not pressed and HIGH when pressed.
@brunovendru I changed to INPUT_PULLUP, and added a millis()-based timer so the LCD gets updated on one schedule, and the poor man's debouncing delay was dropped to 50 milliseconds. This makes the pushbutton somewhat more responsive.
I did not test with either a temperature sensor or the LCD display. I just wanted to see the button logic functioning as it looked like it might. It does.
I marked most changes with a //... comment.
# include <LiquidCrystal.h>
# include <EEPROM.h>
# define TEMP_SENSOR_PIN A0
# define BUTTON_PIN 8
//... add an LED so we see we have pressed long enough
# define longPressLED 9
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
bool isCelsius = true;
unsigned long buttonPressTime = 0;
bool buttonPressed = false;
bool buttonLongPress = false;
const int maxAddress = 0; // EEPROM address for max temperature
const int minAddress = sizeof(float); // EEPROM address for min temperature
float currentTemp;
float maxTemp;
float minTemp;
void setup() {
//... how does anyone get anywhere without the serial monitor?
Serial.begin(115200);
Serial.println("\nReset Pushbutton World!\n");
lcd.begin(16, 2);
pinMode(BUTTON_PIN, INPUT_PULLUP); //... you need to pull it one way or another
pinMode(longPressLED, OUTPUT); //... oops! simulator doesn't need this!
// Read max and min temperatures from EEPROM
EEPROM.get(maxAddress, maxTemp);
EEPROM.get(minAddress, minTemp);
// If EEPROM is empty (initial value is NaN), set max and min to current temperature
if (isnan(maxTemp) || isnan(minTemp)) {
maxTemp = -1000.0; // Start with a very low initial max
minTemp = 1000.0; // Start with a very high initial min
}
lcd.print("Temp: ");
lcd.setCursor(0, 1);
lcd.print(maxTemp);
lcd.print(minTemp);
}
//... for LCD printing scheduler
unsigned long now;
void loop() {
//... only print temperatiure to the LCD every 777 milliseconds
now = millis();
static unsigned long lastLCDPrint;
if (now - lastLCDPrint > 777) {
lastLCDPrint = now;
currentTemp = readTemperature();
if (isCelsius) {
Serial.println("temp in C");
lcd.setCursor(6, 0);
lcd.print(currentTemp);
lcd.print(" C ");
}
else {
Serial.println("temp in F");
lcd.setCursor(6, 0);
lcd.print(currentTemp * 9 / 5 + 32);
lcd.print(" F ");
}
if (currentTemp > maxTemp) {
maxTemp = currentTemp;
EEPROM.put(maxAddress, maxTemp);
}
if (currentTemp < minTemp) {
minTemp = currentTemp;
EEPROM.put(minAddress, minTemp);
}
lcd.setCursor(0, 1);
lcd.print(maxTemp);
lcd.print(" -- ");
lcd.print(minTemp);
} //... every 777 milliseconds
//... one chage if you wire your switch differently
# define PRESST LOW
if (digitalRead(BUTTON_PIN) == PRESST) {
if (!buttonPressed) {
Serial.println(" buttonPressed -> true");
buttonPressed = true;
buttonPressTime = millis();
} else if (millis() - buttonPressTime > 3000) {
Serial.println(" buttonLongPress -> true");
digitalWrite(longPressLED, HIGH);
buttonLongPress = true;
}
} else {
if (buttonPressed) {
if (buttonLongPress) {
maxTemp = -1000.0;
minTemp = 1000.0;
Serial.println(" long press stores");
EEPROM.put(maxAddress, maxTemp);
EEPROM.put(minAddress, minTemp);
digitalWrite(longPressLED, LOW);
buttonLongPress = false;
} else {
isCelsius = !isCelsius;
Serial.println(" toggle C/F");
}
buttonPressed = false;
}
}
delay(50); //... poor man's debouncing
}
float readTemperature() {
int sensorValue = analogRead(TEMP_SENSOR_PIN);
float voltage = sensorValue * 5.0 / 1024.0;
return voltage * 100.0;
}
which looks like you destroy the values before you store them. Perhaps this is meant to reset minTemp and maxTemp, if so it would make more sense to do that after you hit the EEPROM.