风筝
发表于: 2018-12-20 11:42:26 | 显示全部楼层

在本篇文章中,我们将使用RTC实时时钟模块搭建数字时钟。我们将了解什么是“RTC”模块,如何与Arduino开发板进行交互以及它的作用。


RTC模块电路可以准确地保持当前时间。它具有两个功能,它与微控制器和微处理器通信以提供当前时间,以及充当备用电路,以便在发生电源故障时保持时间,因为它具有内置电池备份系统。


我们可以在任何电子设备中找到RTC,其中时间是小工具的重要功能。例如,即使在断电或取出电池后,我们的计算机或笔记本电脑仍能保持时间。在计算机的主板上,我们都可以找到一块CMOS电池,为RTC电路供电。我们将在这个项目中使用类似的电路。


RTC模块是一种廉价的设备,可以在任何电子商务网站和您当地的电子项目商店中找到。


典型RTC模块DS1307的示意图:

P_20160813_150716-2.jpg


P_20160813_150700-1.jpg


大多数RTC模块在购买时都带有电池(CR2032)。尺寸和型号有所不同,上面所示可能与您不一样。但请确保型号为DS1307。本文中编写的代码仅与DS1307兼容。


现在你对RTC了解一些。现在让我们继续讨论数字时钟设计。在继续此项目之前,您需要从以下链接下载库并在IDE上安装:


•DS1307RTC.h

链接:github.com/PaulStoffregen/DS1307RTC

•TimeLib.h

链接:github.com/PaulStoffregen/Time

如果您使用的是最新版本,则以下两个库将预先安装在Arduino IDE上。

•LiquidCrystal.h

•Wire.h


连接电路:

LCD_bb-1.png

arduino和LCD显示器之间的电路连接是标准的,我们可以在其他基于LCD的项目上找到类似的连接。唯一的附加组件是RTC。


为了减少原型期间的线路拥塞,可以将RTC直接插入arduino的模拟引脚。用公头插针焊接SCL、SDA、Vcc和GND,并将A2插入A5引脚,如原型所示。

P_20160813_160329-1.jpg


如何在Arduino上正确插入RTC:

P_20160813_160458-1.jpg

如果您的RTC具有不同的引脚位置且无法复制,如上图所示,您始终可以使用电线进行连接。现在您的硬件设置已完成,让我们转到项目的软件部分。


如何设定时间:

一旦RTC模块被编程,即使从arduino中移除,它也会保持时间。电池应至少使用几年。


没有按钮来调整时间;以下程序将在RTC中设置时间。在编译代码时,时间会自动与计算机的时间同步,因此在上载程序之前,请确保将计算机设置为正确的时间。

