O projeto consiste em montar um gerenciador inteligente para cuidar da chocadeira sozinha com viragem de ovo a cada 2 horas set de temperatura, contagem de dias.
Lista de material e :
LCD Nokia5110 o que estou utilizando e o modelo AZUL.
Arduino UNO ou similar
DHT22
Rele simples para o vira ovo
Rele solido para resistência
Resistencia para chocadeira
O código para o Arduino
#include <Adafruit_PCD8544.h>
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22
#define RELAY_PIN 3
#define BUTTON_UP 4
#define BUTTON_DOWN 5
#define BUTTON_SELECT 6
#define LDR_PIN A0 // Pino analógico para o LDR
#define BACKLIGHT_PIN 7 // Pino digital para controlar o transistor do backlight
// pin 8 - Serial clock out (SCLK)
// pin 9 - Serial data out (DIN)
// pin 10 - Data/Command select (D/C)
// pin 11 - LCD chip select (CS/CE)
// pin 12 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 11, 12);
DHT dht(DHTPIN, DHTTYPE);
// Variáveis para o menu
int menuOption = -1; // -1 significa tela principal
int targetTemp = 377; // 37.7°C como padrão
unsigned long startTime;
bool heatingOn = false;
unsigned long lastToggle = 0;
// Variáveis para ajustar a data
int setDay = 1;
int setMonth = 1;
int setYear = 2024;
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_SELECT, INPUT_PULLUP);
pinMode(BACKLIGHT_PIN, OUTPUT);
digitalWrite(BACKLIGHT_PIN, LOW); // Inicialmente desligado
display.begin();
display.setContrast(47);
display.clearDisplay();
display.display();
dht.begin();
startTime = millis();
}
void loop() {
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
int days = (millis() - startTime) / (1000 * 60 * 60 * 24);
// Leitura do LDR e controle do backlight
int ldrValue = analogRead(LDR_PIN);
if (ldrValue < 500) {
digitalWrite(BACKLIGHT_PIN, HIGH);
} else {
digitalWrite(BACKLIGHT_PIN, LOW);
}
// Navegação no menu com o botão SELECT
if (digitalRead(BUTTON_SELECT) == LOW) {
menuOption++;
if (menuOption > 3) {
menuOption = -1; // Volta para a tela principal
}
delay(200); // Atraso para evitar múltiplos incrementos acidentais
}
// Executa a ação de acordo com a opção do menu
if (menuOption == 0) { // Ajuste do dia
adjustDay();
} else if (menuOption == 1) { // Ajuste do mês
adjustMonth();
} else if (menuOption == 2) { // Ajuste do ano
adjustYear();
} else if (menuOption == 3) { // Ajuste da temperatura
adjustTemperature(temp, humidity, days);
} else { // Tela principal
controlHeating(temp);
displayMainScreen(temp, humidity, days);
}
}
void adjustDay() {
if (digitalRead(BUTTON_UP) == LOW) {
setDay++;
if (setDay > 31) setDay = 1;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
setDay--;
if (setDay < 1) setDay = 31;
delay(100);
}
displayDate();
}
void adjustMonth() {
if (digitalRead(BUTTON_UP) == LOW) {
setMonth++;
if (setMonth > 12) setMonth = 1;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
setMonth--;
if (setMonth < 1) setMonth = 12;
delay(100);
}
displayDate();
}
void adjustYear() {
if (digitalRead(BUTTON_UP) == LOW) {
setYear++;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
setYear--;
delay(100);
}
displayDate();
}
void adjustTemperature(float temp, float humidity, int days) {
if (digitalRead(BUTTON_UP) == LOW) {
targetTemp++;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
targetTemp--;
delay(100);
}
displayMenu(temp, humidity, days);
}
void displayMainScreen(float temp, float humidity, int days) {
display.clearDisplay();
display.setCursor(0, 0);
// Exibe a data configurada pelo usuário no formato DD/MM/AA
display.print("Data: ");
if (setDay < 10) display.print("0");
display.print(setDay);
display.print("/");
if (setMonth < 10) display.print("0");
display.print(setMonth);
display.print("/");
display.print(setYear % 100); // Exibe os dois últimos dígitos do ano
display.setCursor(0, 10);
display.print("Temp: ");
display.print(temp);
display.print(" C");
display.setCursor(0, 20);
display.print("Umid: ");
display.print(humidity);
display.print(" %");
display.setCursor(0, 30);
display.print("Dias: ");
display.print(days);
display.display();
}
void displayMenu(float temp, float humidity, int days) {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Set Temp:");
display.setCursor(0, 10);
display.print(targetTemp / 10.0);
display.print(" C");
display.setCursor(0, 20);
display.print("Atual: ");
display.print(temp);
display.print(" C");
display.setCursor(0, 30);
display.print("Dias: ");
display.print(days);
display.display();
}
void displayDate() {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Set Date:");
display.setCursor(0, 10);
display.print("Day: ");
display.print(setDay);
display.setCursor(0, 20);
display.print("Month: ");
display.print(setMonth);
display.setCursor(0, 30);
display.print("Year: ");
display.print(setYear % 100); // Exibe apenas os últimos 2 dígitos do ano
display.display();
}
void controlHeating(float temp) {
unsigned long currentTime = millis();
// Lógica para alternar o estado do relé a cada 2 horas
if (currentTime - lastToggle >= 2 * 60 * 60 * 1000) { // A cada 2 horas
if (temp < (targetTemp / 10.0)) {
digitalWrite(RELAY_PIN, HIGH);
heatingOn = true;
} else {
digitalWrite(RELAY_PIN, LOW);
heatingOn = false;
}
lastToggle = currentTime;
}
// Lógica para desativar o relé 3 dias antes do término
unsigned long elapsedDays = (currentTime - startTime) / (1000 * 60 * 60 * 24);
if (elapsedDays >= 18) { // Faltando 3 dias
if (temp >= (targetTemp / 10.0) && heatingOn) {
digitalWrite(RELAY_PIN, LOW);
heatingOn = false;
}
}
}
Agora com um SD card para caso venha ocorrer desligamento ou falta de energia.
#include <Adafruit_PCD8544.h>
#include <DHT.h>
#include <SPI.h>
#include <SD.h>
#define DHTPIN 2
#define DHTTYPE DHT22
#define RELAY_PIN 3
#define BUTTON_UP 4
#define BUTTON_DOWN 5
#define BUTTON_SELECT 6
#define LDR_PIN A0 // Pino analógico para o LDR
#define BACKLIGHT_PIN 7 // Pino digital para controlar o transistor do backlight
#define SD_CS_PIN 10 // Pino de seleção do cartão SD
// pin 8 - Serial clock out (SCLK)
// pin 9 - Serial data out (DIN)
// pin 10 - Data/Command select (D/C)
// pin 11 - LCD chip select (CS/CE)
// pin 12 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 11, 12);
DHT dht(DHTPIN, DHTTYPE);
// Variáveis para o menu
int menuOption = -1; // -1 significa tela principal
int targetTemp = 377; // 37.7°C como padrão
unsigned long startTime;
bool heatingOn = false;
unsigned long lastToggle = 0;
// Variáveis para ajustar a data
int setDay = 1;
int setMonth = 1;
int setYear = 2024;
// Variáveis para data log
unsigned long logInterval = 10000; // Intervalo de log em milissegundos
unsigned long lastLogTime = 0;
File logFile;
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_SELECT, INPUT_PULLUP);
pinMode(BACKLIGHT_PIN, OUTPUT);
digitalWrite(BACKLIGHT_PIN, LOW); // Inicialmente desligado
display.begin();
display.setContrast(47);
display.clearDisplay();
display.display();
dht.begin();
// Inicializa o cartão SD
if (!SD.begin(SD_CS_PIN)) {
display.clearDisplay();
display.setCursor(0, 0);
display.print("SD Card failed");
display.display();
while (1); // Pare o programa se o SD falhar
}
// Abre o arquivo de log para leitura
logFile = SD.open("datalog.txt", FILE_READ);
if (logFile) {
// Lê o último log para recuperar o estado
String lastLine = "";
while (logFile.available()) {
lastLine = logFile.readStringUntil('\n');
}
logFile.close();
// Parse the last line for state restoration
int dayIndex = lastLine.indexOf("Day: ");
int monthIndex = lastLine.indexOf("Month: ");
int yearIndex = lastLine.indexOf("Year: ");
int tempIndex = lastLine.indexOf("Temp: ");
if (dayIndex > -1) setDay = lastLine.substring(dayIndex + 5, monthIndex - 1).toInt();
if (monthIndex > -1) setMonth = lastLine.substring(monthIndex + 7, yearIndex - 1).toInt();
if (yearIndex > -1) setYear = lastLine.substring(yearIndex + 5, tempIndex - 1).toInt();
} else {
// Cria o arquivo de log se não existir
logFile = SD.open("datalog.txt", FILE_WRITE);
if (!logFile) {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Failed to open log");
display.display();
while (1); // Pare o programa se falhar ao abrir o arquivo
}
}
// Define startTime para o momento atual
startTime = millis();
}
void loop() {
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
int days = (millis() - startTime) / (1000 * 60 * 60 * 24);
// Leitura do LDR e controle do backlight
int ldrValue = analogRead(LDR_PIN);
if (ldrValue < 500) {
digitalWrite(BACKLIGHT_PIN, HIGH);
} else {
digitalWrite(BACKLIGHT_PIN, LOW);
}
// Navegação no menu com o botão SELECT
if (digitalRead(BUTTON_SELECT) == LOW) {
menuOption++;
if (menuOption > 3) {
menuOption = -1; // Volta para a tela principal
}
delay(200); // Atraso para evitar múltiplos incrementos acidentais
}
// Executa a ação de acordo com a opção do menu
if (menuOption == 0) { // Ajuste do dia
adjustDay();
} else if (menuOption == 1) { // Ajuste do mês
adjustMonth();
} else if (menuOption == 2) { // Ajuste do ano
adjustYear();
} else if (menuOption == 3) { // Ajuste da temperatura
adjustTemperature(temp, humidity, days);
} else { // Tela principal
controlHeating(temp);
displayMainScreen(temp, humidity, days);
}
// Data log
unsigned long currentTime = millis();
if (currentTime - lastLogTime >= logInterval) {
logData(temp, humidity, days);
lastLogTime = currentTime;
}
}
void adjustDay() {
if (digitalRead(BUTTON_UP) == LOW) {
setDay++;
if (setDay > 31) setDay = 1;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
setDay--;
if (setDay < 1) setDay = 31;
delay(100);
}
displayDate();
}
void adjustMonth() {
if (digitalRead(BUTTON_UP) == LOW) {
setMonth++;
if (setMonth > 12) setMonth = 1;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
setMonth--;
if (setMonth < 1) setMonth = 12;
delay(100);
}
displayDate();
}
void adjustYear() {
if (digitalRead(BUTTON_UP) == LOW) {
setYear++;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
setYear--;
delay(100);
}
displayDate();
}
void adjustTemperature(float temp, float humidity, int days) {
if (digitalRead(BUTTON_UP) == LOW) {
targetTemp++;
delay(100);
}
if (digitalRead(BUTTON_DOWN) == LOW) {
targetTemp--;
delay(100);
}
displayMenu(temp, humidity, days);
}
void displayMainScreen(float temp, float humidity, int days) {
display.clearDisplay();
display.setCursor(0, 0);
// Exibe a data configurada pelo usuário no formato DD/MM/AA
display.print("Data: ");
if (setDay < 10) display.print("0");
display.print(setDay);
display.print("/");
if (setMonth < 10) display.print("0");
display.print(setMonth);
display.print("/");
display.print(setYear % 100); // Exibe os dois últimos dígitos do ano
display.setCursor(0, 10);
display.print("Temp: ");
display.print(temp);
display.print(" C");
display.setCursor(0, 20);
display.print("Umid: ");
display.print(humidity);
display.print(" %");
display.setCursor(0, 30);
display.print("Dias: ");
display.print(days);
display.display();
}
void displayMenu(float temp, float humidity, int days) {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Set Temp:");
display.setCursor(0, 10);
display.print(targetTemp / 10.0);
display.print(" C");
display.setCursor(0, 20);
display.print("Atual: ");
display.print(temp);
display.print(" C");
display.setCursor(0, 30);
display.print("Dias: ");
display.print(days);
display.display();
}
void displayDate() {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Set Date:");
display.setCursor(0, 10);
display.print("Day: ");
display.print(setDay);
display.setCursor(0, 20);
display.print("Month: ");
display.print(setMonth);
display.setCursor(0, 30);
display.print("Year: ");
display.print(setYear % 100); // Exibe apenas os últimos 2 dígitos do ano
display.display();
}
void controlHeating(float temp) {
unsigned long currentTime = millis();
// Lógica para alternar o estado do relé a cada 2 horas
if (currentTime - lastToggle >= 2 * 60 * 60 * 1000) { // A cada 2 horas
if (temp < (targetTemp / 10.0)) {
digitalWrite(RELAY_PIN, HIGH);
heatingOn = true;
} else {
digitalWrite(RELAY_PIN, LOW);
heatingOn = false;
}
lastToggle = currentTime;
}
// Lógica para desativar o relé 3 dias antes do término
unsigned long elapsedDays = (currentTime - startTime) / (1000 * 60 * 60 * 24);
if (elapsedDays >= 18) { // Faltando 3 dias
if (temp >= (targetTemp / 10.0) && heatingOn) {
digitalWrite(RELAY_PIN, LOW);
heatingOn = false;
}
}
}
void logData(float temp, float humidity, int days) {
// Construa uma string com os dados
String logEntry = String(setDay) + "/" + String(setMonth) + "/" + String(setYear % 100) + ", " +
String(temp) + " C, " + String(humidity) + " %, " + String(days) + " days\n";
logFile = SD.open("datalog.txt", FILE_WRITE);
if (logFile) {
logFile.print(logEntry);
logFile.flush(); // Garante que os dados sejam escritos no cartão SD
logFile.close();
}
}