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

[项目] 【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟

[复制链接]
这是我对大型数字时钟的看法

基于 Brian Lough 的俄罗斯方块图书馆:
https://github.com/witnessmenow/WiFi-Tetris-Clock
https://www.youtube.com/watch?v=ey2mjZ-UQNM
添加了一个 MP3 / WAV 播放器,为这个时钟提供声音
添加了一个 Web 界面以动态更改设置
添加了两个文本代码来显示您的滚动消息
设计了包含音频硬件的 PCB
基于 ESP32,开源固件和硬件

用品
PCB在这里购买: 会说话的时钟主板
I2S音板:Maz98357 I2S;
ESP32 DEVKIT V1 30pin 版本
强烈建议:单行标头 2.54 用作 ESP32 的套接字
HUB75 显示器 64*64(优选)或 32*64 使用 1 或 2(优选)显示器应该是库支持的显示器,请在此处查看要使用的面板
微型 SD 卡
议长
一些电线和一根 USB 电缆用于对 ESP32 进行编程
您还需要安装软件(Arduino IDE)或使用 web界面上传预编译版本

第一次设置时钟。

当您第一次启动时钟时,它不知道您的 WIFI 凭据,它将启动到接入点模式。

它将充当 WIFI 点。使用您的手机、平板电脑或其他支持 WIFI 的设备连接到该接入点。接入点的名称是 GeniusWeb,密码是 Genius

连接到该 Wifi 点后,时钟将启动您可以访问的网络服务器。

如果您在连接串行监视器时启动,它会显示您需要访问的 IP 号码。如果没有,您必须检查您的路由器以找出要使用的 IP 地址。

使用 Web 界面更改设置

您应该更改的第一件事是显示设置,选择您拥有的硬件并按“确认显示类型”您可能必须反复试验地更改它,因为显示有很多变化,而且这些变化不是很一致

接下来,您应该更改 WIFI 凭据以允许时钟访问您的 wifi 网络。更改时钟后,您将不得不重新启动时钟。

如果重新启动使时钟成功访问您的 WIFI 网络,时间和日期将自动更新。但是,请确保将其设置为正确的时区。

时区是一种文本格式,更多信息请参见:时区



哦,不......没有wifi?

如果您没有 WIFI 或您的 WIFI 政策不允许时钟建立连接,那就不理想了。但你仍然可以使用时钟。作为接入点启动后,转到 web界面并手动设置时间。在此版本中,日期不会更新,而是设置为我的生日。

那还有什么呢?

顶部有按钮,每个按钮都用声音编程。按下它,您的声音就会从扬声器中发出。

有滑块可以更改音量、亮度、动画速度、每个(新闻)行情的速度。

有两个代码用于显示滚动消息。每个股票代码最多可包含 100 个字符。

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图1

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图2

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图3

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图4

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图6

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图5

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图7

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图8

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图9

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图10

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图11

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图12

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图13

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图15

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟图14

驴友花雕  中级技神
 楼主|

发表于 昨天 18:52

【Arduino 动手做】WiFi-会说话的俄罗斯方块时钟