上传此“SetTime”代码以设置插入RTC的时间:

  1. #include <Wire.h>

  2. #include <TimeLib.h>

  3. #include <DS1307RTC.h>

  4. int P=A3; //Assign power pins for RTC

  5. int N=A2;

  6. const char *monthName[12] = {

  7. "Jan", "Feb", "Mar", "Apr", "May", "Jun",

  8. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"

  9. };

  10. tmElements_t tm;

  11. void setup() {

  12. pinMode(P,OUTPUT);

  13. pinMode(N,OUTPUT);

  14. digitalWrite(P,HIGH);

  15. digitalWrite(N,LOW);

  16. bool parse=false;

  17. bool config=false;

  18. // get the date and time the compiler was run

  19. if (getDate(__DATE__) && getTime(__TIME__)) {

  20. parse = true;

  21. // and configure the RTC with this info

  22. if (RTC.write(tm)) {

  23. config = true;

  24. }

  25. }

  26. Serial.begin(9600);

  27. while (!Serial) ; // wait for Arduino Serial Monitor

  28. delay(200);

  29. if (parse && config) {

  30. Serial.print("DS1307 configured Time=");

  31. Serial.print(__TIME__);

  32. Serial.print(", Date=");

  33. Serial.println(__DATE__);

  34. } else if (parse) {

  35. Serial.println("DS1307 Communication Error :-{");

  36. Serial.println("Please check your circuitry");

  37. } else {

  38. Serial.print("Could not parse info from the compiler, Time="");

  39. Serial.print(__TIME__);

  40. Serial.print("", Date="");

  41. Serial.print(__DATE__);

  42. Serial.println(""");

  43. }

  44. }

  45. void loop() {

  46. }

  47. bool getTime(const char *str)

  48. {

  49. int Hour, Min, Sec;

  50. if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;

  51. tm.Hour = Hour;

  52. tm.Minute = Min;

  53. tm.Second = Sec;

  54. return true;

  55. }

  56. bool getDate(const char *str)

  57. {

  58. char Month[12];

  59. int Day, Year;

  60. uint8_t monthIndex;

  61. if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;

  62. for (monthIndex = 0; monthIndex < 12; monthIndex++) {

  63. if (strcmp(Month, monthName[monthIndex]) == 0) break;

  64. }

  65. if (monthIndex >= 12) return false;

  66. tm.Day = Day;

  67. tm.Month = monthIndex + 1;

  68. tm.Year = CalendarYrToTm(Year);

  69. return true;

  70. }
复制代码

上传此代码后,打开串行监视器,弹出成功消息,说明时间已设置。


这表示您在RTC和arduino之间的连接是正确的并且设置了时间。


现在上传以下代码以在LCD中显示时间。

  1. //------------Program Developed by R.Girish-------//

  2. #include <Wire.h>

  3. #include <TimeLib.h>

  4. #include <DS1307RTC.h>

  5. #include <LiquidCrystal.h>

  6. LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

  7. int P=A3;

  8. int N=A2;

  9. void setup() {

  10. lcd.begin(16,2);

  11. pinMode(P,OUTPUT);

  12. pinMode(N,OUTPUT);

  13. digitalWrite(P,HIGH);

  14. digitalWrite(N,LOW);

  15. }

  16. void loop() {

  17. tmElements_t tm;

  18. lcd.clear();

  19. if (RTC.read(tm))

  20. {

  21. if(tm.Hour>=12)

  22. {

  23. lcd.setCursor(14,0);

  24. lcd.print("PM");

  25. }

  26. if(tm.Hour<12)

  27. {

  28. lcd.setCursor(14,0);

  29. lcd.print("AM");

  30. }

  31. lcd.setCursor(0,0);

  32. lcd.print("TIME:");

  33. if(tm.Hour>12) //24Hrs to 12 Hrs conversion//

  34. {

  35. if(tm.Hour==13) lcd.print("01");

  36. if(tm.Hour==14) lcd.print("02");

  37. if(tm.Hour==15) lcd.print("03");

  38. if(tm.Hour==16) lcd.print("04");

  39. if(tm.Hour==17) lcd.print("05");

  40. if(tm.Hour==18) lcd.print("06");

  41. if(tm.Hour==19) lcd.print("07");

  42. if(tm.Hour==20) lcd.print("08");

  43. if(tm.Hour==21) lcd.print("09");

  44. if(tm.Hour==22) lcd.print("10");

  45. if(tm.Hour==23) lcd.print("11");

  46. }

  47. else

  48. {

  49. lcd.print(tm.Hour);

  50. }

  51. lcd.print(":");

  52. lcd.print(tm.Minute);

  53. lcd.print(":");

  54. lcd.print(tm.Second);

  55. lcd.setCursor(0,1);

  56. lcd.print("DATE:");

  57. lcd.print(tm.Day);

  58. lcd.print("/");

  59. lcd.print(tm.Month);

  60. lcd.print("/");

  61. lcd.print(tmYearToCalendar(tm.Year));

  62. } else {

  63. if (RTC.chipPresent()) {

  64. lcd.setCursor(0,0);

  65. lcd.print("RTC stopped!!!");

  66. lcd.setCursor(0,1);

  67. lcd.print("Run SetTime code");

  68. } else {

  69. lcd.clear();

  70. lcd.setCursor(0,0);

  71. lcd.print("Read error!");

  72. lcd.setCursor(0,1);

  73. lcd.print("Check circuitry!");

  74. }

  75. delay(500);

  76. }

  77. delay(500);

  78. }


  79. //------------Program Developed by R.Girish-------//
复制代码

完成后,您应该看到时间和日期显示在LCD上并运行。


注意:从DS1307RTC的示例代码修改“SetTime”代码以优化RTC模块的线连接,上传原始代码不会设置时间。

跳转到指定楼层
风筝
发表于: 2018-12-20 13:51:26 | 显示全部楼层

使用Arduino的数字闹钟

上面我们学习了如何使用RTC模块构建基本的Arduino时钟,接下来我们将研究如何使用Arduino将其升级为数字闹钟电路。


有些人不需要闹钟,他们自然醒来,有些人在闹钟响几次后醒来,有些人多次按下贪睡按钮,上大学/工作到很晚一些借口。有趣的小闹钟项目可能会遇到早晨醒来时的懒惰问题。如果用户没有响应,大多数闹钟都有一个贪睡按钮和预先确定的警报截止时间。


我们设计了这个没有懒人按钮(闹钟按钮)的闹钟,并且在用户按下按钮之前闹钟不会关闭。


此时钟可以12小时格式显示时间,日期格式为DD / MM / YYYY格式。


时间和日期将在1602 LCD显示屏上展示。 RTC或实时时钟时间模块将负责保持时间,即使长时间断电也可以保持正确的时间。


提供了5个按钮,其功能在后面进行解释。 Arduino项目的主板可以选择任何型号,我们推荐Arduino pro mini或Arduino nano,因为它的尺寸紧凑。


现在让我们看一下原理图。

LCD.png

以上是Arduino显示连接示意图,通过旋转10K电位器调整显示对比度。


以下是电路的其余部分:

该电路可以为9V 500mA适配器供电。

DigitalAlarmCLock.jpg

5个按钮的功能:

S1  - 用于停止报警(它也是复位按钮)

S2  - 用于设置闹钟。长按S2,您将进入闹钟设置菜单。

S3  - 用于增加小时数。

S4  - 用于增加分钟数。

S5  - 用于切换警报状态。如果右侧底角的LCD显示屏上存在“*”,则报警为ON,如果“*”不存在,则报警统计为OFF。


下载以下库文件:

Link1:github.com/PaulStoffregen/DS1307RTC

Link2:github.com/PaulStoffregen/Time


现在,我们必须设置时间到RTC模块,时间将从您的PC同步到RTC模块。


上传以下代码以设置时间并打开串行监视器:

  1. //------------------------------------------------//
  2. #include <Wire.h>
  3. #include <TimeLib.h>
  4. #include <DS1307RTC.h>
  5. const char *monthName[12] = {
  6. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  7. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  8. };
  9. tmElements_t tm;
  10. void setup() {
  11. bool parse=false;
  12. bool config=false;
  13. // get the date and time the compiler was run
  14. if (getDate(__DATE__) && getTime(__TIME__)) {
  15. parse = true;
  16. // and configure the RTC with this info
  17. if (RTC.write(tm)) {
  18. config = true;
  19. }
  20. }
  21. Serial.begin(9600);
  22. while (!Serial) ; // wait for Arduino Serial Monitor
  23. delay(200);
  24. if (parse && config) {
  25. Serial.print("DS1307 configured Time=");
  26. Serial.print(__TIME__);
  27. Serial.print(", Date=");
  28. Serial.println(__DATE__);
  29. } else if (parse) {
  30. Serial.println("DS1307 Communication Error :-{");
  31. Serial.println("Please check your circuitry");
  32. } else {
  33. Serial.print("Could not parse info from the compiler, Time="");
  34. Serial.print(__TIME__);
  35. Serial.print("", Date="");
  36. Serial.print(__DATE__);
  37. Serial.println(""");
  38. }
  39. }
  40. void loop() {
  41. }
  42. bool getTime(const char *str)
  43. {
  44. int Hour, Min, Sec;
  45. if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  46. tm.Hour = Hour;
  47. tm.Minute = Min;
  48. tm.Second = Sec;
  49. return true;
  50. }
  51. bool getDate(const char *str)
  52. {
  53. char Month[12];
  54. int Day, Year;
  55. uint8_t monthIndex;
  56. if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
  57. for (monthIndex = 0; monthIndex < 12; monthIndex++) {
  58. if (strcmp(Month, monthName[monthIndex]) == 0) break;
  59. }
  60. if (monthIndex >= 12) return false;
  61. tm.Day = Day;
  62. tm.Month = monthIndex + 1;
  63. tm.Year = CalendarYrToTm(Year);
  64. return true;
  65. }
  66. //----------------------------------------//
复制代码

现在您已成功设置RTC时间


接下来,您需要上传以下主要代码:

  1. //------------Program Developed by R.Girish-------//
  2. #include <LiquidCrystal.h>
  3. #include <DS1307RTC.h>
  4. #include <TimeLib.h>
  5. #include <Wire.h>
  6. #include <EEPROM.h>
  7. const int rs = 7;
  8. const int en = 6;
  9. const int d4 = 5;
  10. const int d5 = 4;
  11. const int d6 = 3;
  12. const int d7 = 2;
  13. const int buzzer = 8;
  14. boolean alarm = false;
  15. boolean outloop = true;
  16. const int setAlarm = A0;
  17. const int Hrs = A1;
  18. const int Min = A2;
  19. const int ok = A3;
  20. const int HrsADD = 0;
  21. const int MinADD = 1;
  22. const int ALsave = 2;
  23. int HrsVal = 0;
  24. int MinVal = 0;
  25. int H = 0;
  26. int M = 0;
  27. int S = 0;
  28. int i = 0;
  29. int j = 0;
  30. int k = 0;
  31. LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
  32. void setup()
  33. {
  34. Serial.begin(9600);
  35. lcd.begin(16, 2);
  36. pinMode(buzzer, OUTPUT);
  37. pinMode(setAlarm, INPUT);
  38. pinMode(Hrs, INPUT);
  39. pinMode(Min, INPUT);
  40. pinMode(ok, INPUT);
  41. digitalWrite(setAlarm, HIGH);
  42. digitalWrite(Hrs, HIGH);
  43. digitalWrite(Min, HIGH);
  44. digitalWrite(ok, HIGH);
  45. }
  46. void loop()
  47. {
  48. tmElements_t tm;
  49. lcd.clear();
  50. if (EEPROM.read(ALsave) == false)
  51. {
  52. lcd.setCursor(15, 1);
  53. lcd.print("");
  54. }
  55. if (EEPROM.read(ALsave) == true)
  56. {
  57. lcd.setCursor(15, 1);
  58. lcd.print(F("*"));
  59. }
  60. if (RTC.read(tm))
  61. {
  62. if (tm.Hour >= 12)
  63. {
  64. lcd.setCursor(14, 0);
  65. lcd.print("PM");
  66. }
  67. if (tm.Hour < 12)
  68. {
  69. lcd.setCursor(14, 0);
  70. lcd.print("AM");
  71. }
  72. lcd.setCursor(0, 0);
  73. lcd.print("TIME:");
  74. H = tm.Hour;
  75. if (tm.Hour > 12)
  76. {
  77. if (tm.Hour == 13)
  78. {
  79. lcd.print("01");
  80. }
  81. if (tm.Hour == 14)
  82. {
  83. lcd.print("02");
  84. }
  85. if (tm.Hour == 15)
  86. {
  87. lcd.print("03");
  88. }
  89. if (tm.Hour == 16)
  90. {
  91. lcd.print("04");
  92. }
  93. if (tm.Hour == 17)
  94. {
  95. lcd.print("05");
  96. }
  97. if (tm.Hour == 18)
  98. {
  99. lcd.print("06");
  100. }
  101. if (tm.Hour == 19)
  102. {
  103. lcd.print("07");
  104. }
  105. if (tm.Hour == 20)
  106. {
  107. lcd.print("08");
  108. }
  109. if (tm.Hour == 21)
  110. {
  111. lcd.print("09");
  112. }
  113. if (tm.Hour == 22)
  114. {
  115. lcd.print("10");
  116. }
  117. if (tm.Hour == 23)
  118. {
  119. lcd.print("11");
  120. }
  121. }
  122. else
  123. {
  124. lcd.print(tm.Hour);
  125. }
  126. M = tm.Minute;
  127. S = tm.Second;
  128. lcd.print(":");
  129. lcd.print(tm.Minute);
  130. lcd.print(":");
  131. lcd.print(tm.Second);
  132. lcd.setCursor(0, 1);
  133. lcd.print("DATE:");
  134. lcd.print(tm.Day);
  135. lcd.print("/");
  136. lcd.print(tm.Month);
  137. lcd.print("/");
  138. lcd.print(tmYearToCalendar(tm.Year));
  139. } else {
  140. if (RTC.chipPresent())
  141. {
  142. lcd.setCursor(0, 0);
  143. lcd.print("RTC stopped!!!");
  144. lcd.setCursor(0, 1);
  145. lcd.print("Run SetTime code");
  146. } else {
  147. lcd.clear();
  148. lcd.setCursor(0, 0);
  149. lcd.print("Read error!");
  150. lcd.setCursor(0, 1);
  151. lcd.print("Check circuitry!");
  152. }
  153. }
  154. if (digitalRead(setAlarm) == LOW)
  155. {
  156. setALARM();
  157. }
  158. if (H == EEPROM.read(HrsADD) && M == EEPROM.read(MinADD) && S == 0)
  159. {
  160. if (EEPROM.read(ALsave) == true)
  161. {
  162. sound();
  163. }
  164. }
  165. if (digitalRead(ok) == LOW)
  166. {
  167. if (EEPROM.read(ALsave) == true)
  168. {
  169. EEPROM.write(ALsave, 0);
  170. alarm = false;
  171. delay(1000);
  172. return;
  173. }
  174. if (EEPROM.read(ALsave) == false)
  175. {
  176. EEPROM.write(ALsave, 1);
  177. alarm = true;
  178. delay(1000);
  179. return;
  180. }
  181. }
  182. delay(1000);
  183. }
  184. void setALARM()
  185. {
  186. HrsVal = EEPROM.read(HrsADD);
  187. MinVal = EEPROM.read(MinADD);
  188. lcd.clear();
  189. lcd.setCursor(0, 0);
  190. lcd.print(F(">>>>SET ALARM<<<"));
  191. lcd.setCursor(0, 1);
  192. lcd.print(F("Hrs:"));
  193. lcd.print(EEPROM.read(HrsADD));
  194. lcd.print(F(" Min:"));
  195. lcd.print(EEPROM.read(MinADD));
  196. delay(600);
  197. while (outloop)
  198. {
  199. if (HrsVal > 23)
  200. {
  201. HrsVal = 0;
  202. lcd.clear();
  203. lcd.setCursor(0, 0);
  204. lcd.print(F(">>>>SET ALARM<<<"));
  205. lcd.setCursor(0, 1);
  206. lcd.print(F("Hrs:"));
  207. lcd.print(HrsVal);
  208. lcd.print(F(" Min:"));
  209. lcd.print(MinVal);
  210. }
  211. if (MinVal > 59)
  212. {
  213. MinVal = 0;
  214. lcd.clear();
  215. lcd.setCursor(0, 0);
  216. lcd.print(F(">>>>SET ALARM<<<"));
  217. lcd.setCursor(0, 1);
  218. lcd.print(F("Hrs:"));
  219. lcd.print(HrsVal);
  220. lcd.print(F(" Min:"));
  221. lcd.print(MinVal);
  222. }
  223. if (digitalRead(Hrs) == LOW)
  224. {
  225. HrsVal = HrsVal + 1;
  226. lcd.clear();
  227. lcd.setCursor(0, 0);
  228. lcd.print(F(">>>>SET ALARM<<<"));
  229. lcd.setCursor(0, 1);
  230. lcd.print(F("Hrs:"));
  231. lcd.print(HrsVal);
  232. lcd.print(F(" Min:"));
  233. lcd.print(MinVal);
  234. delay(250);
  235. }
  236. if (digitalRead(Min) == LOW)
  237. {
  238. MinVal = MinVal + 1;
  239. lcd.clear();
  240. lcd.setCursor(0, 0);
  241. lcd.print(F(">>>>SET ALARM<<<"));
  242. lcd.setCursor(0, 1);
  243. lcd.print(F("Hrs:"));
  244. lcd.print(HrsVal);
  245. lcd.print(F(" Min:"));
  246. lcd.print(MinVal);
  247. delay(250);
  248. }
  249. if (digitalRead(setAlarm) == LOW)
  250. {
  251. EEPROM.write(HrsADD, HrsVal);
  252. EEPROM.write(MinADD, MinVal);
  253. lcd.clear();
  254. lcd.setCursor(0, 0);
  255. lcd.print(F("Alarm is Set for"));
  256. lcd.setCursor(0, 1);
  257. lcd.print(EEPROM.read(HrsADD));
  258. lcd.print(F(":"));
  259. lcd.print(EEPROM.read(MinADD));
  260. lcd.print(F(" Hrs"));
  261. delay(1000);
  262. outloop = false;
  263. }
  264. }
  265. outloop = true;
  266. }
  267. void sound()
  268. {
  269. lcd.clear();
  270. lcd.setCursor(0, 0);
  271. lcd.print("Wakey Wakey !!!");
  272. lcd.setCursor(0, 1);
  273. lcd.print("Its Time now.....");
  274. for (j = 0; j < 10; j++)
  275. {
  276. for (i = 0; i < 2 ; i++)
  277. {
  278. digitalWrite(buzzer, HIGH);
  279. delay(150);
  280. digitalWrite(buzzer, LOW);
  281. delay(150);
  282. }
  283. delay(400);
  284. }
  285. for (k = 0; k < 10; k++)
  286. {
  287. for (i = 0; i < 4 ; i++)
  288. {
  289. digitalWrite(buzzer, HIGH);
  290. delay(150);
  291. digitalWrite(buzzer, LOW);
  292. delay(150);
  293. }
  294. delay(250);
  295. }
  296. while (true)
  297. {
  298. digitalWrite(buzzer, HIGH);
  299. delay(150);
  300. digitalWrite(buzzer, LOW);
  301. delay(150);
  302. }
  303. }
  304. //------------Program Developed by R.Girish-------//
复制代码

上传代码后,需要在显示屏上看到正确的时间和日期。


现在让我们看看如何设置闹钟:

•长按S2直到您可以看到闹钟菜单。

•按S3和S4分别调整小时和分钟。

•设定所需时间后,再次按S2。它会说“警报设置为xx:xx小时”。

•如果警报为ON,您可以在显示屏上看到“*”符号,如果警报为OFF,则不会有“*”符号。

•您可以按S5半秒钟打开/关闭闹钟。不要长按直到“*”消失(它再次返回),只需按半秒钟即可切换警报状态。


重要的提示:

在任何时钟上设置闹钟时最常见的错误是无意中切换AM / PM,这导致我们的预期时间没有闹钟。

为解决此问题,建议的闹钟设置采用24小时时钟格式设计。

使用AM / PM格式在液晶显示屏上显示的时间为12小时,但是当您使用此项目设置闹钟时,您必须以24小时格式设置0到23小时。

例如:如果要在晚上9:00设置闹钟,则必须设置21小时0分钟。对于,凌晨5点:5小时0分钟等等。

Webp.net-compress-image.jpg


你喜欢这个项目吗?如果对这个项目有任何疑问,请随时在本帖下面进行回复。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 705 | 回复: 1492



手机版|

GMT+8, 2024-11-24 08:06 , Processed in 1.062610 second(s), 10 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表