#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#include <avr/io.h>
#include <avr/interrupt.h>
// Definizione dei pin e del tipo di sensore
#define DHTPINint 12
#define DHTPINest 13
#define DHTTYPE DHT22
// Pin dei pulsanti
#define BUTTON_INC_PIN 2 // Aumento temperatura, collegato a PD2
#define BUTTON_DEC_PIN 3 // Diminuzione temperatura, collegato a PD3
// Macro per scrittura e lettura pin digitali
#define writeDigitalValue(port, pin, value) ((value) ? ((port) |= (pin)) : ((port) &= ~(pin)))
#define readDigitalValue(port, pin) ((port & (1 << pin)) != 0)
// Inizializzazione dei sensori DHT
DHT dhtint(DHTPINint, DHTTYPE);
DHT dhtest(DHTPINest, DHTTYPE);
// Inizializzazione LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
volatile bool readTemperatureFlag = false; // Flag per la lettura periodica dei DHT22
volatile bool updateLcdFlag = false; // Flag per aggiornare periodicamente lo schermo LCD
volatile bool controlActive = false; // Flag per attivare/disattivare il controllo della temperatura
volatile int setTemperature = 22; // Temperatura desiderata iniziale
volatile float tempInt, tempEst, humInt, humEst;
uint16_t co2val = 0;
// Aggiungi variabili per gestione debounce
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // Millisecondi
void setup() {
// Configurazione dei pin
DDRC = DDRC | B00001;
DDRD = DDRD | B00111100;
DDRB = DDRB | B110000;
// Configura i pin dei pulsanti come input
pinMode(BUTTON_INC_PIN, INPUT_PULLUP); // Abilita pull-up interno su PD2
pinMode(BUTTON_DEC_PIN, INPUT_PULLUP); // Abilita pull-up interno su PD3
// Configurazione LCD
lcd.init();
lcd.backlight();
// Avvio dei sensori DHT
dhtint.begin();
dhtest.begin();
// Configurazione Timer1 per lettura della temperatura (2 secondi)
TCCR1A = 0; // Modalità CTC
TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10); // Prescaler 1024
OCR1A = 31250; // 2 secondi con 16MHz di clock e prescaler 1024
TIMSK1 = (1 << OCIE1A); // Abilita l'interruzione per il confronto A
// Configurazione Timer2 per aggiornamento LCD (1 secondo)
TCCR2A = (1 << WGM21); // Modalità CTC
TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20); // Prescaler 1024
OCR2A = 15624; // 1 secondo con 16MHz di clock e prescaler 1024
TIMSK2 = (1 << OCIE2A); // Abilita l'interruzione per il confronto A
// Abilita gli interrupt per i pulsanti
PCICR |= (1 << PCIE2); // Abilita interrupt per PCINT23..16 (PORTD)
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // Abilita interrupt per PD2 (PCINT18) e PD3 (PCINT19)
sei(); // Abilita le interruzioni globali
}
void loop() {
// Se il flag di lettura della temperatura è impostato
if (readTemperatureFlag) {
readTemperatureFlag = false; // Resetta il flag
// Lettura delle temperature e umidità
tempInt = dhtint.readTemperature();
tempEst = dhtest.readTemperature();
humInt = dhtint.readHumidity();
humEst = dhtest.readHumidity();
// Controllo del valore della CO2
co2val = map(analogRead(A0), 0, 1023, 500, 1500);
// Logica per il controllo dei pin in base alle temperature e alla CO2
if (co2val > 1200) {
if (tempEst > tempInt) {
writeDigitalValue(PORTB, (1 << PB2), HIGH); // Pin 10 su HIGH
writeDigitalValue(PORTB, (1 << PB0), LOW); // Pin 8 su LOW
} else {
writeDigitalValue(PORTB, (1 << PB0), HIGH); // Pin 8 su HIGH
writeDigitalValue(PORTB, (1 << PB2), LOW); // Pin 10 su LOW
}
} else {
writeDigitalValue(PORTB, (1 << PB2), LOW); // Pin 10 su LOW
writeDigitalValue(PORTB, (1 << PB0), LOW); // Pin 8 su LOW
}
}
// Se il flag di aggiornamento dell'LCD è impostato
if (updateLcdFlag) {
updateLcdFlag = false; // Resetta il flag
// Visualizzazione dei dati su LCD
lcd.setCursor(0, 0);
lcd.print("Temp. Impostata:");
lcd.setCursor(17, 0);
lcd.print(setTemperature);
lcd.setCursor(0, 1);
lcd.print("Temp. Int.: ");
lcd.print(tempInt);
lcd.setCursor(0, 2);
lcd.print("Temp. Est.: ");
lcd.print(tempEst);
lcd.setCursor(0, 3);
lcd.print(controlActive ? "Controllo: ON " : "Controllo: OFF");
}
}
// Interruzione per lettura periodica della temperatura (ogni 2 secondi)
ISR(TIMER1_COMPA_vect) {
readTemperatureFlag = true; // Imposta il flag per la lettura della temperatura
}
// Interruzione per la gestione dei pulsanti
ISR(PCINT2_vect) {
// Gestione dei pulsanti con debounce
unsigned long currentTime = millis();
if ((currentTime - lastDebounceTime) > debounceDelay) {
lastDebounceTime = currentTime;
// Leggi i valori dei pulsanti
if (digitalRead(BUTTON_INC_PIN) == LOW) {
// Gestisci il pulsante collegato a PD2 (es. pulsante A, per aumentare la temperatura)
setTemperature++;
}
if (digitalRead(BUTTON_DEC_PIN) == LOW) {
// Gestisci il pulsante collegato a PD3 (es. pulsante B, per diminuire la temperatura)
setTemperature--;
}
// Aggiorna flag per aggiornare LCD dopo il cambiamento
updateLcdFlag = true;
}
}
// Interruzione per aggiornare il display LCD (ogni 1 secondo)
ISR(TIMER2_COMPA_vect) {
updateLcdFlag = true; // Imposta il flag per l'aggiornamento dell'LCD
}