87浏览
查看: 87|回复: 2

[项目] 【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟

[复制链接]
在手腕上总是戴着时钟的时候,无论是手腕上的手表还是智能手机,Arduino Uno/Nano 都有点沉闷。否则,您将本文中的 NTP 服务器同步设备放在外部,这些设备通过您的 Internet 连接始终在线。

我的一个朋友出于个人原因拒绝在他的卧室里使用带有 WiFi 连接的设备,所以我让 Arduino 配备了一个单独的时钟。
选择合适的产品
我很惊讶,甚至 Adafruit 也有这么多不同的产品可供选择:取决于所需的张力,以及不同的精度!在这里,我决定使用两种产品:更便宜的 DS1307 和可能更精确的 DS3231。
需要明确的是:这两种产品都可以用于这个时钟。要使用DS1307,请注意正确的PIN分配和温度显示选项的限制: 在displayTemp()上注“//”;loop () 中的函数。

调整程序
我去找程序,发现了另一个成员的东西。我重新构建并适应了这个程序,但保留了捷克语的评论并添加了英语评论。
广告应该尽可能大,所以我决定做一个 7 段的广告:毕竟,我只想把时间放在心上。
我在查看草图时遇到的下一个积极的惊喜是:在这里,DS3231 提供了使用温度的选项,而 DS1307 除了不准确之外还缺少温度。

初始化时钟
如果您有 CR1220 纽扣电池,您可以按照 Adafruit 的简短教程设置时钟进行作。总之,时间不是从 Internet 下载的,而是随着时间的推移从本地 PC 下载的。上传时间戳将传输到计时器。

功能
之后,我将 LED 矩阵添加到电路中以进行时间和温度输出。时间和温度的变化周期可以通过变量设置。
特别是,程序中详细描述了对 LED 矩阵上单个 - 闪烁 - 点和数字的控制是如何工作的和控制的。
在这里,我参考了更多 Adafruit 来源。
程序通过根据环境光调整夏/冬时间和 LED 矩阵的亮度(夜间显示屏应比白天暗)来完善。
在视频中,您当然注意到了时间和温度的变化。你注意了图片左边的点吗?这会根据秒数改变其位置(向上或向下)。
如果您知道如何在时钟出现故障时在 LED 矩阵上发出“ERR”,请给我反馈。此刻会出现“bEEF”。

扩张
警报或警报时间也尚未集成。
也可能通过蓝牙模块和 Blynk 进行扩展。

更新:
从面包板到打孔卡永久投注的转移今天已经完成。

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图1

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图6

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图3

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图2

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图5


【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图4

驴友花雕  中级技神
 楼主|

发表于 2025-7-28 09:55:32

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟

项目代码

  1. // MyClock v1.1
  2. // Ingo Lohs
  3. // Hardware: tested with Arduino Uno and Arduino Nano (ATmega328P [Old Bootloader]) by using Arduino IDE v1.8.8
  4. // Change v1.0 > v1.1
  5. // dayOfWeek == 1 anstatt 7 abgeändert in displayTime() zur korrekten Ermittlung des Sonntages für die Zeitumstellung
  6. /* Theory for the Matrix ht16k33
  7. The easiest is to just call print - just like you do with Serial
  8. print(variable,HEX) - this will print a hexidecimal number, from 0000 up to FFFF
  9. print(variable,DEC) or
  10. print(variable) - this will print a decimal integer, from 0000 up to 9999
  11. If you need more control, you can call writeDigitNum(location, number) - this will write the number (0-9) to a single location.
  12. Location #0 is all the way to the left, location #2 is the colon dots so you probably want to skip it, location #4 is all the way to the right.
  13. To control the colon and decimal points, use the writeDigitRaw(location, bitmap) function.
  14. (Note that both dots of the center colon are wired together internal to the display, so it is not possible to address them separately.)
  15. Specify 2 for the location and the bits are mapped as follows:
  16. 0x02 - center colon (both dots)
  17. 0x04 - left colon - lower dot
  18. 0x08 - left colon - upper dot
  19. 0x10 - decimal point
  20. If you want a decimal point, call writeDigitNum(location, number, true) which will paint the decimal point.
  21. To draw the colon, use drawColon(true or false)
  22. If you want full control of the segments in all digits, you can call writeDigitRaw(location,bitmask) to draw a raw 8-bit mask (as stored in a uint8_t) to any location.
  23. All the drawing routines only change the display memory kept by the Arduino. Don't forget to call writeDisplay() after drawing to 'save' the memory out to the matrix via I2C.
  24. Source: https://www.mouser.com/ds/2/737/adafruit-led-backpack-932846.pdf
  25. */
  26. #include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
  27. #include <Adafruit_GFX.h>
  28. #include "Adafruit_LEDBackpack.h"
  29. #define DS3231_I2C_ADDRESS 0x68
  30. int ldr_sensor = A0;            // LDR Photoresistor with 100k Ohm to GND, other leg 5V
  31. int ldr_value = 0;              // LDR value - var store value
  32. int brightness_matrix;          // LED Matrix brightness - var store value
  33. int threshold_brightness = 400; // Threshold
  34. int blinkrate_value = 0;        // LED Matrix blink rate
  35. int delay_matrix_time = 20;     // how long display time (20 sec)
  36. int delay_matrix_temp = 2000;   // how long display temp (2 sec)
  37. int blinky_dot = 2;             // blinks nothing - on the left side 2 single dots
  38. Adafruit_7segment matrix = Adafruit_7segment();
  39. byte decToBcd(byte val){
  40. return ( (val/10*16) + (val%10) );
  41. }
  42. byte bcdToDec(byte val){
  43. return ( (val/16*10) + (val%16) );
  44. }
  45. void setup() {
  46.   Serial.begin(9600);
  47.   Wire.begin();
  48.   matrix.begin(0x70);
  49. }
  50. void loop() {
  51.     lightBrightness(); // Matrix-Brightness Justierung
  52.     matrixBlinkrate(); // Mattrix-Blinkrate Jusitierung
  53.     displayTime();     // display the real-time clock data
  54.     displayTemp();     // display the temperature   
  55. }
  56. void lightBrightness() {
  57. // setBrightness(brighness) - will let you change the overall brightness of the entire display. 0 is least bright, 15 is brightest and is what is initialized by the display when you start
  58.     ldr_value = analogRead(ldr_sensor);
  59.     Serial.print("LDR: ");
  60.     Serial.println(ldr_value);
  61.     if (ldr_value <= threshold_brightness) { // measurement of brightness vs Threshold
  62.       brightness_matrix = 0; // bright at daylight
  63.     }
  64.     else {
  65.       brightness_matrix = 15; // dark at night
  66.     }
  67. }
  68. void matrixBlinkrate() {
  69. // blinkRate(rate) - You can blink the entire display. 0 is no blinking. 1, 2 or 3 is for display blinking.
  70. matrix.blinkRate(blinkrate_value);
  71. }
  72.   
  73. void displayTime(){
  74. matrix.setBrightness(brightness_matrix);
  75. matrix.clear();
  76. // how long display time on matrix in seconds
  77. for (uint16_t i = 0; i < delay_matrix_time; i++) {
  78.   byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  79.   getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  80.     byte se = second;         
  81.     byte mi = minute;
  82.     byte ho = hour;
  83.     byte we = dayOfWeek;
  84.     byte dm = dayOfMonth;
  85.     byte mo = month;
  86.     byte ye = year;
  87.     // změna času na letní - poslední neděle v březnu ve 2 hodiny
  88.     // >> Change to summer time - last Sunday in March at 2 o'clock
  89.     if ((dayOfWeek == 1) && (dayOfMonth >= 25)&& (month == 3) && (hour == 2)) {
  90.       // nastavení hodin na 3 hodinu
  91.       // set the clock to 3 hours
  92.       setDS3231time(se,mi,3,we,dm,mo,ye);
  93.     }   
  94.    
  95.     // změna času na zimní  
  96.     // >> Change to winter time
  97.     if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 10) && (hour == 1)&& (year != 1)) {
  98.    
  99.       // rok použit jako indikace, že bylo léto
  100.       // year used as an indication that it was summer
  101.       setDS3231time(se,mi,ho,we,dm,mo,1);
  102.     }  
  103.    
  104.     if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 10) && (hour == 3) &&(year == 1)) {
  105.       // nastavení hodin na 2 hodinu a příznak na 0
  106.       // set the clock to 2 hours and flag year to 0
  107.       setDS3231time(se,mi,2,we,dm,mo,0);
  108.     }
  109.    
  110.      /*   
  111.       Specify 2 for the location and the bits are mapped as follows:
  112.       0x02 - center colon (both dots)
  113.       0x04 - left colon - lower dot
  114.       0x08 - left colon - upper dot
  115.       0x10 - decimal point
  116.      */
  117.      /* location #2 controls also the left 2 single points like this (=blinky_dot):
  118.       2 = blinks nothing
  119.       3 = blinks nothing
  120.       4 = blinks top left (single upper dot)
  121.       5 = blinks top left (single upper dot)
  122.       6 = blinks top left (single upper dot) + both Colon in mid
  123.       7 = blinks top left (single upper dot) + both Colon in mid
  124.       8 = blinks bottom left (single lower dot)
  125.       9 = blinks bottom left (single lower dot)
  126.      10 = blinks bottom left (single lower dot) + both Colon in mid
  127.      11 = blinks bottom left (single lower dot) + both Colon in mid
  128.      12 = blinks both Colon (both single dots left) without both Colon in mid
  129.      */   
  130.    
  131.     // format hours: _0:mm
  132.     if (hour > 9) {
  133.     matrix.writeDigitNum(0, (hour / 10), false);
  134.     matrix.writeDigitNum(1, (hour % 10), false);    // this will write the number (0-9) to a single location by using modulo https://www.arduino.cc/reference/en/language/structure/arithmetic-operators/modulo/
  135.     } else {
  136.     matrix.writeDigitNum(1, hour, false);
  137.     }
  138.                
  139.       // matrix.drawColon(true);                    // both Colon in mid active: in case you want not blink the dots left you can activate the both Colon here  
  140.       
  141.     // give seconds a chance to show at left location dots
  142.     if (se <= 30) {
  143.       blinky_dot = 10; // blinks bottom left (single lower dot) + both Colon in mid
  144.     } else if (se > 30) {
  145.       blinky_dot = 6;   // blinks top left (single upper dot) + both Colon in mid
  146.     }
  147.       matrix.writeDigitRaw(2, blinky_dot);            
  148.    
  149.       matrix.writeDigitNum(3, (minute / 10), false);
  150.       matrix.writeDigitNum(4, (minute % 10), false);
  151.    
  152.       matrix.writeDisplay();
  153.       
  154.       // blinky double dots for half seconds
  155.       delay(500);
  156.       matrix.drawColon(false);
  157.       matrix.writeDisplay();
  158.       delay(500);   
  159.   }
  160. }
  161. void displayTemp(){
  162. matrix.setBrightness(brightness_matrix);
  163. matrix.clear();
  164.   byte temp = get3231Temp();
  165.   int abs_temp = abs(temp);                                           // absolute number of a value
  166.   matrix.writeDigitNum(1,(abs_temp % 10), false);                     // position 1, value 9, show decimal)
  167.   if (temp < 0)    matrix.writeDigitRaw(0,64);                        
  168.   if (temp <= -10) matrix.writeDigitRaw(2,12);                        // and if the temperature is negative, we plot the minus sign to first place.
  169.   if (temp >= 10)  matrix.writeDigitNum(0, (abs_temp/10), false);     // position 0, value 1, show decimal)
  170.   if (temp <= -10) matrix.writeDigitNum(0, (abs_temp/10), false);     // position 0, value 1, show decimal)
  171.   // matrix.writeDigitRaw(2,0x10);                                    // decimal dot
  172.   matrix.writeDigitRaw(3,99);                                         // 99 = "°"
  173.   matrix.writeDigitRaw(4,57);                                         // 57 = "C"
  174.   matrix.writeDisplay();
  175.   
  176.   // displays temperature values on the serial line
  177.   // zobrazí hodnoty teploty na seriove lince
  178.   Serial.print("Temperatur in C: ");
  179.   Serial.println(get3231Temp());                                      // +/- 3 Grad Celsius
  180.   
  181.   // how long display temp on matrix in seconds
  182.   delay(delay_matrix_temp);
  183. }
  184. void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year){
  185.     // set time and date data to DS3231
  186.     Wire.beginTransmission(DS3231_I2C_ADDRESS);
  187.     Wire.write(0);                    // set next input to start at the seconds register
  188.     Wire.write(decToBcd(second));     // set seconds
  189.     Wire.write(decToBcd(minute));     // set minutes
  190.     Wire.write(decToBcd(hour));       // set hours
  191.     Wire.write(decToBcd(dayOfWeek));  // set day of week (1=Sunday, 7=Saturday)
  192.     Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  193.     Wire.write(decToBcd(month));      // set month
  194.     Wire.write(decToBcd(year));       // set year (0 to 99)
  195.     Wire.endTransmission();
  196. }
  197. void getDateDs3231
  198. (byte *second,
  199. byte *minute,
  200. byte *hour,
  201. byte *dayOfWeek,
  202. byte *dayOfMonth,
  203. byte *month,
  204. byte *year)
  205. {
  206.     Wire.beginTransmission(DS3231_I2C_ADDRESS);
  207.     Wire.write(0);
  208.     Wire.endTransmission();
  209.     Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  210.     *second = bcdToDec(Wire.read() & 0x7f);
  211.     *minute = bcdToDec(Wire.read());
  212.     *hour = bcdToDec(Wire.read() & 0x3f);
  213.     *dayOfWeek = bcdToDec(Wire.read());
  214.     *dayOfMonth = bcdToDec(Wire.read());
  215.     *month = bcdToDec(Wire.read());
  216.     *year = bcdToDec(Wire.read());
  217. }
  218. float get3231Temp(){
  219.   byte tMSB, tLSB;
  220.   float temp3231;
  221.     Wire.beginTransmission(DS3231_I2C_ADDRESS);
  222.     Wire.write(0x11);
  223.     Wire.endTransmission();
  224.     Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  225.     if (Wire.available()) {
  226.       tMSB = Wire.read();                 // 2's complement int portion
  227.       tLSB = Wire.read();                 // fraction portion
  228.       temp3231 = (tMSB & B01111111);      // do 2's math on Tmsb
  229.       temp3231 += ( (tLSB >> 6) * 0.25 ); // only care about bits 7 & 8
  230.       
  231.       return temp3231;
  232.     }
  233.     else {
  234.     // oh no, no data!
  235.       Serial.println("DS3231 Sensor Error - cant read temperature");
  236.       matrix.print(0xBEEF, HEX); // inform the user with BEEF
  237.       matrix.writeDisplay();
  238.       delay(5000);
  239.     }   
  240. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2025-7-28 10:14:41

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟

【Arduino 动手做】采用Arduino Nano + DS3231 + LDR的7段时钟
项目链接:https://www.hackster.io/ingo-loh ... o-ds3231-ldr-286f4b
项目作者:英戈·洛斯

项目视频 :https://vimeo.com/310608873?fl=pl&fe=ti&pgroup=plv
项目代码:
https://www.hackster.io/code_files/228037/download
https://www.hackster.io/code_files/231657/download

【Arduino 动手做】采用 Nano + DS3231 + LDR的7段时钟图1

回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail