Thiết bị bật tắt Moderm Wifi tự động – Một dự án về việc hẹn giờ

Dự án này mình đã hoàn thiện vào cuối năm 2015. Tuy nhiên bây giờ mới có thời gian giới thiệu tới các bạn. Gia đình bạn có sử dụng wifi và những lúc không sử dụng bạn muốn tắt nó đi để tránh ảnh hưởng của sóng wifi tới sức khỏe, đặc biệt là với trẻ nhỏ. Dựa trên lí do đó mình đã làm 1 thiết bị có khả năng tự bật tắt wifi theo thời gian định sẵn, có thể điều khiển từ xa và học lệnh các loại điều khiển.enlightened Qua bài viết này, hi vọng nhận được nhiều ý kiến đóng góp từ các bạn đồng thời nâng cấp thêm nhiều tính năng cho thiết bị.wink

1. Chuẩn bị

2. Bắt đầu

Phần cứng các bạn kết nối như sau:

Arduino DS1307 LCD5510 IR LED NÚT NHẤN RELAY
3 SCLK
4 DIN
5 DC
6 CS
7 RST
10 DATA
11 DATA
12 LIGHT
A0 DOWN
A1 UP
A2 SETUP
SDA SDA
SCL SCL
GND GND GND GND GND
5V VCC VCC VCC VCC

Đừng vội hoang mang nhé, các bạn chỉ cần nối chân lần lượt từng module với arduino theo thứ tự trên thôi wink!

 mặt saumặt trước

3. Các thư viện có liên quan

  • <SPI.h> Thư viện giao tiếp SPI giữa Arduino với LCD 5510 (đã có mặc định trong Library)
  • <Adafruit_GFX.h> Thư viện đồ họa
  • <Adafruit_PCD8544.h> Thư viện điều khiển LCD 5510
  • <Wire.h> Thư viện giao tiếp với module thời gian thực DS1307 (đã có mặc định trong Library mặc định của Arduino)
  • <IRremote.h> Thư viện cho IR LED
  • <IRremoteInt.h> Thư viện cho IR LED
  • <string.h> Thư viện xử lý chuỗi (dùng cho việc xử lý chuỗi khi học mã IR từ Remote) (đã có mặc định trong Library)
  • <EEPROM.h> Thư viện EEPROM để thao tác lưu mã IR vào bộ nhớ (đã có mặc định trong Library)

Các bạn có thể down các thư viện chưa có tại đây (mirror), sau đó giải nén và đưa vào thư mục C:\Program Files\Arduino\libraries\

Có 1 lưu ý nho nhỏ đó là thư viện IRremote, IRremoteInt ở trong thư mục library mặc định của arduino nó không hoạt động được theo cách của mình, vì vậy trước khi copy thư viện của mình vào mục thư viện của các bạn thì các bạn xóa thư viện IRremote mặc định đi nhé

4. Lập trình

Trước khi đến phần lập trình, mình xin diễn giải sơ bộ như sau:

Arduino được kết nối với module thời gian thực DS1307 để có được thông số thời gian chính xác, sau đó hiển thị lên LCD 5510, Căn cứ vào thời gian đó, Arduino sẽ điều khiển cho Module Relay bật hoặc tắt.

Các bạn có thể tham khảo thêm về việc sử dụng module DS1307 trong vài viết của bác NTP_PRO yes

Và bài viết về cách sử dụng LCD 5510 của bác ksp nhé yes

Led Thu hồng ngoại (IR LED) được kết nối với arduino có tác dụng nhận tín hiệu hồng ngoại từ điều khiển từ xa (Remote), điều khiển từ xa sẽ truyền 1 chuỗi tín hiệu, led thu đọc được và arduino sẽ xử lý tín hiệu. Mình lấy ví dụ đơn giản đối với điều khiển tivi: khi nhấn nút nguồn trên điều khiển, led phát trên điều khiển sẽ gửi 1 chuỗi tín hiệu dạng : XXXXXXXXXX (x là các kí tự bất kì). Và tất nhiên với mỗi 1 nút trên điều khiển sẽ tương ứng với 1 chuỗi cố định. Led thu nhận được chuỗi XXXXXXXXX đó truyền cho arduino và arduino sẽ thực hiện xử lý theo chương trình.  Các bạn cũng có thể tham khảo thêm phần giao tiếp với IR LED trong bài viết nữa của bác NTP_PRO yes