项目代码

  1. /*******************************************************************
  2.     Tetris clock that fetches its time Using the EzTimeLibrary
  3.     For use with the ESP32 or TinyPICO
  4. *                                                                 *
  5.     Written by Brian Lough
  6.     YouTube: https://www.youtube.com/brianlough
  7.     Tindie: https://www.tindie.com/stores/brianlough/
  8.     Twitter: https://twitter.com/witnessmenow
  9. *******************************************************************/
  10. // ----------------------------
  11. // Standard Libraries - Already Installed if you have ESP32 set up
  12. // ----------------------------
  13. #include <WiFi.h>
  14. // ----------------------------
  15. // Additional Libraries - each one of these will need to be installed.
  16. // ----------------------------
  17. // Enabling this is meant to have a performance
  18. // improvement but its worse for me.
  19. // https://github.com/2dom/PxMatrix/pull/103
  20. //#define double_buffer
  21. #include <PxMatrix.h>
  22. // The library for controlling the LED Matrix
  23. // At time of writing this my changes for the TinyPICO
  24. // Have been merged into the main PxMatrix library,
  25. // but have not been released, so you will need to install
  26. // from Github
  27. //
  28. // If you are using a regular ESP32 you may be able to use
  29. // the library manager version
  30. // https://github.com/2dom/PxMatrix
  31. // Adafruit GFX library is a dependancy for the PxMatrix Library
  32. // Can be installed from the library manager
  33. // https://github.com/adafruit/Adafruit-GFX-Library
  34. #include <TetrisMatrixDraw.h>
  35. // This library draws out characters using a tetris block
  36. // amimation
  37. // Can be installed from the library manager
  38. // https://github.com/toblum/TetrisAnimation
  39. #include <ezTime.h>
  40. // Library used for getting the time and adjusting for DST
  41. // Search for "ezTime" in the Arduino Library manager
  42. // https://github.com/ropg/ezTime
  43. // ---- Stuff to configure ----
  44. // Initialize Wifi connection to the router
  45. char ssid[] = "SSID";     // your network SSID (name)
  46. char password[] = "password"; // your network key
  47. // Set a timezone using the following list
  48. // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  49. #define MYTIMEZONE "Europe/Dublin"
  50. // Sets whether the clock should be 12 hour format or not.
  51. bool twelveHourFormat = true;
  52. // If this is set to false, the number will only change if the value behind it changes
  53. // e.g. the digit representing the least significant minute will be replaced every minute,
  54. // but the most significant number will only be replaced every 10 minutes.
  55. // When true, all digits will be replaced every minute.
  56. bool forceRefresh = true;
  57. // -----------------------------
  58. // ----- Wiring -------
  59. #define P_LAT 22
  60. #define P_A 19
  61. #define P_B 23
  62. #define P_C 18
  63. #define P_D 5
  64. #define P_E 15
  65. #define P_OE 26 //TinyPICO
  66. //#define P_OE 21 //Huzzah32
  67. //#define P_OE 2 // Generic ESP32
  68. // ---------------------
  69. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  70. hw_timer_t * timer = NULL;
  71. hw_timer_t * animationTimer = NULL;
  72. // PxMATRIX display(32,16,P_LAT, P_OE,P_A,P_B,P_C);
  73. // PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D);
  74. PxMATRIX display(64, 32, P_LAT, P_OE, P_A, P_B, P_C, P_D, P_E);
  75. TetrisMatrixDraw tetris(display); // Main clock
  76. TetrisMatrixDraw tetris2(display); // The "M" of AM/PM
  77. TetrisMatrixDraw tetris3(display); // The "P" or "A" of AM/PM
  78. Timezone myTZ;
  79. unsigned long oneSecondLoopDue = 0;
  80. bool showColon = true;
  81. volatile bool finishedAnimating = false;
  82. bool displayIntro = true;
  83. String lastDisplayedTime = "";
  84. String lastDisplayedAmPm = "";
  85. // This method is needed for driving the display
  86. void IRAM_ATTR display_updater() {
  87.   portENTER_CRITICAL_ISR(&timerMux);
  88.   display.display(10);
  89.   portEXIT_CRITICAL_ISR(&timerMux);
  90. }
  91. // This method is for controlling the tetris library draw calls
  92. void animationHandler()
  93. {
  94. #ifndef double_buffer
  95.   portENTER_CRITICAL_ISR(&timerMux);
  96. #endif
  97.   // Not clearing the display and redrawing it when you
  98.   // dont need to improves how the refresh rate appears
  99.   if (!finishedAnimating) {
  100. #ifdef double_buffer
  101.     display.fillScreen(tetris.tetrisBLACK);
  102. #else
  103.     display.clearDisplay();
  104. #endif
  105.     //display.fillScreen(tetris.tetrisBLACK);
  106.     if (displayIntro) {
  107.       finishedAnimating = tetris.drawText(1, 21);
  108.     } else {
  109.       if (twelveHourFormat) {
  110.         // Place holders for checking are any of the tetris objects
  111.         // currently still animating.
  112.         bool tetris1Done = false;
  113.         bool tetris2Done = false;
  114.         bool tetris3Done = false;
  115.         tetris1Done = tetris.drawNumbers(-6, 26, showColon);
  116.         tetris2Done = tetris2.drawText(56, 25);
  117.         // Only draw the top letter once the bottom letter is finished.
  118.         if (tetris2Done) {
  119.           tetris3Done = tetris3.drawText(56, 15);
  120.         }
  121.         finishedAnimating = tetris1Done && tetris2Done && tetris3Done;
  122.       } else {
  123.         finishedAnimating = tetris.drawNumbers(2, 26, showColon);
  124.       }
  125.     }
  126. #ifdef double_buffer
  127.     display.showBuffer();
  128. #endif
  129.   }
  130. #ifndef double_buffer
  131.   portEXIT_CRITICAL_ISR(&timerMux);
  132. #endif
  133. }
  134. void drawIntro(int x = 0, int y = 0)
  135. {
  136.   tetris.drawChar("P", x, y, tetris.tetrisCYAN);
  137.   tetris.drawChar("o", x + 5, y, tetris.tetrisMAGENTA);
  138.   tetris.drawChar("w", x + 11, y, tetris.tetrisYELLOW);
  139.   tetris.drawChar("e", x + 17, y, tetris.tetrisGREEN);
  140.   tetris.drawChar("r", x + 22, y, tetris.tetrisBLUE);
  141.   tetris.drawChar("e", x + 27, y, tetris.tetrisRED);
  142.   tetris.drawChar("d", x + 32, y, tetris.tetrisWHITE);
  143.   tetris.drawChar(" ", x + 37, y, tetris.tetrisMAGENTA);
  144.   tetris.drawChar("b", x + 42, y, tetris.tetrisYELLOW);
  145.   tetris.drawChar("y", x + 47, y, tetris.tetrisGREEN);
  146. }
  147. void drawConnecting(int x = 0, int y = 0)
  148. {
  149.   tetris.drawChar("C", x, y, tetris.tetrisCYAN);
  150.   tetris.drawChar("o", x + 5, y, tetris.tetrisMAGENTA);
  151.   tetris.drawChar("n", x + 11, y, tetris.tetrisYELLOW);
  152.   tetris.drawChar("n", x + 17, y, tetris.tetrisGREEN);
  153.   tetris.drawChar("e", x + 22, y, tetris.tetrisBLUE);
  154.   tetris.drawChar("c", x + 27, y, tetris.tetrisRED);
  155.   tetris.drawChar("t", x + 32, y, tetris.tetrisWHITE);
  156.   tetris.drawChar("i", x + 37, y, tetris.tetrisMAGENTA);
  157.   tetris.drawChar("n", x + 42, y, tetris.tetrisYELLOW);
  158.   tetris.drawChar("g", x + 47, y, tetris.tetrisGREEN);
  159. }
  160. void setup() {
  161.   Serial.begin(115200);
  162.   // Attempt to connect to Wifi network:
  163.   Serial.print("Connecting Wifi: ");
  164.   Serial.println(ssid);
  165.   // Set WiFi to station mode and disconnect from an AP if it was Previously
  166.   // connected
  167.   WiFi.mode(WIFI_STA);
  168.   WiFi.begin(ssid, password);
  169.   while (WiFi.status() != WL_CONNECTED) {
  170.     Serial.print(".");
  171.     delay(500);
  172.   }
  173.   Serial.println("");
  174.   Serial.println("WiFi connected");
  175.   Serial.print("IP address: ");
  176.   Serial.println(WiFi.localIP());
  177.   // Do not set up display before WiFi connection
  178.   // as it will crash!
  179.   // Intialise display library
  180.   display.begin(16, SPI_BUS_CLK, 27, SPI_BUS_MISO, SPI_BUS_SS); // TinyPICO
  181.   //display.begin(16); // Generic ESP32 including Huzzah
  182.   display.flushDisplay();
  183.   // Setup timer for driving display
  184.   timer = timerBegin(0, 80, true);
  185.   timerAttachInterrupt(timer, &display_updater, true);
  186.   timerAlarmWrite(timer, 2000, true);
  187.   timerAlarmEnable(timer);
  188.   yield();
  189. #ifdef double_buffer
  190.   display.fillScreen(tetris.tetrisBLACK);
  191. #else
  192.   display.clearDisplay();
  193. #endif
  194.   // "connecting"
  195.   drawConnecting(5, 10);
  196. #ifdef double_buffer
  197.   display.showBuffer();
  198. #endif
  199.   // Setup EZ Time
  200.   setDebug(INFO);
  201.   waitForSync();
  202.   Serial.println();
  203.   Serial.println("UTC:             " + UTC.dateTime());
  204.   myTZ.setLocation(F(MYTIMEZONE));
  205.   Serial.print(F("Time in your set timezone:         "));
  206.   Serial.println(myTZ.dateTime());
  207. #ifdef double_buffer
  208.   display.fillScreen(tetris.tetrisBLACK);
  209. #else
  210.   display.clearDisplay();
  211. #endif
  212.   // "Powered By"
  213.   drawIntro(6, 12);
  214. #ifdef double_buffer
  215.   display.showBuffer();
  216. #endif
  217.   delay(2000);
  218.   // Start the Animation Timer
  219.   tetris.setText("TINY PICO");
  220.   animationTimer = timerBegin(1, 80, true);
  221.   timerAttachInterrupt(animationTimer, &animationHandler, true);
  222.   timerAlarmWrite(animationTimer, 100000, true);
  223.   timerAlarmEnable(animationTimer);
  224.   // Wait for the animation to finish
  225.   while (!finishedAnimating)
  226.   {
  227.     delay(10); //waiting for intro to finish
  228.   }
  229.   delay(2000);
  230.   finishedAnimating = false;
  231.   displayIntro = false;
  232.   tetris.scale = 2;
  233. }
  234. void setMatrixTime() {
  235.   String timeString = "";
  236.   String AmPmString = "";
  237.   if (twelveHourFormat) {
  238.     // Get the time in format "1:15" or 11:15 (12 hour, no leading 0)
  239.     // Check the EZTime Github page for info on
  240.     // time formatting
  241.     timeString = myTZ.dateTime("g:i");
  242.     //If the length is only 4, pad it with
  243.     // a space at the beginning
  244.     if (timeString.length() == 4) {
  245.       timeString = " " + timeString;
  246.     }
  247.     //Get if its "AM" or "PM"
  248.     AmPmString = myTZ.dateTime("A");
  249.     if (lastDisplayedAmPm != AmPmString) {
  250.       Serial.println(AmPmString);
  251.       lastDisplayedAmPm = AmPmString;
  252.       // Second character is always "M"
  253.       // so need to parse it out
  254.       tetris2.setText("M", forceRefresh);
  255.       // Parse out first letter of String
  256.       tetris3.setText(AmPmString.substring(0, 1), forceRefresh);
  257.     }
  258.   } else {
  259.     // Get time in format "01:15" or "22:15"(24 hour with leading 0)
  260.     timeString = myTZ.dateTime("H:i");
  261.   }
  262.   // Only update Time if its different
  263.   if (lastDisplayedTime != timeString) {
  264.     Serial.println(timeString);
  265.     lastDisplayedTime = timeString;
  266.     tetris.setTime(timeString, forceRefresh);
  267.     // Must set this to false so animation knows
  268.     // to start again
  269.     finishedAnimating = false;
  270.   }
  271. }
  272. void handleColonAfterAnimation() {
  273.   // It will draw the colon every time, but when the colour is black it
  274.   // should look like its clearing it.
  275.   uint16_t colour =  showColon ? tetris.tetrisWHITE : tetris.tetrisBLACK;
  276.   // The x position that you draw the tetris animation object
  277.   int x = twelveHourFormat ? -6 : 2;
  278.   // The y position adjusted for where the blocks will fall from
  279.   // (this could be better!)
  280.   int y = 26 - (TETRIS_Y_DROP_DEFAULT * tetris.scale);
  281.   tetris.drawColon(x, y, colour);
  282. }
  283. void loop() {
  284.   unsigned long now = millis();
  285.   if (now > oneSecondLoopDue) {
  286.     // We can call this often, but it will only
  287.     // update when it needs to
  288.     setMatrixTime();
  289.     showColon = !showColon;
  290.     // To reduce flicker on the screen we stop clearing the screen
  291.     // when the animation is finished, but we still need the colon to
  292.     // to blink
  293.     if (finishedAnimating) {
  294.       handleColonAfterAnimation();
  295.     }
  296.     oneSecondLoopDue = now + 1000;
  297.   }
  298. }
复制代码


回复

使用道具 举报

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

本版积分规则

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

硬件清单

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

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

mail