Trong bài này chúng ta sẽ làm một đồng hồ với thời gian được cập nhật tự động qua Internet bằng kết nối Wifi. Ngoài ra đồng hồ còn hiển thị thông số môi trường như nhiệt độ và độ ẩm. Khác với những bài trước, LED ma trận sẽ được sử dụng cho phần hiển thị.
Thiết bị đầu tiên cần có là một bộ NodeMCU. Có thể sử dụng Arduino nhưng NodeMCU sẽ giúp chúng ta tận dụng tính năng kết nối Wifi với chip wifi ESP có sẵn.
Thiết bị thứ hai là cảm biến môi trường, loại rẻ tiền đơn giản nhất là DHT11. Khi kết nối DHT 11 với vi điều khiển, cần chú ý sử dụng điện trở treo cao tại chân Data. Nếu mạch DHT11 gắn sẵn điện trở thì ta chỉ cần nối dây theo đúng vị trí chân.
Thiết bị quan trọng nhất là chip giải mã MAX7219. Nó giúp đơn giản hóa việc hiển thị trên LED ma trận. Các mạch đèn ma trận gắn sẵn MAX7219 có giá thành không quá cao, kích thước nhỏ gọn, bao gồm cả chip thường và chip dán. Tuy nhiên LED ma trận có kích thước giới hạn và chỉ hỗ trợ 1 màu. Điện áp sử dụng theo khuyến cáo là 5V.
Với mạch LED gắn sẵn MAX7219, khi lập trình ta cần bổ sung đầy đủ các thư viện. Với một bo 4 đèn LED ma trận, ta có thể sử dụng nguồn 3,3V từ NodeMCU vì dòng ra vẫn đảm bảo. Nếu sử dụng nhiều LED hơn, ta phải dùng nguồn riêng nuôi LED (chân đất gắn chung giữa các mạch).
Có thể xem lại những bài trước để bổ sung thư viện cho ESP và DHT. Thư viện NTPClient có thể bổ sung trực tiếp bằng Library Manager.
Thư viện MAX7219 có thể tải của MarkRuys hoặc tại đây
Chương trình như sau:
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <SPI.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
const char *ssid = "abc";
const char *password = "xyz";
#define pinCS D6
// LED pin --> ESP
// DIN --> D7
// CS --> D6
// CLK --> D5
#define DHTPin D4
#define DHTTYPE DHT11
//String date;
String weatherString;
int refresh = 0;
int HorizontalDisplays = 4; // Số Lượng Led Matrix Ngang
int VerticalDisplays = 1; // Số Lượng Led Matrix dọc
int t = 0;
int h = 0;
Max72xxPanel matrix = Max72xxPanel(pinCS, HorizontalDisplays, VerticalDisplays);
//
int wait = 50; // tốc độ chạy
int spacer = 2;
int width = 5 + spacer; // Khoảng cách ký tự có thể điều chỉnh
//
DHT dht(DHTPin, DHTTYPE);
WiFiUDP ntpUDP;
// By default 'pool.ntp.org' is used with 60 seconds update interval and
// no offset
NTPClient timeClient(ntpUDP, "3.asia.pool.ntp.org", 7*3600, 60000);
// You can specify the time server pool and the offset, (in seconds)
// additionaly you can specify the update interval (in milliseconds).
// NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
void setup()
{
Serial.begin(115200);
dht.begin();
pinMode(DHTPin, INPUT);
matrix.setIntensity(7); // điều chỉnh độ sáng 0-15
// Tọa Độ Led Matrix bắt đầu 8 * 8
matrix.setRotation(0, 1); // 1
matrix.setRotation(1, 1); // 2
matrix.setRotation(2, 1); // 3
matrix.setRotation(3, 1); // 4
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED )
{
delay ( 500 );
Serial.print ( "." );
}
Serial.println( "Got Wifi" );
timeClient.begin();
}
void loop()
{
h = dht.readHumidity();
t = dht.readTemperature();
hienthi_t_h();
DisplayTime();
delay(10000);
}
void hienthi_t_h()
{
ScrollText("Hello");
ScrollText("I'm OK");
weatherString = "Temp:" + String(t) + "`C";
ScrollText(weatherString);
weatherString = "Hum:" + String(h) + "%";
ScrollText(weatherString);
}
// =======================================================================
void DisplayTime()
{
timeClient.update();
matrix.fillScreen(LOW);
int y = (matrix.height() - 8) / 2;
matrix.drawChar(14, y, (String(":"))[0], HIGH, LOW,1);
String hour1 = String (timeClient.getHours() / 10);
String hour2 = String (timeClient.getHours() % 10);
String min1 = String (timeClient.getMinutes() / 10);
String min2 = String (timeClient.getMinutes() % 10);
int xh = 2;
int xm = 19;
matrix.drawChar(xh, y, hour1[0], HIGH, LOW, 1);
matrix.drawChar(xh + 7, y, hour2[0], HIGH, LOW, 1);
matrix.drawChar(xm, y, min1[0], HIGH, LOW, 1);
matrix.drawChar(xm + 7, y, min2[0], HIGH, LOW, 1);
matrix.write();
}
// =======================================================================
void ScrollText (String text)
{
for ( int i = 0 ; i < width * text.length() + matrix.width() - 1 - spacer; i++ )
{
if (refresh == 1)
i = 0;
refresh = 0; matrix.fillScreen(LOW); int letter = i / width; int x = (matrix.width() - 1) - i % width; int y = (matrix.height() - 8) / 2; while ( x + width - spacer >= 0 && letter >= 0 ) { if ( letter < text.length() ) { matrix.drawChar(x, y, text[letter], HIGH, LOW, 1); } letter--; x -= width; } matrix.write(); delay(wait);
}
}