ok, giờ thì làm tách cafe và bắt đầu thôi!!! wink

  1. #include <SPI.h>
  2. #include <Adafruit_GFX.h>
  3. #include <Adafruit_PCD8544.h>
  4. #include <Wire.h>
  5. #include <IRremote.h>
  6. #include <IRremoteInt.h>
  7. #include <string.h>
  8. #include <EEPROM.h>
  9. int RECV_PIN = 10; // gán giá trị chân của IR LED là 10
  10. int IRLength=0; // Gán độ dài của chuỗi kí tự
  11. String IRCode, ReadIR[12],CodeRemote;// mã IRCode: giá trị IR đọc từ EEPROM, ReadIR: Đọc IR từ Led thu, CodeRemote giá trị IR từ Led thu
  12. String StrCode[12]=“”; // Giới hạn độ dài chuỗi
  1. int StringLength=0;
  2. int i=0,CountSET=0;
  3. IRrecv irrecv(RECV_PIN); // Khai báo chân của IR LED
  1.  
  2. /* Địa chỉ của DS1307 */
  3. const byte DS1307 = 0x68;
  4. /* Số byte dữ liệu sẽ đọc từ DS1307 */
  5. const byte NumberOfFields = 7;
  6. /* khai báo các biến thời gian */
  7. int second, minute, hour, day, wday, month, year, count=0, countT=0;
  8. long TimeBD=0,TimeHT=0,Time=0;
  9.  
  10. int StateWifi=0; // Trạng thái của relay
  11. int StateCurent=0;
  12. int CountWF =0, CountIF=0,CountClear=0,value=0; // các biến đếm
  13. char* State;
  14. char* thu;
  15.  
  16. Adafruit_PCD8544 display = Adafruit_PCD8544(3, 4, 5, 6, 7);
  17. const int SETUP =A2; // nút Setup
  18. const int UP =A1; // nút up
  19. const int DOWN =A0; // nút down
  20. int StateSETUP=0,StateUP=0,StateDOWN=0; // trạng thái các nút
  21. void setup() {
  22. pinMode(12, OUTPUT); // khai báo chân 12 là chân out (chân LIGHT của LCD) dùng để điều khiển bật tắt đèn nền LCD
  23. pinMode(11, OUTPUT); // Chân của relay
  24. pinMode(DOWN, INPUT_PULLUP);
  25. pinMode(UP, INPUT_PULLUP);
  26. pinMode(SETUP, INPUT_PULLUP);
  27. display.begin(); // Bắt đầu hiển thị LCD
  28. display.clearDisplay(); // Xóa màn hình
  29. Wire.begin(); //Khởi tạo kết nối với DS1307
  30. irrecv.enableIRIn(); // Băt đầu nhận tín hiệu từ remote
  31. /* cài đặt thời gian cho module */
  32. //setTime(12, 30, 45, 1, 8, 2, 15); // 12:30:45 CN 08-02-2015 Phần này các bạn xem trong mục chú thích
  33. IRLength=EEPROM.read(50); // Đọc dữ liệu trong eeprom
  34. }
  35.  
  36.  
  37. void loop() {
  38. readDS1307(); // đọc thời gian trong ds1307
  39. Check_State(); // kiểm tra lại trạng thái của relay
  40. Hen_Gio(); // hàm hẹn giờ bật – tắt
  41. WIFI(); // hàm hiện thỉ trạng thái hiện tại của wifi đang bật hay tắt
  42. StateSETUP= digitalRead(SETUP);
  43. StateUP= digitalRead(UP);
  44. StateDOWN= digitalRead(DOWN);
  45. // nhấn là 0(LOW), bình thường là 1(HIGH)
  46. if(StateSETUP==0) // khi nút setup được nhấn giữ
  47. { digitalWrite(12, LOW); // đèn nền sáng
  48. SetTime(); // hàm chỉnh sửa thời gian hiện tại
  49.  
  50. }
  51. else
  52. {
  53. digitalWrite(12, HIGH); // đèn nền tắt
  54.  
  55. }
  56. ////////////////
  57. if(StateSETUP!=0)
  58. {
  59. Button_ON_OFF();// nếu nút setup không được nhấn, hàm kiểm tra trạng thái nút on – off sẽ khởi chạy
  60.  
  61. }
  62. else
  63. {
  64.  
  65. }
  66. if (irrecv.decode(&results))
  67. {
  68. RemoteIR();
  69. IRrecord();
  70. irrecv.resume(); // Receive the next value
  71. }
  72. if (StateWifi!=StateCurent) // Nếu trạng thái của relay hiện tại khác với trạng thái relay ban đầu
  73. {
  74. LED_LCD();// Hàm tự đông tắt đèn nền của LCD sau 10 giây. Điều này có nghĩa là cứ có 1 thay đổi trạng thái relay thì đèn nền sẽ sáng, sau 10 giây tự động tắt
  75. }
  76. HienThiGio();// Hàm hiển thị thời gian
  77. Clear_Display(); // Xóa màn hình để cập nhật thời gian liên tục lên LCD
  78. }
  79.  
  80. void readDS1307() // Hàm xử lý thời gian
  81. {
  82. Wire.beginTransmission(DS1307);
  83. Wire.write((byte)0x00);
  84. Wire.endTransmission();
  85. Wire.requestFrom(DS1307, NumberOfFields);
  86. second = bcd2dec(Wire.read() & 0x7f);
  87. minute = bcd2dec(Wire.read() );
  88. hour = bcd2dec(Wire.read() & 0x3f); // chế độ 24h.
  89. wday = bcd2dec(Wire.read() );
  90. day = bcd2dec(Wire.read() );
  91. month = bcd2dec(Wire.read() );
  92. year = bcd2dec(Wire.read() );
  93. year += 2000;
  94. }
  95. /* Chuyển từ format BCD (Binary-Coded Decimal) sang Decimal */
  96. int bcd2dec(byte num)
  97. {
  98. return ((num/16 * 10) + (num % 16));
  99. }
  100. /* Chuyển từ Decimal sang BCD */
  101. int dec2bcd(byte num)
  102. {
  103. return ((num/10 * 16) + (num % 10));
  104. }
  105. void HienThiGio()
  106. {
  107. display.setTextSize(2);
  108. display.setTextColor(BLACK);
  109. display.setCursor(15,10);
  110. display.print(hour);
  111. display.print(“:”);
  112. display.print(minute);
  113. display.setTextSize(1);
  114. display.setTextColor(BLACK);
  115. display.setCursor(2,0);
  116. display.print(thu);
  117. if (thu!=“CN”)
  118. {
  119. display.print(wday);
  120. }
  121. display.print(“:”);
  122. display.print(day);
  123. display.print(“:”);
  124. display.print(month);
  125. display.print(“:”);
  126. display.print(year);
  127. display.display();
  128. if (second==59)
  129. {
  130. display.clearDisplay();
  131. }
  132. if (wday==1)
  133. {
  134. thu=“CN”;
  135. }
  136. else
  137. {
  138. thu=“T”;
  139. }
  140. }
  141.  
  142.  
  143. /* cài đặt thời gian cho DS1307 */
  144. void setTime(byte hr, byte min, byte sec, byte wd, byte d, byte mth, byte yr)
  145. {
  146. Wire.beginTransmission(DS1307);
  147. Wire.write(byte(0x00)); // đặt lại pointer
  148. Wire.write(dec2bcd(sec));
  149. Wire.write(dec2bcd(min));
  150. Wire.write(dec2bcd(hr));
  151. Wire.write(dec2bcd(wd)); // day of week: Sunday = 1, Saturday = 7
  152. Wire.write(dec2bcd(d));
  153. Wire.write(dec2bcd(mth));
  154. Wire.write(dec2bcd(yr));
  155. Wire.endTransmission();
  156. }
  157. void Hen_Gio()
  158. {
  159. // Mình đặt thời gian để relay ngắt là từ 22h đêm đến 4h59
  160. if (((hour==22) ||(hour==23) ||(hour==0) ||(hour==1) ||(hour==2) ||(hour==3) ||(hour==4)) && (count==0))
  161. {
  162. digitalWrite(11, LOW); //relay ngắt
  163. StateWifi=0; // gán trạng thái của wifi =0
  164. count=1;// đặt biến đếm =1
  165. }
  166. if (((hour==5) ||(hour==6) ||(hour==7)) && (count==1)) // thời gian mở lại relay là từ 5h đến 7h59
  167. {
  168. digitalWrite(11, HIGH); // relay đóng
  169. StateWifi=1; // gán trạng thái wifi = 1
  170. count=0; // đặt biến đếm =0
  171. }
  172. if (((hour==8)|| (hour==9)||(hour==10)) && (count==0)&& ( (wday==2)||(wday==3)||(wday==4)||(wday==5)||(wday==6)))
  173. {
  174. digitalWrite(11, LOW);
  175. StateWifi=0;
  176. count=1;
  177. }
  178. if (((hour==11)||(hour==12)||(hour==13)) && ( (wday==2)||(wday==3)||(wday==4)||(wday==5)||(wday==6)) && (count==1))
  179. {
  180. digitalWrite(11, HIGH);
  181. StateWifi=1;
  182. count=0;
  183. }
  184. if (((hour==14)||(hour==15)||(hour==16))&& ( (wday==2)||(wday==3)||(wday==4)||(wday==5)||(wday==6)) && (count==0))
  185. {
  186. digitalWrite(11, LOW);
  187. StateWifi=0;
  188. count=1;
  189. }
  190. if (((hour==17)||(hour==18)||(hour==19)||(hour==20)||(hour==21)) && ( (wday==2)||(wday==3)||(wday==4)||(wday==5)||(wday==6)) && (count==1))
  191. {
  192. digitalWrite(11, HIGH);
  193. StateWifi=1;
  194. count=0;
  195. }
  196.  
  197. }
  198. void LED_LCD()
  199. {
  200. digitalWrite(12, LOW); // đèn nền sáng
  201.  
  202. if (countT==0) // nếu biến countT=0
  203. {
  204. TimeBD= ((hour*3600) + (minute*60) + second); // Thời gian ban đầu = tổng số giây tại thời điểm hiện tại
  205. countT=1; // gán biến đếm =1 để đảm bảo nó sẽ không thực hiện lại dòng lệnh bên trên quá 1 lần
  206. }
  207. TimeHT=abs(((hour*3600) + (minute*60) + second) TimeBD); // thời gian hiện tại = tổng số giây tại thời điểm hiện tại – thời gian ban đầu
  208. if (TimeHT>=10) // nếu thời gian hiện tại >= 10
  209. {
  210. digitalWrite(12, HIGH); // đèn nền tắt
  211. countT=0; // gán biến đếm CountT=0
  212. StateCurent=StateWifi; // Gán trạng thái wifi
  213. }
  214. }
  215. void WIFI()
  216. {
  217. display.setTextSize(1);
  218. display.setTextColor(BLACK);
  219. display.setCursor(0,30);
  220. display.print(“WiFi”);
  221. display.print(“:”);
  222. display.setTextSize(2);
  223. display.setTextColor(BLACK);
  224. if (StateWifi==1)
  225. {
  226. digitalWrite(11, HIGH);
  227. State=“ON”;
  228. //display.clearDisplay();
  229. }
  230. if (StateWifi==0)
  231. {
  232. digitalWrite(11, LOW);
  233. State=“OFF”;
  234. // display.clearDisplay();
  235. }
  236. display.println(State);
  237. display.display();
  238. if ((second==59) || (second==0)) // hàm này có tác dụng cập nhật lại trạng thái wifi trên màn hình
  239. {
  240. display.clearDisplay();
  241. }
  242. }
  243. void Check_State() // hàm này để kiểm tra lại trạng thái relay
  244. {
  245. if ((hour==5) ||(hour==6) ||(hour==7) ||(hour==11) ||(hour==12) ||(hour==13) ||(hour==17)||(hour==18)||(hour==19)||(hour==20)
  246. ||(hour==21))
  247. {
  248. if (CountIF==0) {
  249. StateCurent=0;
  250. StateWifi=1;
  251. count=1;
  252. CountIF=1;
  253. }
  254. }
  255. if ((hour==22) ||(hour==23) ||(hour==0) ||(hour==1) ||(hour==2) ||(hour==3) ||(hour==4)||(hour==8)||(hour==9)||(hour==10)
  256. ||(hour==14)||(hour==15)||(hour==16))
  257. {
  258. if (CountWF==0)
  259. {
  260. count=0;
  261. StateCurent=1;
  262. StateWifi=0;
  263. CountWF=1;
  264. }
  265. }
  266. }
  267. void Clear_Display()
  268. {
  269. if (CountClear==0)
  270. {
  271. display.clearDisplay();
  272. CountClear=1;
  273. }
  274. }
  275. void RemoteIR() // hàm xử lý tín hiệu hồng ngoại
  276. {
  277. for (i=0;i<IRLength;i++)
  278. {
  279. ReadIR[i]=EEPROM.read(i)-48; // đọc giá trị đã được lưu trong eeprom sau đó – 48 để
  280. delay(10);
  281. }
  282. IRCode=ReadIR[0]; // gán giá trị đã đọc được vào biến IRCode
  283. for(i=1;i<IRLength;i++)
  284. {
  285. IRCode+=ReadIR[i];
  286. delay(10);
  287. }
  288. if(StateSETUP!=0) // nếu nút setup không được nhấn
  289. {
  290. CodeRemote=(results.value); // gán giá trị hồng ngoại nhận được vào CodeRemote
  291. if (CodeRemote==IRCode) // nếu giá trị nhận được = giá trị đã lưu trong eeprom
  292. {
  293. if (StateWifi==1) // nếu trạng thái wifi đã gán =1 tức là relay đang đóng
  294. {
  295. StateWifi=0; // thì sẽ chuyển trạng thái wifi = 0 đồng thời relay mở
  296. display.clearDisplay(); // xóa màn hình để cập nhật trạng thái trên màn hình
  297. }
  298. else if (StateWifi==0)
  299. {
  300. StateWifi=1;
  301. display.clearDisplay();
  302. }
  303. }
  304. }
  305. }
  306. void IRrecord() // hàm học mã hồng ngoại và lưu vào eeprom
  307. {
  308. if(StateSETUP==0) // nếu nhấn giữ nút setup
  309. {
  310. StrCode[12]=(results.value); // gán giá trị nhận được vào mảng StrCode
  311. StringLength=StrCode[12].length(); // Đọc độ dài mảng
  312. EEPROM.write(50,StringLength);// ghi giá trị đọc được và eeprom
  313. for(i=0;i<StringLength;i++)
  314. {
  315. EEPROM.write(i,StrCode[12].charAt(i));
  316. delay(10);
  317. }
  318. }
  319.  
  320. }
  321. void SetTime() // hàm điều chỉnh thời gian
  322. {
  323. readDS1307();
  324. display.clearDisplay();
  325. if(StateUP==0) // nếu nút up được nhấn
  326. {
  327. minute=minute+1;
  328. if(minute>59)
  329. {
  330. minute=0;
  331. hour=hour+1;
  332. }
  333. if ((hour==0) && (minute==1))
  334. {
  335. wday=wday+1;
  336. if (wday>7)
  337. {
  338. wday=1;
  339. }
  340. day=day+1;
  341. }
  342. Wire.begin();
  343. setTime(hour, minute, 00, wday, day, month, 15);
  344. delay(10);
  345. }
  346. if(StateDOWN==0)
  347. {
  348. minute=minute1;
  349. if(minute<0)
  350. {
  351. minute=59;
  352. hour=hour1;
  353. }
  354. if ((hour<0) && (minute==59))
  355. {
  356. wday=wday1;
  357. hour=23;
  358. if (wday<1)
  359. {
  360. wday=7;
  361. }
  362. day=day1;
  363. }
  364. Wire.begin();
  365. delay(10);
  366. }
  367.  
  368. }
  369. void Button_ON_OFF()
  370. {
  371. if(StateUP==0)
  372. {
  373. StateWifi=0;
  374. display.clearDisplay();
  375. }
  376. if(StateDOWN==0)
  377. {
  378. StateWifi=1;
  379. display.clearDisplay();
  380. }
  381. }

