Tự làm gương thông minh với Raspberry Pi
Gương thông minh là dự án vừa đẹp vừa thực dụng: mỗi sáng soi gương đánh răng, bạn tiện thể liếc qua giờ giấc và thời tiết mà không cần cầm điện thoại lên. Phần khó nhất thực ra không phải là điện tử — mà là phần cơ khí ghép mica và khung. Còn phần mềm thì chỉ là một trang web full-screen chạy nền trên trình duyệt.
Nguyên lý hoạt động
- Phần vật lý: dán một lớp phim mica hai chiều (two-way acrylic mirror film) lên một tấm kính hoặc mica trong suốt. Phía sau tấm này đặt một màn hình LCD/LED thường (tháo từ TV cũ hoặc màn máy tính cũ đều được), và Raspberry Pi giấu phía sau cùng, tất cả gói trong một khung ảnh.
- Lớp phim hai chiều hoạt động như gương ở phía có ánh sáng mạnh hơn (phòng), nhưng để ánh sáng từ vùng tối hơn (màn hình phía sau) xuyên qua được. Vì vậy, nền trang web phải là màu đen tuyệt đối — pixel đen coi như “tắt”, chỉ pixel sáng (chữ trắng, icon) mới xuyên qua lớp mica và hiện thành chữ nổi trên mặt gương.
- Raspberry Pi chạy Chromium ở chế độ kiosk (full màn hình, không thanh địa chỉ, không viền), tự khởi động ngay khi cắm điện, hiển thị một trang HTML đơn giản có đồng hồ và widget thời tiết.
Linh kiện
- Raspberry Pi (Pi 4 khuyến nghị để render mượt, Pi 3 vẫn chạy được)
- Màn hình LCD cũ (tháo phần vỏ nhựa, chỉ giữ lại tấm panel + mạch điều khiển)
- Phim mica gương hai chiều (two-way mirror acrylic film), kích thước bằng màn hình
- Khung ảnh hoặc khung gỗ tự đóng để chứa toàn bộ cụm
- Thẻ microSD, nguồn 5V cho Pi, và nguồn riêng cho màn hình
Code mẫu
Trang HTML/CSS/JS full-screen, nền đen, hiển thị đồng hồ và nhiệt độ lấy từ API thời tiết công khai:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Gương thông minh</title>
<style>
body { background: #000; color: #fff; font-family: 'Helvetica Neue', sans-serif; margin: 0; overflow: hidden; }
#clock { font-size: 6rem; text-align: center; margin-top: 10vh; font-weight: 200; }
#weather { text-align: center; font-size: 2rem; opacity: 0.85; }
</style>
</head>
<body>
<div id="clock"></div>
<div id="weather">Đang tải thời tiết...</div>
<script>
function updateClock() {
const now = new Date();
document.getElementById('clock').textContent =
now.toLocaleTimeString('vi-VN', { hour: '2-digit', minute: '2-digit' });
}
setInterval(updateClock, 1000);
updateClock();
async function updateWeather() {
try {
// Thay LAT/LON bang toa do thuc te noi dat guong
const res = await fetch('https://api.open-meteo.com/v1/forecast?latitude=LAT&longitude=LON¤t=temperature_2m');
const data = await res.json();
const temp = data.current.temperature_2m;
document.getElementById('weather').textContent = `${temp}°C`;
} catch (err) {
document.getElementById('weather').textContent = 'Khong lay duoc du lieu thoi tiet';
}
}
updateWeather();
setInterval(updateWeather, 10 * 60 * 1000); // cap nhat moi 10 phut
</script>
</body>
</html>
Tự động mở Chromium ở chế độ kiosk khi Pi khởi động — tạo file ~/.config/autostart/mirror.desktop:
[Desktop Entry]
Type=Application
Name=SmartMirror
Exec=chromium-browser --kiosk --noerrdialogs --disable-infobars --incognito file:///home/pi/mirror/index.html
Thêm vào ~/.config/lxsession/LXDE-pi/autostart để tắt chế độ tiết kiệm màn hình và ẩn con trỏ chuột (cần cài unclutter):
@xset s off
@xset -dpms
@xset s noblank
@unclutter -idle 0.5
Những lỗi thường gặp
- Nền không phải màu đen tuyệt đối (ví dụ dùng ảnh nền hoặc xám đậm) làm cả vùng đó hiện lờ mờ trên mặt gương thay vì “biến mất” — luôn dùng
#000thuần chobody. - Không tắt chế độ tiết kiệm màn hình (DPMS) khiến màn hình tự tắt sau vài phút không có thao tác chuột/bàn phím — gương thông minh không có input nên chắc chắn sẽ bị tắt nếu quên bước này.
- Lớp mica hai chiều làm giảm độ sáng đáng kể (thường 60-70%), nên cần chỉnh độ sáng màn hình lên tối đa mới đủ rõ chữ xuyên qua gương.
- API thời tiết miễn phí có thể giới hạn số lần gọi — không nên fetch quá thường xuyên, 10-15 phút một lần là hợp lý.
Mở rộng
Thêm cảm biến PIR để màn hình chỉ sáng khi có người đứng trước gương (tiết kiệm điện và tăng tuổi thọ panel), tích hợp thông báo từ MQTT/nhà thông minh, hoặc thêm widget lịch/to-do từ một feed JSON riêng.
Bình luận