Va salut !
Si inca un montaj cu excelentul Wemos D1 mini : ceas cu matrice de leduri, cu senzor de temperatura DS18B20. Are efect de scroll a afisarii. Testat, functioneaza perfect. L-am montat in bucatarie, iar senzorul de temperatura l-am scos in balcon. Succes !
// Ceas matrice LED cu ora automata vara/iarna + DS18B20
// Conexiuni : DS18B20 la D2 ; matrice DIN - D8 ; CS - D7 ; CLK - D6
#include <ESP8266WiFi.h> #include <time.h> #include <MD_MAX72xx.h> #include <SPI.h> #include <OneWire.h> #include <DallasTemperature.h>
const char* ssid = "your_ssid";
const char* password = "your_psw";
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define DATA_PIN D8
#define CS_PIN D7
#define CLK_PIN D6
MD_MAX72XX matrix(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ONE_WIRE_BUS D2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
#define H1_START 25
#define H2_START 17
#define M1_START 8
#define M2_START 0
uint8_t lastH1 = 99, lastH2 = 99, lastM1 = 99, lastM2 = 99;
int lastHour = -1, lastMinute = -1;
// ===== FONT 6x8 =====
static const uint8_t dig6x8[] PROGMEM = {
7, 0x06, 0x7E, 0xFF, 0x81, 0x81, 0xFF, 0x7E,
0x06, 0x00, 0x82, 0xFF, 0xFF, 0x80, 0x00,
0x06, 0x82, 0xC3, 0xE1, 0xB1, 0x9F, 0xCE,
0x06, 0x42, 0xC3, 0x89, 0x89, 0xFF, 0x76,
0x06, 0x38, 0x24, 0xA2, 0xFF, 0xFF, 0xA0,
0x06, 0x4F, 0xCF, 0x89, 0x89, 0xF9, 0x71,
0x06, 0x7E, 0xFF, 0x89, 0x89, 0xFB, 0x72,
0x06, 0x03, 0x03, 0xF1, 0xF9, 0x0F, 0x07,
0x06, 0x76, 0xFF, 0x89, 0x89, 0xFF, 0x76,
0x06, 0x4E, 0xDF, 0x91, 0x91, 0xFF, 0x7E
};
// ===== FUNCȚII GRAFICE =====
void clearDigit(int posX) {
for (int r = 0; r < 8; r++)
for (int c = 0; c < 5; c++)
matrix.setPoint(r, posX + c, false);
}
void rollUpDigit(int newDigit, int posX) {
int w = pgm_read_byte(&dig6x8[0]);
int off = newDigit * w + 1;
uint8_t buf[8] = {0};
for (int c = 0; c < w - 1; c++)
buf[c] = pgm_read_byte(&dig6x8[off + (w - 1 - c)]);
for (int s = 0; s < 10; s++) {
for (int r = 0; r < 7; r++)
for (int c = 0; c < w - 1; c++)
matrix.setPoint(r, posX + c, matrix.getPoint(r + 1, posX + c));
for (int c = 0; c < w - 1; c++)
matrix.setPoint(7, posX + c, s >= 2 ? (buf[c] & (1 << (s - 2))) : false);
matrix.update();
delay(30);
}
}
void drawClock(int hour, int minute, bool dots) {
matrix.setPoint(2, 15, dots);
matrix.setPoint(5, 15, dots);
matrix.update();
}
// ===== SETUP =====
void setup() {
Serial.begin(115200);
matrix.begin();
matrix.control(MD_MAX72XX::INTENSITY, 1);
matrix.clear();
sensors.begin();
sensors.setWaitForConversion(true);
// WiFi cu animatie
WiFi.begin(ssid, password);
Serial.print("Conectare WiFi");
int wifiDots = 0;
while (WiFi.status() != WL_CONNECTED) {
matrix.clear();
for (int i = 0; i <= wifiDots; i++)
matrix.setPoint(4, 2 + i, true);
matrix.update();
wifiDots = (wifiDots + 1) % 28;
delay(500);
Serial.print(".");
}
Serial.println(" conectat");
// NTP + DST România
configTime("EET-2EEST,M3.5.0/3,M10.5.0/4", "pool.ntp.org");
struct tm t;
while (!getLocalTime(&t)) delay(500);
matrix.clear();
}
// ===== LOOP =====
void loop() {
struct tm t;
if (!getLocalTime(&t)) return;
int sec = t.tm_sec;
static bool tempMode = false;
static unsigned long tempStart = 0;
// ---- AFISARE TEMPERATURA ----
if ((sec == 15 || sec == 45) && !tempMode) {
matrix.clear();
sensors.requestTemperatures();
float temp = sensors.getTempCByIndex(0);
bool ok = !isnan(temp) && temp >= -50 && temp <= 125;
if (!ok) {
// Afiseaza "---" pe pozitiile temperaturii
for (int pos : {17, 8, 0}) {
for (int c = 1; c <= 4; c++) {
matrix.setPoint(3, pos + c, true);
}
}
} else {
bool neg = temp < 0;
if (neg) temp = -temp;
if (temp > 99.9) temp = 99.9;
int whole = (int)temp;
int dec = (int)((temp - whole) * 10 + 0.5);
int a = (whole >= 10) ? whole / 10 : -1; // zeci
int b = whole % 10; // unitati
int c = dec; // zecimala
// MUTĂ DOAR zecile și unitățile cu o coloană la stânga
if (a >= 0) {
rollUpDigit(a, 17); // zeci: 16 → 17, 1 la stanga
}
rollUpDigit(b, 9); // unitati: 8 → 9, 1 la stanga
// PUNCTUL ZECIMAL RĂMÂNE NEMODIFICAT la (7,7)
matrix.setPoint(7, 7, true);
rollUpDigit(c, 0); // zecimala
// Semn minus - ajustat pentru noua poziție a zecilor
if (neg) {
// 21 = 15 (start zeci) + 6 (lățime digit)
for (int i = 1; i <= 4; i++) {
matrix.setPoint(3, 21 + i, true);
}
}
}
matrix.update();
tempMode = true;
tempStart = millis();
}
if (tempMode) {
if (millis() - tempStart >= 5000) {
tempMode = false;
matrix.clear();
lastH1 = lastH2 = lastM1 = lastM2 = 99;
lastHour = lastMinute = -1;
}
return;
}
// ---- CEAS ----
static unsigned long blinkT = 0;
static bool dots = false;
if (millis() - blinkT > 500) {
dots = !dots;
drawClock(t.tm_hour, t.tm_min, dots);
blinkT = millis();
}
if (t.tm_hour == lastHour && t.tm_min == lastMinute) return;
uint8_t h1 = t.tm_hour / 10;
uint8_t h2 = t.tm_hour % 10;
uint8_t m1 = t.tm_min / 10;
uint8_t m2 = t.tm_min % 10;
if (m2 != lastM2) { rollUpDigit(m2, M2_START); lastM2 = m2; }
if (m1 != lastM1) { rollUpDigit(m1, M1_START); lastM1 = m1; }
if (h2 != lastH2) { rollUpDigit(h2, H2_START); lastH2 = h2; }
if (h1 != lastH1) {
if (h1) rollUpDigit(h1, H1_START);
else clearDigit(H1_START);
lastH1 = h1;
}
lastHour = t.tm_hour;
lastMinute = t.tm_min;
}
Niciun comentariu:
Trimiteți un comentariu