5. Chú thích

Phần code có đoạn:

//setTime(12, 30, 45, 1, 8, 2, 15); // 12:30:45 CN 08-02-2015

Minh để sau dấu chú thích là bởi vì khi nạp chương trình, thời gian sẽ được set theo giá trị12:30:45 CN 08-02-2015 . và những lần chạy tiếp theo nó sẽ liên tục set lại giá trị cũ.

Vì vậy chỉ trong lần nạp chương trình đầu tiên mình mới để hàm setTime. sau đó để hàm settime vào sau dấu chú thích “//” rồi nạp lại lần nữa

6. Sử dụng thế nào?

Khi cần thay đổi thời gian.

Nhấn và giữ nút setup sau đó nhấn nút Up, Down để tăng, giảm thời gian.

Khi cần học mã điều khiển.

Nhấn và giữ nút setup, sau đó nhấn nút bạn cần học mã trên điều khiển (nhớ phải quay điều khiển về hướng IR LED nhé)

khi cần bật tắt bằng tay.

Nhấn nút up để bật, nhấn nút down để tắt.

Hiện tại mình mới chỉ dừng lại ở mức nạp code mặc định khoảng thời gian hẹn để bật tắt.

Cuối cùng, các bạn chỉ cần nối dây nguồn của moderm wifi vào relay và mắc nguồn cho arduino là xong. Bạn nào chưa hiểu có thể liên hệ trực tiếp với mình qua mục tin nhắn hoặc bình luận dưới bài viết nhé. Chúc các bạn thành công!

Facebook Comments

Trả lời

Thư điện tử của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *