#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
// Pin configuration
#define DHTPIN 2
#define MQ2PIN A1 // Analog pin for MQ2 sensor
#define SOUND_SENSOR_PIN A2 // Analog pin for sound sensor
#define BUZZERPIN 3
#define BUTTON1PIN 4
#define BUTTON2PIN 5
#define BUTTON3PIN 6
#define BUTTON4PIN 7 // Mute button
// DHT setup
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// LCD setup
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// Thresholds
const int temperatureThresholds[] = {85, 95, 90}; // Example thresholds, replace as needed
const int MQ2Threshold = 750;
const int numSoundSamples = 10; // Number of samples for averaging sound level
// Variables
int currentPage = 1;
bool buzzerActive = false;
bool buzzerMQ2Active = false;
bool buzzerMuted = false;
unsigned long buzzerStartTime = 0;
int currentThresholdIndex = 0;
unsigned long lastButtonPress = 0;
const unsigned long debounceDelay = 300; // Increase debounce time to 300 ms
unsigned long lastDHTRead = 0;
const unsigned long DHTReadInterval = 1000; // Interval to read DHT sensor (1 second)
// Custom character definitions
byte tempChar[] = {
0b00100,
0b01010,
0b01010,
0b01110,
0b11111,
0b11111,
0b01110,
0b00100
};
byte humidityChar[] = {
0B00100,
0B00100,
0B01010,
0B01010,
0B10001,
0B10001,
0B10001,
0B01110,
};
byte gasChar[] = {
0b10001, // * *
0b01010, // * *
0b10001, // * *
0b01010, // * *
0b10001, // * *
0b01010, // * *
0b10001, // * *
0b00000
};
byte soundChar[] = {
0b00000,
0b00100,
0b01110,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000
};
byte buzzerUnmutedChar[] = {
0b00100,
0b01110,
0b10101,
0b10101,
0b10101,
0b01110,
0b00100,
0b00000
};
byte buzzerMutedChar[] = {
0b00100,
0b01110,
0b10101,
0b11011,
0b10101,
0b01110,
0b00100,
0b00000
};
// Function declarations
void updateDisplay(float temperature = NAN, float humidity = NAN, int mq2Value = -1, float soundLevel = NAN);
void togglePage();
void manageBuzzer(float temperature, int mq2Value);
void scrollPresets();
void muteBuzzer();
float soundLevelToDB(int soundLevel);
float getAverageSoundLevel();
// Initialize setup()
void setup() {
// Initialize the LCD
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn on the backlight
// Initialize the DHT sensor
dht.begin();
// Set pin modes
pinMode(MQ2PIN, INPUT);
pinMode(SOUND_SENSOR_PIN, INPUT);
pinMode(BUZZERPIN, OUTPUT);
pinMode(BUTTON1PIN, INPUT_PULLUP);
pinMode(BUTTON2PIN, INPUT_PULLUP);
pinMode(BUTTON3PIN, INPUT_PULLUP);
pinMode(BUTTON4PIN, INPUT_PULLUP);
// Define custom characters
lcd.createChar(0, tempChar);
lcd.createChar(1, humidityChar);
lcd.createChar(2, gasChar);
lcd.createChar(3, soundChar);
lcd.createChar(4, buzzerUnmutedChar);
lcd.createChar(5, buzzerMutedChar);
// Display welcome message
lcd.setCursor(0, 0);
lcd.print("Welcome to your");
lcd.setCursor(0, 1);
lcd.print("Smart 3D Enclosure");
lcd.setCursor(0, 2);
lcd.print("Version 3.2.3");
delay(5000); // Display for 5 seconds
lcd.clear();
// Display initial page
updateDisplay();
}
void loop() {
unsigned long currentMillis = millis();
// Read button states with debounce
if (digitalRead(BUTTON1PIN) == LOW && (currentMillis - lastButtonPress) > debounceDelay) {
lastButtonPress = currentMillis;
togglePage();
}
if (digitalRead(BUTTON2PIN) == LOW && (currentMillis - lastButtonPress) > debounceDelay) {
lastButtonPress = currentMillis;
lcd.clear(); // Clear the display
}
if (digitalRead(BUTTON3PIN) == LOW && (currentMillis - lastButtonPress) > debounceDelay) {
lastButtonPress = currentMillis;
scrollPresets(); // Scroll through presets
}
if (digitalRead(BUTTON4PIN) == LOW && (currentMillis - lastButtonPress) > debounceDelay) {
lastButtonPress = currentMillis;
muteBuzzer(); // Mute/unmute buzzer
}
// Read DHT sensor only if the specified interval has passed
if (currentMillis - lastDHTRead >= DHTReadInterval) {
lastDHTRead = currentMillis;
float temperature = dht.readTemperature(true); // Temperature in Fahrenheit
float humidity = dht.readHumidity();
int mq2Value = analogRead(MQ2PIN);
float soundLevel = getAverageSoundLevel();
// Update display based on button interactions
updateDisplay(temperature, humidity, mq2Value, soundLevel);
// Check thresholds and manage buzzer
manageBuzzer(temperature, mq2Value);
}
delay(100); // Short delay for stability
}
void togglePage() {
currentPage = (currentPage == 1) ? 2 : (currentPage == 2) ? 3 : (currentPage == 3) ? 4 : 1;
lcd.clear(); // Clear the display to avoid overlapping content
updateDisplay(); // Update display based on the new page
}
void manageBuzzer(float temperature, int mq2Value) {
unsigned long currentTime = millis();
if (!buzzerMuted) {
if (temperature > temperatureThresholds[currentThresholdIndex]) {
if (!buzzerActive) {
buzzerActive = true;
buzzerStartTime = currentTime;
}
if (buzzerActive && (currentTime - buzzerStartTime >= 500)) {
tone(BUZZERPIN, 1000); // 1 kHz frequency
delay(500); // Buzzer on for 0.5 seconds
noTone(BUZZERPIN);
delay(9500); // Wait for 9.5 seconds
buzzerStartTime = millis(); // Reset buzzer start time
}
} else {
noTone(BUZZERPIN);
buzzerActive = false;
}
if (mq2Value > MQ2Threshold) {
if (!buzzerMQ2Active) {
buzzerMQ2Active = true;
buzzerStartTime = currentTime;
}
if (buzzerMQ2Active && (currentTime - buzzerStartTime >= 1500)) {
tone(BUZZERPIN, 1000); // 1 kHz frequency
delay(1500); // Buzzer on for 1.5 seconds
noTone(BUZZERPIN);
delay(8500); // Wait for 8.5 seconds
buzzerStartTime = millis(); // Reset buzzer start time
}
} else {
noTone(BUZZERPIN);
buzzerMQ2Active = false;
}
} else {
noTone(BUZZERPIN);
}
}
void updateDisplay(float temperature, float humidity, int mq2Value, float soundLevel) {
if (currentPage == 1) {
lcd.setCursor(0, 0);
lcd.write(0); // Temperature Icon
if (isnan(temperature)) {
lcd.print("NA");
} else {
lcd.print(temperature);
lcd.print(" F");
}
lcd.setCursor(0, 1);
lcd.write(1); // Humidity Icon
if (isnan(humidity)) {
lcd.print("NA");
} else {
lcd.print(humidity);
lcd.print(" %");
}
lcd.setCursor(0, 2);
lcd.write(2); // Gas Icon
lcd.print(" MQ2: ");
if (mq2Value == -1) {
lcd.print("NA");
} else {
lcd.print(mq2Value);
lcd.print(" ");
}
lcd.setCursor(0, 3);
lcd.print("Page 1");
} else if (currentPage == 2) {
lcd.setCursor(0, 0);
lcd.write(3); // Sound Icon
lcd.print(" ");
if (isnan(soundLevel)) {
lcd.print("NA");
} else {
lcd.print(soundLevel);
lcd.print(" dB");
}
lcd.setCursor(0, 1);
lcd.print("Preset Temp: ");
lcd.print(temperatureThresholds[currentThresholdIndex]);
lcd.setCursor(0, 2);
lcd.write(0); // Temperature Icon
lcd.print(" ");
if (isnan(temperature)) {
lcd.print("NA");
} else {
lcd.print(temperature);
lcd.print(" F");
}
lcd.setCursor(0, 3);
lcd.print("Page 2");
} else if (currentPage == 3) {
// Uptime calculation
unsigned long uptimeMillis = millis();
unsigned long uptimeSeconds = uptimeMillis / 1000;
unsigned long uptimeMinutes = uptimeSeconds / 60;
unsigned long uptimeHours = uptimeMinutes / 60;
unsigned long seconds = uptimeSeconds % 60;
unsigned long minutes = uptimeMinutes % 60;
unsigned long hours = uptimeHours;
lcd.setCursor(0, 0);
lcd.print("Uptime: ");
lcd.print(hours);
lcd.print("h ");
lcd.print(minutes);
lcd.print("m ");
lcd.print(seconds);
lcd.print("s");
lcd.setCursor(0, 1);
lcd.print("Version 3.2.3");
lcd.setCursor(0, 2);
lcd.print(" Buzzer: ");
lcd.write(buzzerMuted ? 5 : 4); // Buzzer Icon (Muted/Unmuted)
lcd.setCursor(0, 3);
lcd.print("Page 3");
} else if (currentPage == 4) {
lcd.setCursor(0, 0);
lcd.print("Made by Diego R");
lcd.setCursor(0, 1);
lcd.print("Jimenez");
lcd.setCursor(0, 2);
lcd.print("Page 4");
}
}
void scrollPresets() {
currentThresholdIndex = (currentThresholdIndex + 1) % (sizeof(temperatureThresholds) / sizeof(temperatureThresholds[0]));
updateDisplay();
}
void muteBuzzer() {
buzzerMuted = !buzzerMuted; // Toggle buzzer mute state
if (buzzerMuted) {
noTone(BUZZERPIN); // Ensure buzzer is off
}
}
float soundLevelToDB(int soundLevel) {
// Conversion logic for sound sensor to dB
return soundLevel * (5.0 / 1023.0) * 25; // Example conversion, adjust based on your sensor
}
float getAverageSoundLevel() {
int totalSoundLevel = 0;
for (int i = 0; i < numSoundSamples; i++) {
totalSoundLevel += analogRead(SOUND_SENSOR_PIN);
}
return soundLevelToDB(totalSoundLevel / numSoundSamples);
}