I’m trying to display sensor readings on my 20x4 I2C LCD using an ESP32. I have two push buttons connected with external pull-up resistors. The goal is that when I press the “Next” button, the LCD should switch to displaying readings from other sensors.
However, the system only works correctly for a few seconds. After that, the sensor readings start showing negative values unexpectedly. I’m confident that my circuit is correct. I’m using a PCF8574 I2C module, powered from the ESP32’s onboard 3.3V supply.
Below is my code:
// ========================================
// COMBINED SENSOR DISPLAY WITH NAVIGATION
// MQ7 Gas Sensor + BMP280 + LCD 20x4
// ========================================
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <LiquidCrystal_I2C.h>
// ========================================
// PIN CONFIGURATION
// ========================================
#define SDA_PIN 21
#define SCL_PIN 22
#define BUTTON_NEXT 16 // Next button pin
#define BUTTON_BACK 17 // Back button pin
#define MQ7_PIN 36 // MQ7 analog pin
// ========================================
// SENSOR SETTINGS
// ========================================
#define SEA_LEVEL_PRESSURE_HPA 1013.25
// ========================================
// HARDWARE OBJECTS
// ========================================
Adafruit_BMP085 bmp; // BMP280/BMP180 sensor
LiquidCrystal_I2C lcd(0x27, 20, 4); // 20x4 LCD
// ========================================
// BUTTON VARIABLES
// ========================================
int buttonNextState = 0;
int buttonBackState = 0;
int lastButtonNextState = 0;
int lastButtonBackState = 0;
int currentScreen = 0; // Current display screen
int totalScreens = 2; // Total number of screens
// ========================================
// HELPER FUNCTION: Display text on LCD
// ========================================
void printLine(uint8_t row, const char *text) {
char buffer[21];
snprintf(buffer, sizeof(buffer), "%-20s", text);
lcd.setCursor(0, row);
lcd.print(buffer);
}
// ========================================
// SETUP: Initialize hardware
// ========================================
void setup() {
// Start serial communication
Serial.begin(115200);
// Setup button pins
pinMode(BUTTON_NEXT, INPUT);
pinMode(BUTTON_BACK, INPUT);
// Initialize I2C with custom pins
Wire.begin(SDA_PIN, SCL_PIN);
Wire.setClock(10000);
// Initialize LCD
lcd.begin();
lcd.backlight();
lcd.clear();
// Display startup message
printLine(0, "Sensor Monitor");
printLine(1, "Initializing...");
// Check if BMP sensor is connected
if (!bmp.begin()) {
printLine(2, "BMP280 NOT FOUND!");
printLine(3, "Check connections");
while (1); // Halt if sensor not found
}
printLine(2, "BMP280: OK");
printLine(3, "MQ7: Ready");
delay(2000);
lcd.clear();
}
// ========================================
// MAIN LOOP: Handle buttons and display
// ========================================
void loop() {
// Read button states
buttonNextState = digitalRead(BUTTON_NEXT);
buttonBackState = digitalRead(BUTTON_BACK);
// Check NEXT button press
if (buttonNextState != lastButtonNextState) {
if (buttonNextState == HIGH) {
currentScreen++;
if (currentScreen >= totalScreens) {
currentScreen = 0; // Wrap to first screen
}
lcd.clear();
delay(50); // Debounce
}
}
lastButtonNextState = buttonNextState;
// Check BACK button press
if (buttonBackState != lastButtonBackState) {
if (buttonBackState == HIGH) {
currentScreen--;
if (currentScreen < 0) {
currentScreen = totalScreens - 1; // Wrap to last screen
}
lcd.clear();
delay(50); // Debounce
}
}
lastButtonBackState = buttonBackState;
// Display current screen
displayScreen();
// Update delay
delay(500);
}
// ========================================
// DISPLAY FUNCTION: Show current screen
// ========================================
void displayScreen() {
char displayText[21];
if (currentScreen == 0) {
// ====================================
// SCREEN 1: BMP280 Data
// ====================================
float temperature = bmp.readTemperature();
long pressurePascals = bmp.readPressure();
float pressureHpa = pressurePascals / 100.0;
float altitude = bmp.readAltitude(SEA_LEVEL_PRESSURE_HPA * 100);
// Display header
printLine(0, "=== BMP280 Data ===");
// Temperature
snprintf(displayText, sizeof(displayText), "Temp: %.1f%cC", temperature, 223);
printLine(1, displayText);
// Pressure
snprintf(displayText, sizeof(displayText), "Press: %.1f hPa", pressureHpa);
printLine(2, displayText);
// Altitude
snprintf(displayText, sizeof(displayText), "Alt: %.1f m", altitude);
printLine(3, displayText);
} else if (currentScreen == 1) {
// ====================================
// SCREEN 2: MQ7 Gas Sensor Data
// ====================================
int coValue = analogRead(MQ7_PIN);
// Display header
printLine(0, "==== MQ7 Sensor ====");
// CO reading
snprintf(displayText, sizeof(displayText), "CO Level: %d", coValue);
printLine(1, displayText);
// Status based on threshold
if (coValue < 400) {
printLine(2, "Status: SAFE");
} else if (coValue < 800) {
printLine(2, "Status: WARNING");
} else {
printLine(2, "Status: DANGER!");
}
// Navigation hint
printLine(3, "Next/Back to navigate");
}
}