// max7219-clock-dht.ino
// Código modificado: removido Fahrenheit, traduzido para Português.
// Header file includes
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <DHT.h>
#include <SPI.h>
#include <Wire.h>
#include "Font7Seg.h"
// Define the number of devices we have in the chain and the hardware interface
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4 // Define o número de displays conectados
#define CLK_PIN 13 // CLK or SCK
#define DATA_PIN 11 // DATA or MOSI
#define CS_PIN 10 // CS or SS
#define SPEED_TIME 75 // Velocidade da transição
#define PAUSE_TIME 0
#define MAX_MESG 20
// RTC DS1307
#define DS1307_ADDRESS 0x68
// DHT22
#define DHTPIN 2
#define DHTTYPE DHT22
#define TIMEDHT 1000
// Global variables
uint8_t wday, mday, month, year;
uint8_t hours, minutes, seconds;
char szTime[9]; // mm:ss\0
char szMesg[MAX_MESG + 1] = "";
float humidity, celsius, fahrenheit;
// Caractere customizado para Grau Celsius ($)
uint8_t degC[] = {6, 3, 3, 56, 68, 68, 68 }; // Deg C
uint8_t clear = 0x00;
uint32_t timerDHT = TIMEDHT;
DHT dht(DHTPIN, DHTTYPE);
// Hardware SPI connection
MD_Parola P = MD_Parola (HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
void beginDS1307()
{
// Read the values (date and time) of the DS1307 module
Wire.beginTransmission (DS1307_ADDRESS);
Wire.write(clear);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 0x07);
seconds = bcdToDec(Wire.read());
minutes = bcdToDec(Wire.read());
hours = bcdToDec(Wire.read() & 0xff);
wday = bcdToDec(Wire.read());
mday = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
}
uint8_t decToBcd(uint8_t value)
{
return ((value / 10 * 16) + (value % 10));
}
uint8_t bcdToDec(uint8_t value)
{
return ((value / 16 * 10) + (value % 16));
}
void getTime(char *psz, bool f = true)
{
sprintf(psz, "%02d%c%02d", hours, (f?':': ' '), minutes);
}
void getDate(char *psz)
{
char szBuf[10];
sprintf(psz, "%d %s %04d", mday, mon2str(month, szBuf, sizeof(szBuf) - 1), (year + 2000));
}
void getTemperature()
{
if ((millis() - timerDHT) > TIMEDHT) {
timerDHT = millis();
humidity = dht.readHumidity();
celsius = dht.readTemperature();
fahrenheit = dht.readTemperature(true);
if (isnan(humidity) || isnan (celsius) || isnan(fahrenheit)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
}
}
char *mon2str(uint8_t mon, char *psz, uint8_t len)
{
static const __FlashStringHelper* str[] =
{
// Meses traduzidos (sem acentos)
F("Jan"), F("Fev"),
F("Mar"), F("Abr"),
F("Mai"), F("Jun")
,
F("Jul")
,
F("Ago"),
F("Set"), F("Out")
,
F("Nov"), F("Dez")
};
strncpy_P(psz, (const char PROGMEM *)str[mon - 1], len);
psz[len] = '\0';
return (psz);
}
char *dow2str(uint8_t code, char *psz, uint8_t len)
{
static const __FlashStringHelper* str[] =
{
// Dias da Semana traduzidos (sem acentos)
F("Domingo"), F("Segunda-Feira"), F("Terca-Feira"),
F("Quarta-Feira"), F("Quinta-Feira"), F("Sexta-Feira"),
F("Sabado")
};
strncpy_P(psz, (const char PROGMEM *)str[code - 1], len);
psz[len] = '\0';
return (psz);
}
void setup(void)
{
Wire.begin();
P.begin(2);
P.setInvert(false);
P.setZone(0, MAX_DEVICES - 4, MAX_DEVICES - 1);
P.setZone(1, MAX_DEVICES - 4, MAX_DEVICES - 1);
P.displayZoneText(1, szTime, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
P.displayZoneText(0, szMesg, PA_CENTER, SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT);
// Adiciona caractere customizado para Grau Celsius
P.addChar('$', degC);
dht.begin();
}
void loop(void)
{
static uint32_t lastTime = 0; // Memory (ms)
static uint8_t display = 0; // Current display mode
static bool flasher = false; // Seconds passing flasher
beginDS1307();
getTemperature();
P.displayAnimate();
if (P.getZoneStatus(0))
{
switch (display)
{
case 0: // Temperatura em Graus Celsius (ºC)
P.setPause(0, 1000);
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_UP);
display++; // Próximo: case 1 (Umidade)
dtostrf(celsius, 3, 1, szMesg);
strcat(szMesg, "$");
break;
case 1: // Umidade (Humidity)
P.setTextEffect(0, PA_SCROLL_DOWN, PA_SCROLL_LEFT);
display++; // Próximo: case 2 (Relógio)
dtostrf(humidity, 3, 0, szMesg);
strcat(szMesg, "%UR");
break;
case 2: // Relógio (Clock)
P.setFont(0, numeric7Seg);
P.setTextEffect(0, PA_PRINT, PA_NO_EFFECT);
P.setPause(0, 0);
if ((millis() - lastTime) >= 1000)
{
lastTime = millis();
getTime(szMesg, flasher);
flasher = !flasher;
}
if ((seconds == 0) && (seconds <= 30)) {
display++; // Próximo: case 3 (Dia da semana)
P.setTextEffect(0, PA_PRINT, PA_WIPE_CURSOR);
}
break;
case 3: // Dia da semana (Day of week)
P.setFont(0, nullptr);
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display++; // Próximo: default (Calendário)
dow2str(wday, szMesg, MAX_MESG);
break;
default: // Calendário (Calendar)
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display = 0; // Volta para Temperatura ºC
getDate(szMesg);
break;
}
P.displayReset(0); // Reseta a Zona Zero para o novo efeito/texto
}
}