96浏览
查看: 96|回复: 4

[项目] 【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟

[复制链接]
这是一款模拟式数字时钟,具有多种显示状态、24 小时闹钟、倒计时闹钟、多种闹钟显示状态……

这次我将向你展示如何制作一个美观的环形时钟。该时钟采用 WS2812 环形设计,内含 60 个 LED(4 个四分之一圆 Neopixel 灯 x 15 个 LED),非常适合此用途。这是一款模拟数字时钟,具有多种显示状态、24 小时闹钟、倒计时闹钟、多种闹钟显示状态以及演示模式。小时、分钟和秒分别由相应 LED 的不同颜色表示。

戒指支架是用3D打印机制作的,您可以下载下方的.stl文件。桌面时钟的物理外壳基于Neopixel戒指的尺寸。时钟需要5V/3A或更高的电源供电。代码取自开源项目“Rise and Shine LED Clock”。我只对硬件做了一些小改动,以改变LED的光强度。

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图1

驴友花雕  中级技神
 楼主|

发表于 昨天 08:50

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟

该装置制作非常简单,仅包含几个组件:

- 60 个 LED WS2812 环,由四个四分之一圆形 Neopixels 和 15 个 LED 组成

- Arduino 纳米微控制器

- 带按钮的旋转编码器

- 两个 3A 整流二极管

- 和一个开关

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图1

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 08:52

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟

开机后(短按3次),我们进入钟面切换模式。左右移动旋转编码器即可切换钟面:共有6种不同的钟面。

- 标准时钟,带有 3 个点,红色表示小时,绿色表示分钟,蓝色表示秒

- 呼吸效果

- 每小时亮起 12 个白色 LED

- 带摆锤

- 逐渐改变秒数

- 60分钟计时器

要设置正确的时间,请按住按钮两秒钟以上。闪烁的指示灯指示设置模式,以小时、分钟和秒为单位。按下按钮后,我们将进入闹钟显示。长按按钮,我们将进入闹钟设置模式。再次按下按钮后,我们将进入倒计时模式。在此模式下,系统将对所选时间进行计时,范围为 1 至 60 分钟。

最后是演示模式。在演示模式下,钟面会在特定时间逐一变化。

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图1

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图2

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图3

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图4

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 08:57

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟

项目代码

  1. // Add options for background settings
  2. // TO DO: Clean up and comment code...
  3. // BUG: demo state should start as mode 0 after intro
  4. // NICE TO HAVE: When alarm is cancelled, the alarm still remains set for next day.
  5. //Add the following libraries to the respective folder for you operating system. See http://arduino.cc/en/Guide/Environment
  6. #include <FastLED.h> // FastSPI Library from http://code.google.com/p/fastspi/
  7. #include <Wire.h> //This is to communicate via I2C. On arduino Uno & Nano use pins A4 for SDA (yellow/orange) and A5 for SCL (green). For other boards ee http://arduino.cc/en/Reference/Wire
  8. #include <RTClib.h>           // Include the RTClib library to enable communication with the real time clock.
  9. #include <EEPROM.h>           // Include the EEPROM library to enable the storing and retrevel of settings.
  10. #include <Bounce.h>           // Include the Bounce library for de-bouncing issues with push buttons.
  11. #include <Encoder.h>          // Include the Encoder library to read the out puts of the rotary encoders
  12. RTC_DS1307 RTC; // Establishes the chipset of the Real Time Clock
  13. #define LEDStripPin A0 // Pin used for the data to the LED strip
  14. #define menuPin A3 // Pin used for the menu button (green stripe)
  15. #define numLEDs 60 // Number of LEDs in strip
  16. // Setting up the LED strip
  17. struct CRGB leds[numLEDs];
  18. Encoder rotary1(2, 3); // Setting up the Rotary Encoder
  19. DateTime old; // Variable to compare new and old time, to see if it has moved on.
  20. int rotary1Pos  = 0;
  21. int subSeconds; // 60th's of a second
  22. int secondBrightness;
  23. int secondBrightness2;
  24. int breathBrightness;
  25. long newSecTime; // Variable to record when a new second starts, allowing to create milli seconds
  26. long oldSecTime;
  27. long flashTime; //
  28. long breathCycleTime;
  29. #define holdTime 1500
  30. int cyclesPerSec;
  31. float cyclesPerSecFloat; // So can be used as a float in calcs
  32. float fracOfSec;
  33. float breathFracOfSec;
  34. boolean demo;
  35. #define demoTime 12 // seconds
  36. long previousDemoTime;
  37. long currentDemoTime;
  38. boolean swingBack = false;
  39. int timeHour;
  40. int timeMin;
  41. int timeSec;
  42. int alarmMin; // The minute of the alarm  
  43. int alarmHour; // The hour of the alarm 0-23
  44. int alarmDay = 0; // The day of the alarm
  45. boolean alarmSet; // Whether the alarm is set or not
  46. int modeAddress = 0; // Address of where mode is stored in the EEPROM
  47. int alarmMinAddress = 1; // Address of where alarm minute is stored in the EEPROM
  48. int alarmHourAddress = 2; // Address of where alarm hour is stored in the EEPROM
  49. int alarmSetAddress = 3; // Address of where alarm state is stored in the EEPROM
  50. int alarmModeAddress = 4; // Address of where the alarm mode is stored in the EEPROM
  51. boolean alarmTrig = false; // Whether the alarm has been triggered or not
  52. long alarmTrigTime; // Milli seconds since the alarm was triggered
  53. boolean countDown = false;
  54. long countDownTime = 0;
  55. long currentCountDown = 0;
  56. long startCountDown;
  57. int countDownMin;
  58. int countDownSec;
  59. int countDownFlash;
  60. int demoIntro = 0;
  61. int j = 0;
  62. long timeInterval = 5;
  63. long currentMillis;
  64. long previousMillis = 0;
  65. float LEDBrightness = 0;
  66. float fadeTime;
  67. float brightFadeRad;
  68. int state = 0; // Variable of the state of the clock, with the following defined states
  69. #define clockState 0
  70. #define alarmState 1
  71. #define setAlarmHourState 2
  72. #define setAlarmMinState 3
  73. #define setClockHourState 4
  74. #define setClockMinState 5
  75. #define setClockSecState 6
  76. #define countDownState 7
  77. #define demoState 8
  78. int mode; // Variable of the display mode of the clock
  79. int modeMax = 6; // Change this when new modes are added. This is so selecting modes can go back beyond.
  80. int alarmMode; // Variable of the alarm display mode
  81. int alarmModeMax = 3;
  82. Bounce menuBouncer = Bounce(menuPin,20); // Instantiate a Bounce object with a 50 millisecond debounce time for the menu button
  83. boolean menuButton = false;
  84. boolean menuPressed = false;
  85. boolean menuReleased = false;
  86. int advanceMove = 0;
  87. boolean countTime = false;
  88. long menuTimePressed;
  89. long lastRotary;
  90. int rotaryTime = 1000;
  91. int LEDPosition;
  92. int reverseLEDPosition;
  93. int pendulumPos;
  94. int fiveMins;
  95. int odd;
  96. int LEDOffset = 30;
  97. void setup()
  98. {
  99.   // Set up all pins
  100.   pinMode(menuPin, INPUT_PULLUP);     // Uses the internal 20k pull up resistor. Pre Arduino_v.1.0.1 need to be "digitalWrite(menuPin,HIGH);pinMode(menuPin,INPUT);"
  101.    
  102.   // Start LEDs
  103.   LEDS.addLeds<WS2811, LEDStripPin, GRB>(leds, numLEDs); // Structure of the LED data. I have changed to from rgb to grb, as using an alternative LED strip. Test & change these if you're getting different colours.
  104.   
  105.   // Start RTC
  106.   Wire.begin(); // Starts the Wire library allows I2C communication to the Real Time Clock
  107.   RTC.begin(); // Starts communications to the RTC
  108.   
  109.   Serial.begin(9600); // Starts the serial communications
  110.   // Uncomment to reset all the EEPROM addresses. You will have to comment again and reload, otherwise it will not save anything each time power is cycled
  111.   // write a 0 to all 512 bytes of the EEPROM
  112. //  for (int i = 0; i < 512; i++)
  113. //  {EEPROM.write(i, 0);}
  114.   // Load any saved setting since power off, such as mode & alarm time  
  115.   mode = EEPROM.read(modeAddress); // The mode will be stored in the address "0" of the EEPROM
  116.   alarmMin = EEPROM.read(alarmMinAddress); // The mode will be stored in the address "1" of the EEPROM
  117.   alarmHour = EEPROM.read(alarmHourAddress); // The mode will be stored in the address "2" of the EEPROM
  118.   alarmSet = EEPROM.read(alarmSetAddress); // The mode will be stored in the address "2" of the EEPROM
  119.   alarmMode = EEPROM.read(alarmModeAddress);
  120.   // Prints all the saved EEPROM data to Serial
  121.   Serial.print("Mode is ");Serial.println(mode);
  122.   Serial.print("Alarm Hour is ");Serial.println(alarmHour);
  123.   Serial.print("Alarm Min is ");Serial.println(alarmMin);
  124.   Serial.print("Alarm is set ");Serial.println(alarmSet);
  125.   Serial.print("Alarm Mode is ");Serial.println(alarmMode);
  126.   // create a loop that calcuated the number of counted milliseconds between each second.
  127.   DateTime now = RTC.now();
  128.   //  startTime = millis();  
  129.   //  while (RTC.old() = RTC.new())
  130.   
  131.   //  if (now.month() == 1 && now.day() == 1 && now.hour() == 0 && now.minute() == 0 && now.minute() == 0)
  132.   //    {}
  133.       
  134.   Serial.print("Hour time is... ");
  135.   Serial.println(now.hour());
  136.   Serial.print("Min time is... ");
  137.   Serial.println(now.minute());
  138.   Serial.print("Sec time is... ");
  139.   Serial.println(now.second());
  140.   Serial.print("Year is... ");
  141.   Serial.println(now.year());
  142.   Serial.print("Month is... ");
  143.   Serial.println(now.month());
  144.   Serial.print("Day is... ");
  145.   Serial.println(now.day());
  146. }
  147. void loop()
  148. {
  149.   DateTime now = RTC.now(); // Fetches the time from RTC
  150.   
  151.   // Check for any button presses and action accordingley
  152.   menuButton = menuBouncer.update();  // Update the debouncer for the menu button and saves state to menuButton
  153.   rotary1Pos = rotary1.read(); // Checks the rotary position
  154.   if (rotary1Pos <= -2 && lastRotary - millis() >= rotaryTime)
  155.     {
  156.       advanceMove = -1;
  157.       rotary1.write(0);
  158.       lastRotary = millis();
  159.     }
  160.   if (rotary1Pos >= 2 && lastRotary - millis() >= rotaryTime)
  161.     {
  162.       advanceMove = 1;
  163.       rotary1.write(0);
  164.       lastRotary = millis();
  165.     }
  166.   if (menuButton == true || advanceMove != 0 || countTime == true) {buttonCheck(menuBouncer,now);}
  167.   
  168.   // clear LED array
  169.   memset(leds, 0, numLEDs * 3);
  170.   
  171.   // Check alarm and trigger if the time matches
  172.   if (alarmSet == true && alarmDay != now.day()) // The alarmDay statement ensures it is a newly set alarm or repeat from previous day, not within the minute of an alarm cancel.
  173.     {
  174.       if (alarmTrig == false) {alarm(now);}
  175.       else {alarmDisplay();}
  176.     }
  177. // Check the Countdown Timer
  178.   if (countDown == true)
  179.     {
  180.       currentCountDown = countDownTime + startCountDown - now.unixtime();
  181.       if ( currentCountDown <= 0)
  182.         {
  183.           state =countDownState;
  184.         }
  185.     }
  186.   // Set the time LED's
  187.   if (state == setClockHourState || state == setClockMinState || state == setClockSecState) {setClockDisplay(now);}
  188.   else if (state == alarmState || state == setAlarmHourState || state == setAlarmMinState) {setAlarmDisplay();}
  189.   else if (state == countDownState) {countDownDisplay(now);}
  190.   else if (state == demoState) {runDemo(now);}
  191.   else {timeDisplay(now);}
  192.   // Update LEDs
  193.   LEDS.show();
  194. }
  195. void buttonCheck(Bounce menuBouncer, DateTime now)
  196. {
  197.   if (menuBouncer.fallingEdge()) // Checks if a button is pressed, if so sets countTime to true
  198.     {
  199.       countTime = true;
  200.       Serial.println("rising edge");
  201.     }
  202.   if (menuBouncer.risingEdge()) // Checks if a button is released,
  203.     {
  204.       countTime = false;
  205.       Serial.println("rising edge");
  206.     } // if so sets countTime to false. Now the ...TimePressed will not be updated when enters the buttonCheck,
  207.   if (countTime) // otherwise will menuBouncer.duration will
  208.     {
  209.       menuTimePressed = menuBouncer.duration();
  210.       if (menuTimePressed >= (holdTime - 100) && menuTimePressed <= holdTime)
  211.         {
  212.           clearLEDs();
  213.           LEDS.show();
  214.           delay(100);
  215.         }
  216.     }
  217.   menuReleased = menuBouncer.risingEdge();
  218.   if (menuPressed == true) {Serial.println("Menu Button Pressed");}
  219.   if (menuReleased == true) {Serial.println("Menu Button Released");}
  220.   Serial.print("Menu Bounce Duration ");
  221.   Serial.println(menuTimePressed);
  222.   if (alarmTrig == true)
  223.     {
  224.       alarmTrig = false;
  225.       alarmDay = now.day(); // When the alarm is cancelled it will not display until next day. As without it, it would start again if within a minute, or completely turn off the alarm.
  226.       delay(300); // I added this 300ms delay, so there is time for the button to be released
  227.       return; // This return exits the buttonCheck function, so no actions are performs
  228.     }  
  229.   switch (state)
  230.     {
  231.       case clockState: // State 0
  232.         if (advanceMove == -1 && mode == 0)
  233.           {
  234.             mode = modeMax;
  235.             advanceMove = 0;
  236.           }
  237.         else if(advanceMove != 0) //if displaying the clock, advance button is pressed & released, then mode will change
  238.           {
  239.             mode = mode + advanceMove;
  240.             EEPROM.write(modeAddress,mode);
  241.             advanceMove = 0;
  242.           }
  243.         else if(menuReleased == true)
  244.           {
  245.             if (menuTimePressed <= holdTime) {state = alarmState; newSecTime = millis();}// if displaying the clock, menu button is pressed & released, then Alarm is displayed
  246.             else {state = setClockHourState;} // if displaying the clock, menu button is held & released, then clock hour can be set
  247.           }
  248.         break;
  249.       case alarmState: // State 1
  250.         if (advanceMove == -1 && alarmMode <= 0)
  251.           {
  252.             alarmMode = alarmModeMax;
  253.             alarmSet = 1;
  254.           }
  255.         else if (advanceMove == 1 && alarmMode >= alarmModeMax)
  256.           {
  257.             alarmMode = 0;
  258.             alarmSet = 0;
  259.           }
  260.         else if (advanceMove != 0)
  261.           {
  262.             alarmMode = alarmMode + advanceMove;
  263.             if (alarmMode == 0) {alarmSet = 0;}
  264.             else {alarmSet = 1;}
  265.           }         
  266.         Serial.print("alarmState is ");
  267.         Serial.println(alarmState);            
  268.         Serial.print("alarmMode is ");
  269.         Serial.println(alarmMode);
  270.         EEPROM.write(alarmSetAddress,alarmSet);
  271.         EEPROM.write(alarmModeAddress,alarmMode);
  272.         advanceMove = 0;
  273.         alarmTrig = false;
  274.         if (menuReleased == true)
  275.           {
  276.             if (menuTimePressed <= holdTime) {state = countDownState; j = 0;}// if displaying the alarm time, menu button is pressed & released, then clock is displayed
  277.             else {state = setAlarmHourState;} // if displaying the alarm time, menu button is held & released, then alarm hour can be set
  278.           }
  279.         break;
  280.       case setAlarmHourState: // State 2
  281.         if (menuReleased == true) {state = setAlarmMinState;}
  282.         else if (advanceMove == 1 && alarmHour >= 23) {alarmHour = 0;}
  283.         else if (advanceMove == -1 && alarmHour <= 0) {alarmHour = 23;}
  284.         else if (advanceMove != 0) {alarmHour = alarmHour + advanceMove;}
  285.         EEPROM.write(alarmHourAddress,alarmHour);
  286.         advanceMove = 0;
  287.         break;
  288.       case setAlarmMinState: // State 3
  289.         if (menuReleased == true)
  290.           {
  291.             state = alarmState;
  292.             alarmDay = 0;
  293.             newSecTime = millis();
  294.           }
  295.         else if (advanceMove == 1 && alarmMin >= 59) {alarmMin = 0;}
  296.         else if (advanceMove == -1 && alarmMin <= 0) {alarmMin = 59;}
  297.         else if (advanceMove != 0) {alarmMin = alarmMin + advanceMove;}
  298.         EEPROM.write(alarmMinAddress,alarmMin);
  299.         advanceMove = 0;
  300.         break;
  301.       case setClockHourState: // State 4
  302.         if (menuReleased == true) {state = setClockMinState;}
  303.         else if (advanceMove == 1 && now.hour() == 23)
  304.           {
  305.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), 0, now.minute(), now.second()));
  306.             advanceMove = 0;
  307.           }
  308.         else if (advanceMove == -1 && now.hour() == 0)
  309.           {
  310.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), 23, now.minute(), now.second()));
  311.             advanceMove = 0;
  312.           }
  313.         else if (advanceMove != 0)
  314.           {
  315.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), (now.hour() + advanceMove), now.minute(), now.second()));
  316.             advanceMove = 0;
  317.           }
  318.         break;
  319.       case setClockMinState: // State 5
  320.         if (menuReleased == true) {state = setClockSecState;}
  321.         else if (advanceMove == 1 && now.minute() == 59)
  322.           {
  323.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), 0, now.second()));
  324.             advanceMove = 0;
  325.           }
  326.         else if (advanceMove == -1 && now.minute() == 0)
  327.           {
  328.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), 59, now.second()));
  329.             advanceMove = 0;
  330.           }
  331.         else if (advanceMove != 0)
  332.           {
  333.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), (now.minute() + advanceMove), now.second()));
  334.             advanceMove = 0;
  335.           }
  336.         break;
  337.       case setClockSecState: // State 6
  338.         if (menuReleased == true) {state = clockState;}
  339.         else if (advanceMove == 1 && now.second() == 59)
  340.           {
  341.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), 0));
  342.             advanceMove = 0;
  343.           }
  344.         else if (advanceMove == -1 && now.second() == 0)
  345.           {
  346.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), 59));
  347.             advanceMove = 0;
  348.           }
  349.         else if (advanceMove != 0)
  350.           {
  351.             RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), (now.second() + advanceMove)));
  352.             advanceMove = 0;
  353.           }
  354.         break;
  355.       case countDownState: // State 7
  356.         if(menuReleased == true)
  357.           {
  358.             if (menuTimePressed <= holdTime)
  359.               {
  360.                 if (countDown == true && countDownTime <= 0) {countDown = false; countDownTime = 0; currentCountDown = 0;}
  361.                 else if (countDown == false && countDownTime > 0) {countDown = true; startCountDown = now.unixtime();}
  362.                 else {state = demoState; demoIntro = 1; j = 0;}// if displaying the count down, menu button is pressed & released, then demo State is displayed
  363.               }
  364.             else {countDown = false; countDownTime = 0; currentCountDown = 0; j = 0;} // if displaying the clock, menu button is held & released, then the count down is reset
  365.           }
  366.         else if (advanceMove == -1 && currentCountDown <= 0)
  367.           {
  368.             countDown = false;
  369.             countDownTime = 0;
  370.             currentCountDown = 0;
  371.             demoIntro = 0;         
  372.           }
  373.         else if (advanceMove == 1 && currentCountDown >= 3600)
  374.           {
  375.             countDown = false;
  376.             countDownTime = 3600;           
  377.           }
  378.         else if (advanceMove != 0) //if displaying the count down, rotary encoder is turned then will change accordingley
  379.           {
  380.             countDown = false;
  381.             countDownTime = currentCountDown - currentCountDown%60 + advanceMove*60; // This rounds the count down minute up to the next minute
  382.           }
  383.         advanceMove = 0;
  384.         break;
  385.       case demoState: // State 8
  386.         if(menuReleased == true) {state = clockState; mode = EEPROM.read(modeAddress);} // if displaying the demo, menu button pressed then the clock will display and restore to the mode before demo started
  387.         break;
  388.     }
  389.   if (menuReleased || advanceMove !=0) {countTime = false;}
  390.   Serial.print("Mode is ");
  391.   Serial.println(mode);
  392.   Serial.print("State is ");
  393.   Serial.println(state);
  394. }
  395. void setAlarmDisplay()
  396. {
  397.   for (int i = 0; i < numLEDs; i++)
  398.     {
  399.       fiveMins = i%5;
  400.       if (fiveMins == 0)
  401.         {
  402.           leds[i].r = 100;
  403.           leds[i].g = 100;
  404.           leds[i].b = 100;
  405.         }
  406.     }
  407.   if (alarmSet == 0)
  408.     {
  409.       for (int i = 0; i < numLEDs; i++) // Sets background to red, to state that alarm IS NOT set
  410.         {
  411.           fiveMins = i%5;
  412.           if (fiveMins == 0)
  413.             {
  414.               leds[i].r = 20;
  415.               leds[i].g = 0;
  416.               leds[i].b = 0;
  417.             }  
  418.         }     
  419.     }
  420.   else
  421.     {
  422.       for (int i = 0; i < numLEDs; i++) // Sets background to green, to state that alarm IS set
  423.         {
  424.           fiveMins = i%5;
  425.           if (fiveMins == 0)
  426.             {
  427.               leds[i].r = 0;
  428.               leds[i].g = 20;
  429.               leds[i].b = 0;
  430.             }  
  431.         }     
  432.     }
  433.   if (alarmHour <= 11)
  434.     {
  435.       leds[(alarmHour*5+LEDOffset)%60].r = 255;
  436.     }
  437.   else
  438.     {
  439.       leds[((alarmHour - 12)*5+LEDOffset+59)%60].r = 25;   
  440.       leds[((alarmHour - 12)*5+LEDOffset)%60].r = 255;
  441.       leds[((alarmHour - 12)*5+LEDOffset+1)%60].r = 25;
  442.     }
  443.   leds[(alarmMin+LEDOffset)%60].g = 100;
  444.   flashTime = millis();
  445.   if (state == setAlarmHourState && flashTime%300 >= 150)
  446.     {
  447.       leds[(((alarmHour%12)*5)+LEDOffset+59)%60].r = 0;   
  448.       leds[(((alarmHour%12)*5)+LEDOffset)%60].r = 0;
  449.       leds[(((alarmHour%12)*5)+LEDOffset+1)%60].r = 0;
  450.     }
  451.   if (state == setAlarmMinState && flashTime%300 >= 150)
  452.     {
  453.       leds[(alarmMin+LEDOffset)%60].g = 0;
  454.     }
  455.   leds[(alarmMode+LEDOffset)%60].b = 255;
  456. }
  457. void setClockDisplay(DateTime now)
  458. {
  459.   for (int i = 0; i < numLEDs; i++)
  460.     {
  461.       fiveMins = i%5;
  462.       if (fiveMins == 0)
  463.         {
  464.           leds[i].r = 10;
  465.           leds[i].g = 10;
  466.           leds[i].b = 10;
  467.         }
  468.     }
  469.   if (now.hour() <= 11) {leds[(now.hour()*5+LEDOffset)%60].r = 255;}
  470.   else
  471.     {
  472.       leds[((now.hour() - 12)*5+LEDOffset+59)%60].r = 255;
  473.       leds[((now.hour() - 12)*5+LEDOffset)%60].r = 255;   
  474.       leds[((now.hour() - 12)*5+LEDOffset+1)%60].r = 255;
  475.     }
  476.   flashTime = millis();
  477.   if (state == setClockHourState && flashTime%300 >= 150)
  478.     {
  479.       leds[(((now.hour()%12)*5)+LEDOffset+59)%60].r = 0;   
  480.       leds[((now.hour()%12)*5+LEDOffset)%60].r = 0;
  481.       leds[(((now.hour()%12)*5)+LEDOffset+1)%60].r = 0;
  482.     }
  483.   if (state == setClockMinState && flashTime%300 >= 150) {leds[(now.minute()+LEDOffset)%60].g = 0;}
  484.   else {leds[(now.minute()+LEDOffset)%60].g = 255;}
  485.   if (state == setClockSecState && flashTime%300 >= 150) {leds[(now.second()+LEDOffset)%60].b = 0;}
  486.   else {leds[(now.second()+LEDOffset)%60].b = 255;}
  487. }
  488. // Check if alarm is active and if is it time for the alarm to trigger
  489. void alarm(DateTime now)
  490. {
  491.   if ((alarmMin == now.minute()%60) && (alarmHour == now.hour()%24)) //check if the time is the same to trigger alarm
  492.     {
  493.       alarmTrig = true;
  494.       alarmTrigTime = millis();
  495.     }
  496. }
  497. void alarmDisplay() // Displays the alarm
  498. {
  499.   switch (alarmMode)
  500.     {
  501.       case 1:
  502.         // set all LEDs to a dim white
  503.         for (int i = 0; i < numLEDs; i++)
  504.           {
  505.             leds[i].r = 100;
  506.             leds[i].g = 100;
  507.             leds[i].b = 100;
  508.           }
  509.         break;
  510.       case 2:
  511.         LEDPosition = ((millis() - alarmTrigTime)/300);
  512.         reverseLEDPosition = 60 - LEDPosition;
  513.         if (LEDPosition >= 0 && LEDPosition <= 29)
  514.           {
  515.             for (int i = 0; i < LEDPosition; i++)
  516.               {
  517.                 leds[(i+LEDOffset)%60].r = 5;
  518.                 leds[(i+LEDOffset)%60].g = 5;
  519.                 leds[(i+LEDOffset)%60].b = 5;
  520.               }
  521.           }
  522.         if (reverseLEDPosition <= 59 && reverseLEDPosition >= 31)
  523.           {
  524.             for (int i = 59; i > reverseLEDPosition; i--)
  525.               {
  526.                 leds[(i+LEDOffset)%60].r = 5;
  527.                 leds[(i+LEDOffset)%60].g = 5;
  528.                 leds[(i+LEDOffset)%60].b = 5;
  529.               }              
  530.           }
  531.         if (LEDPosition >= 30)
  532.           {
  533.             for (int i = 0; i < numLEDs; i++)
  534.               {
  535.                 leds[(i+LEDOffset)%60].r = 5;
  536.                 leds[(i+LEDOffset)%60].g = 5;
  537.                 leds[(i+LEDOffset)%60].b = 5;
  538.               }           
  539.           }            
  540.         break;
  541.       case 3:
  542.         fadeTime = 60000;
  543.         brightFadeRad = (millis() - alarmTrigTime)/fadeTime; // Divided by the time period of the fade up.
  544.         if (millis() > alarmTrigTime + fadeTime) LEDBrightness = 255;
  545.         else LEDBrightness = 255.0*(1.0+sin((1.57*brightFadeRad)-1.57));
  546.         Serial.println(brightFadeRad);
  547.         Serial.println(LEDBrightness);
  548.         for (int i = 0; i < numLEDs; i++)
  549.           {
  550.             leds[i].r = LEDBrightness;
  551.             leds[i].g = LEDBrightness;
  552.             leds[i].b = LEDBrightness;
  553.           }
  554.         break;
  555. // Currently not working        
  556. //      case 4:
  557. //        fadeTime = 60000;
  558. //        brightFadeRad = (millis() - alarmTrigTime)/fadeTime; // Divided by the time period of the fade up.
  559. //        LEDPosition = ((millis() - alarmTrigTime)/(fadeTime/30));
  560. ////        if (millis() > alarmTrigTime + fadeTime) LEDBrightness = 255; // If the fade time is complete, then the LED brightness will be set to full.
  561. //        if (brightFadeRad <= 0) LEDBrightness = 0;
  562. //        else if (brightFadeRad >= 0) LEDBrightness = 1;
  563. //        else LEDBrightness = 255.0*(1.0+sin((1.57*brightFadeRad)-1.57));
  564. //        
  565. ////        Serial.println(brightFadeRad);
  566. ////        Serial.println(LEDBrightness);
  567. //        reverseLEDPosition = 60 - LEDPosition;
  568. //        if (LEDPosition >= 0 && LEDPosition <= 29)
  569. //          {
  570. //            for (int i = 0; i < LEDPosition; i++)
  571. //              {
  572. //                leds[i].r = LEDBrightness;
  573. //                leds[i].g = LEDBrightness;
  574. //                leds[i].b = LEDBrightness;
  575. //              }
  576. //          }
  577. //        if (reverseLEDPosition <= 59 && reverseLEDPosition >= 31)
  578. //          {
  579. //            for (int i = 59; i > reverseLEDPosition; i--)
  580. //              {
  581. //                leds[i].r = LEDBrightness;
  582. //                leds[i].g = LEDBrightness;
  583. //                leds[i].b = LEDBrightness;
  584. //              }              
  585. //          }
  586. //        if (LEDPosition >= 30)
  587. //          {
  588. //            for (int i = 0; i < numLEDs; i++)
  589. //              {
  590. //                leds[i].r = LEDBrightness;
  591. //                leds[i].g = LEDBrightness;
  592. //                leds[i].b = LEDBrightness;
  593. //              }           
  594. //          }  
  595. //        break;
  596.     }
  597. }
  598. //  
  599. void countDownDisplay(DateTime now)
  600. {
  601.   flashTime = millis();
  602.   if (countDown == true)
  603.     {
  604.       currentCountDown = countDownTime + startCountDown - now.unixtime();
  605.       if (currentCountDown > 0)
  606.         {
  607.           countDownMin = currentCountDown / 60;
  608.           countDownSec = currentCountDown%60 * 4; // have multiplied by 4 to create brightness
  609.           for (int i = 0; i < countDownMin; i++) {leds[(i+LEDOffset+1)%60].b = 240;} // Set a blue LED for each complete minute that is remaining
  610.           leds[(countDownMin+LEDOffset+1)%60].b = countDownSec; // Display the remaining secconds of the current minute as its brightness      
  611.         }
  612.       else
  613.         {
  614.           countDownFlash = now.unixtime()%2;
  615.           if (countDownFlash == 0)
  616.             {
  617.               for (int i = 0; i < numLEDs; i++) // Set the background as all off
  618.                 {
  619.                   leds[i].r = 0;
  620.                   leds[i].g = 0;
  621.                   leds[i].b = 0;
  622.                 }
  623.             }
  624.           else
  625.             {
  626.               for (int i = 0; i < numLEDs; i++) // Set the background as all blue
  627.                 {
  628.                   leds[i].r = 0;
  629.                   leds[i].g = 0;
  630.                   leds[i].b = 255;
  631.                 }
  632.             }
  633.         }
  634.     }
  635.   else
  636.     {
  637.       currentCountDown = countDownTime;
  638.       if (countDownTime == 0)
  639.         {
  640.           currentMillis = millis();
  641.           clearLEDs();
  642.           switch (demoIntro)
  643.             {
  644.               case 0:
  645.                 for (int i = 0; i < j; i++) {leds[(i+LEDOffset+1)%60].b = 20;}
  646.                 if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  647.                 if (j == numLEDs) {demoIntro = 1;}
  648.                 break;
  649.               case 1:
  650.                 for (int i = 0; i < j; i++) {leds[(i+LEDOffset+1)%60].b = 20;}
  651.                 if (currentMillis - previousMillis > timeInterval) {j--; previousMillis = currentMillis;}
  652.                 if (j < 0) {demoIntro = 0;}
  653.                 break;
  654.             }
  655.         }
  656.       else if (countDownTime > 0 && flashTime%300 >= 150)
  657.         {
  658.           countDownMin = currentCountDown / 60; //
  659.           for (int i = 0; i < countDownMin; i++) {leds[(i+LEDOffset+1)%60].b = 255;} // Set a blue LED for each complete minute that is remaining
  660.         }
  661.     }
  662. }
  663. void runDemo(DateTime now)
  664. {
  665.   currentDemoTime = now.unixtime();
  666.   currentMillis = millis();
  667.   clearLEDs();
  668.   switch (demoIntro)
  669.     {
  670.       case 0:
  671.         timeDisplay(now);
  672.         if (currentDemoTime - previousDemoTime > demoTime) {previousDemoTime = currentDemoTime; mode++;}
  673.         break;
  674.       case 1:
  675.         for (int i = 0; i < j; i++) {leds[i].r = 255;}
  676.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  677.         if (j == numLEDs) {j = 0; demoIntro++;}
  678.         break;
  679.       case 2:
  680.         for (int i = j; i < numLEDs; i++) {leds[i].r = 255;}
  681.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  682.         if (j == numLEDs) {j = 0; demoIntro++;}
  683.         break;
  684.       case 3:
  685.         for (int i = 0; i < j; i++) {leds[i].g = 255;}
  686.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  687.         if (j == numLEDs) {j = 0; demoIntro++;}
  688.         break;
  689.       case 4:
  690.         for (int i = j; i < numLEDs; i++) {leds[i].g = 255;}
  691.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  692.         if (j == numLEDs) {j = 0; demoIntro++;}
  693.         break;
  694.       case 5:
  695.         for (int i = 0; i < j; i++) {leds[i].b = 255;}
  696.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  697.         if (j == numLEDs) {j = 0; demoIntro++;}
  698.         break;
  699.       case 6:
  700.         for (int i = j; i < numLEDs; i++) {leds[i].b = 255;}
  701.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  702.         if (j == numLEDs) {j = 0; demoIntro++;}
  703.         break;
  704.       case 7:
  705.         for (int i = 0; i < j; i++) {leds[i].r = 255; leds[i].g = 255; leds[i].b = 255;}
  706.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  707.         if (j == numLEDs) {j = 0; demoIntro++;}
  708.         break;
  709.       case 8:
  710.         for (int i = j; i < numLEDs; i++) {leds[i].r = 255; leds[i].g = 255; leds[i].b = 255;}
  711.         if (currentMillis - previousMillis > timeInterval) {j++; previousMillis = currentMillis;}
  712.         if (j == numLEDs)
  713.           {
  714.             demoIntro = 0;
  715.             mode = 0;
  716.             Serial.print("Mode is ");
  717.             Serial.println(mode);
  718.             Serial.print("State is ");
  719.             Serial.println(state);
  720.           }
  721.         break;
  722.     }
  723. }
  724. void clearLEDs()
  725. {      
  726.   for (int i = 0; i < numLEDs; i++) // Set all the LEDs to off
  727.     {
  728.       leds[i].r = 0;
  729.       leds[i].g = 0;
  730.       leds[i].b = 0;
  731.     }
  732. }
  733. void timeDisplay(DateTime now)
  734. {
  735.   switch (mode)
  736.     {
  737.       case 0:
  738.         minimalClock(now);
  739.         break;
  740.       case 1:
  741.         basicClock(now);
  742.         break;
  743.       case 2:
  744.         smoothSecond(now);
  745.         break;
  746.       case 3:
  747.         outlineClock(now);
  748.         break;
  749.       case 4:
  750.         minimalMilliSec(now);
  751.         break;
  752.       case 5:
  753.         simplePendulum(now);
  754.         break;
  755.       case 6:
  756.         breathingClock(now);
  757.         break;
  758.       default: // Keep this here and add more timeDisplay modes as defined cases.
  759.         {
  760.           mode = 0;
  761.         }
  762.     }
  763. }
  764. ////////////////////////////////////////////////////////////////////////////////////////////
  765. //   CLOCK DISPLAY MODES
  766. // Add any new display mode functions here. Then add to the "void timeDisplay(DateTime now)" function.
  767. // Add each of the new display mode functions as a new "case", leaving default last.
  768. ////////////////////////////////////////////////////////////////////////////////////////////
  769. //
  770. void minimalClock(DateTime now)
  771. {
  772.   unsigned char hourPos = (now.hour()%12)*5;
  773.   leds[(hourPos+LEDOffset)%60].r = 255;
  774.   leds[(now.minute()+LEDOffset)%60].g = 255;
  775.   leds[(now.second()+LEDOffset)%60].b = 255;
  776. }
  777. //
  778. void basicClock(DateTime now)
  779. {
  780.   unsigned char hourPos = ((now.hour()%12)*5 + (now.minute()+6)/12);
  781.   leds[(hourPos+LEDOffset+59)%60].r = 255;
  782.   leds[(hourPos+LEDOffset+59)%60].g = 0;
  783.   leds[(hourPos+LEDOffset+59)%60].b = 0;  
  784.   leds[(hourPos+LEDOffset)%60].r = 255;
  785.   leds[(hourPos+LEDOffset)%60].g = 0;
  786.   leds[(hourPos+LEDOffset)%60].b = 0;
  787.   leds[(hourPos+LEDOffset+1)%60].r = 255;
  788.   leds[(hourPos+LEDOffset+1)%60].g = 0;
  789.   leds[(hourPos+LEDOffset+1)%60].b = 0;
  790.   leds[(now.minute()+LEDOffset)%60].r = 0;
  791.   leds[(now.minute()+LEDOffset)%60].g = 255;
  792.   leds[(now.minute()+LEDOffset)%60].b = 0;  
  793.   leds[(now.second()+LEDOffset)%60].r = 0;
  794.   leds[(now.second()+LEDOffset)%60].g = 0;
  795.   leds[(now.second()+LEDOffset)%60].b = 255;
  796.   
  797. }
  798. //
  799. void smoothSecond(DateTime now)
  800. {
  801.   if (now.second()!=old.second())
  802.     {
  803.       old = now;
  804.       cyclesPerSec = millis() - newSecTime;
  805.       cyclesPerSecFloat = (float) cyclesPerSec;
  806.       newSecTime = millis();      
  807.     }
  808.   // set hour, min & sec LEDs
  809.   fracOfSec = (millis() - newSecTime)/cyclesPerSecFloat;  // This divides by 733, but should be 1000 and not sure why???
  810.   if (subSeconds < cyclesPerSec) {secondBrightness = 50.0*(1.0+sin((3.14*fracOfSec)-1.57));}
  811.   if (subSeconds < cyclesPerSec) {secondBrightness2 = 50.0*(1.0+sin((3.14*fracOfSec)+1.57));}
  812.   unsigned char hourPos = ((now.hour()%12)*5 + (now.minute()+6)/12);
  813.   // The colours are set last, so if on same LED mixed colours are created
  814.   leds[(hourPos+LEDOffset+59)%60].r = 255;   
  815.   leds[(hourPos+LEDOffset)%60].r = 255;
  816.   leds[(hourPos+LEDOffset+1)%60].r = 255;
  817.   leds[(now.minute()+LEDOffset)%60].g = 255;
  818.   leds[(now.second()+LEDOffset)%60].b = secondBrightness;
  819.   leds[(now.second()+LEDOffset+59)%60].b = secondBrightness2;
  820. }
  821. //
  822. void outlineClock(DateTime now)
  823. {
  824.   for (int i = 0; i < numLEDs; i++)
  825.     {
  826.       fiveMins = i%5;
  827.       if (fiveMins == 0)
  828.         {
  829.           leds[i].r = 100;
  830.           leds[i].g = 100;
  831.           leds[i].b = 100;
  832.         }
  833.     }
  834.   unsigned char hourPos = ((now.hour()%12)*5 + (now.minute()+6)/12);
  835.   leds[(hourPos+LEDOffset+59)%60].r = 255;   
  836.   leds[(hourPos+LEDOffset)%60].r = 255;
  837.   leds[(hourPos+LEDOffset+1)%60].r = 255;
  838.   leds[(now.minute()+LEDOffset)%60].g = 255;
  839.   leds[(now.second()+LEDOffset)%60].b = 255;
  840. }
  841. //
  842. void minimalMilliSec(DateTime now)
  843. {
  844.   if (now.second()!=old.second())
  845.     {
  846.       old = now;
  847.       cyclesPerSec = (millis() - newSecTime);
  848.       newSecTime = millis();
  849.     }
  850.   // set hour, min & sec LEDs
  851.   unsigned char hourPos = ((now.hour()%12)*5 + (now.minute()+6)/12);
  852.   subSeconds = (((millis() - newSecTime)*60)/cyclesPerSec)%60;  // This divides by 733, but should be 1000 and not sure why???
  853.   // Millisec lights are set first, so hour/min/sec lights override and don't flicker as millisec passes
  854.   leds[(subSeconds+LEDOffset)%60].r = 50;
  855.   leds[(subSeconds+LEDOffset)%60].g = 50;
  856.   leds[(subSeconds+LEDOffset)%60].b = 50;
  857.   // The colours are set last, so if on same LED mixed colours are created
  858.   leds[(hourPos+LEDOffset+59)%60].r = 255;   
  859.   leds[(hourPos+LEDOffset)%60].r = 255;
  860.   leds[(hourPos+LEDOffset+1)%60].r = 255;
  861.   leds[(now.minute()+LEDOffset)%60].g = 255;
  862.   leds[(now.second()+LEDOffset)%60].b = 255;
  863. }
  864. // Pendulum will be at the bottom and left for one second and right for one second
  865. void simplePendulum(DateTime now)
  866. {
  867.   if (now.second()!=old.second())
  868.     {
  869.       old = now;
  870.       cyclesPerSec = millis() - newSecTime;
  871.       cyclesPerSecFloat = (float) cyclesPerSec;
  872.       newSecTime = millis();
  873.       if (swingBack == true) {swingBack = false;}
  874.       else {swingBack = true;}
  875.     }
  876.   // set hour, min & sec LEDs
  877.   fracOfSec = (millis() - newSecTime)/cyclesPerSecFloat;  // This divides by 733, but should be 1000 and not sure why???
  878.   if (subSeconds < cyclesPerSec && swingBack == true) {pendulumPos = 27.0 + 3.4*(1.0+sin((3.14*fracOfSec)-1.57));}
  879.   if (subSeconds < cyclesPerSec && swingBack == false) {pendulumPos = 27.0 + 3.4*(1.0+sin((3.14*fracOfSec)+1.57));}
  880.   unsigned char hourPos = ((now.hour()%12)*5 + (now.minute()+6)/12);
  881.   // Pendulum lights are set first, so hour/min/sec lights override and don't flicker as millisec passes
  882.   leds[(pendulumPos + LEDOffset)%60].r = 100;
  883.   leds[(pendulumPos + LEDOffset)%60].g = 100;
  884.   leds[(pendulumPos + LEDOffset)%60].b = 100;
  885.   // The colours are set last, so if on same LED mixed colours are created
  886.   leds[(hourPos+LEDOffset+59)%60].r = 255;   
  887.   leds[(hourPos+LEDOffset)%60].r = 255;
  888.   leds[(hourPos+LEDOffset+1)%60].r = 255;
  889.   leds[(now.minute()+LEDOffset)%60].g = 255;
  890.   leds[(now.second()+LEDOffset)%60].b = 255;
  891. }
  892. void breathingClock(DateTime now)
  893. {
  894.   if (alarmTrig == false)
  895.     {
  896.       breathBrightness = 15.0*(1.0+sin((3.14*millis()/2000.0)-1.57));
  897.       for (int i = 0; i < numLEDs; i++)
  898.         {
  899.           fiveMins = i%5;
  900.           if (fiveMins == 0)
  901.             {
  902.               leds[i].r = breathBrightness + 5;
  903.               leds[i].g = breathBrightness + 5;
  904.               leds[i].b = breathBrightness + 5;
  905.             }
  906.           else
  907.             {
  908.               leds[i].r = 0;
  909.               leds[i].g = 0;
  910.               leds[i].b = 0;
  911.             }
  912.         }
  913.     }
  914.   unsigned char hourPos = ((now.hour()%12)*5 + (now.minute()+6)/12);
  915.   leds[(hourPos+LEDOffset+59)%60].r = 255;   
  916.   leds[(hourPos+LEDOffset)%60].r = 255;
  917.   leds[(hourPos+LEDOffset+1)%60].r = 255;
  918.   leds[(now.minute()+LEDOffset)%60].g = 255;
  919.   leds[(now.second()+LEDOffset)%60].b = 255;
  920. }
  921. /*
  922. // Cycle through the color wheel, equally spaced around the belt
  923. void rainbowCycle(uint8_t wait)
  924. {
  925.   uint16_t i, j;
  926.   for (j=0; j < 384 * 5; j++)
  927.     {     // 5 cycles of all 384 colors in the wheel
  928.       for (i=0; i < numLEDs; i++)
  929.         {
  930.           // tricky math! we use each pixel as a fraction of the full 384-color
  931.           // wheel (thats the i / strip.numPixels() part)
  932.           // Then add in j which makes the colors go around per pixel
  933.           // the % 384 is to make the wheel cycle around
  934.           strip.setPixelColor(i, Wheel(((i * 384 / numLEDs) + j) % 384));
  935.         }
  936.       delay(wait);
  937.     }
  938. }
  939. //Input a value 0 to 384 to get a color value.
  940. //The colours are a transition r - g - b - back to r
  941. uint32_t Wheel(uint16_t WheelPos)
  942. {
  943.   byte r, g, b;
  944.   switch(WheelPos / 128)
  945.   {
  946.     case 0:
  947.       r = 127 - WheelPos % 128; // red down
  948.       g = WheelPos % 128;       // green up
  949.       b = 0;                    // blue off
  950.       break;
  951.     case 1:
  952.       g = 127 - WheelPos % 128; // green down
  953.       b = WheelPos % 128;       // blue up
  954.       r = 0;                    // red off
  955.       break;
  956.     case 2:
  957.       b = 127 - WheelPos % 128; // blue down
  958.       r = WheelPos % 128;       // red up
  959.       g = 0;                    // green off
  960.       break;
  961.   }
  962.   return(strip.Color(r,g,b));
  963. }
  964. */
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 09:00

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟

附录
【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟
项目链接:https://www.hackster.io/mircemk/ ... o-ring-clock-f58ba6
项目作者:北马其顿 米尔塞姆克(Mirko Pavleski)

项目视频 :https://www.youtube.com/watch?v=hyZMtKf4GrI&t=2s
项目代码:https://www.hackster.io/code_files/551627/download
3D 打印:https://hacksterio.s3.amazonaws. ... ring_2ZlrY2euoH.stl

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图1

【Arduino 动手做】DIY WS2812 模拟风格 Arduino 环形时钟图2

回复

使用道具 举报

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

本版积分规则

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

硬件清单

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

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

mail