1. #include <Wire.h>     // Нужна для опроса часовой микросхемы DS1307
  2. #include "FastLED.h"  // Библиотека управления адресной лентой
  3. #include "buildTime.h" // Библиотека для первоначальной установки часов
  4. #include <GyverButton.h> // Библиотека для удобной работы с кнопками
  5. #include <avr/eeprom.h>
  6.  
  7. byte nColor;       // Индекс таблицы цветов
  8.  
  9. #define DS1307_I2C_ADDRESS 0x68
  10.  
  11. #define NUM_LEDS 29       // Количество светодиодов (для WS2811 по 3 штуки на контроллер)
  12. #define COLOR_ORDER BRG   // Порядок цветов
  13. #define DATA_PIN 10       // Куда подключаем ленту
  14. #define PIN_PHOTO_SENSOR A0 // пин датчика освещенности
  15.  
  16. #define BTN_MIN   7   // пин кнопки изменения минут
  17. #define BTN_HOUR  8   // пин кнопки изменения часов
  18. #define BTN_COLOR 9   // пин кнопки смены цвета
  19.  
  20. GButton btnMin(BTN_MIN);
  21. GButton btnHour(BTN_HOUR);
  22. GButton btnColor(BTN_COLOR);
  23.  
  24. unsigned long previousMillis = 0;     //
  25. const long interval = 1000;           // Вывод на экран каждую секунду (1000 мс)
  26. boolean corTime = false;
  27.  
  28. byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // Глобальные переменные для хранения времени
  29.  
  30. CRGB leds[NUM_LEDS];                    // Define LEDs strip
  31. byte digits[10][7] = {{0,1,1,1,1,1,1},  // Digit 0
  32.                      {0,1,0,0,0,0,1},   // Digit 1
  33.                      {1,1,1,0,1,1,0},   // Digit 2
  34.                      {1,1,1,0,0,1,1},   // Digit 3
  35.                      {1,1,0,1,0,0,1},   // Digit 4
  36.                      {1,0,1,1,0,1,1},   // Digit 5
  37.                      {1,0,1,1,1,1,1},   // Digit 6
  38.                      {0,1,1,0,0,0,1},   // Digit 7
  39.                      {1,1,1,1,1,1,1},   // Digit 8
  40.                      {1,1,1,1,0,1,1}};  // Digit 9 | 2D Array for numbers on 7 segment
  41.  
  42. bool Dot = true;          // Состояние точки
  43.  
  44. long ledColor;            // Используется в ф-ции Time2Array для задания цвета точек
  45. long ColorTable[28] = {   // Таблица цветов
  46. CRGB::Amethyst,
  47. CRGB::Aqua,
  48. CRGB::Blue,
  49. CRGB::Chartreuse,
  50. CRGB::DarkGreen,
  51. CRGB::DarkMagenta,
  52. CRGB::DarkOrange,
  53. CRGB::DeepPink,
  54. CRGB::Fuchsia,
  55. CRGB::Gold,
  56. CRGB::GreenYellow,
  57. CRGB::LightCoral,
  58. CRGB::Tomato,
  59. CRGB::Salmon,
  60. CRGB::Red,
  61. CRGB::Orchid,
  62. CRGB::Violet,
  63. CRGB::Cyan,
  64. CRGB::HotPink,
  65. CRGB::Teal,
  66. CRGB::Purple,
  67. CRGB::Maroon,
  68. CRGB::DarkBlue,
  69. CRGB::Navy,
  70. CRGB::Turquoise,
  71. CRGB::Lime,
  72. CRGB::Pink,
  73. CRGB::White
  74. };
  75.  
  76. void setup() {
  77.   Wire.begin();
  78.   Serial.begin(9600); // DEBUG ONLY
  79.  
  80.   LEDS.addLeds<WS2811, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS); // Set LED strip type
  81.   LEDS.setBrightness(50); // Set initial brightness 1 - 255
  82.   // Первоначальная установка времени RTC (раскоментировать для однократного запуска!) :
  83.   // DS1307 seconds, minutes, hours, day, date, month, year
  84.   // setDS1307time(BUILD_SEC, BUILD_MIN, BUILD_HOUR, 2, BUILD_DAY, BUILD_MONTH, BUILD_YEAR); // из "buildTime.h"
  85.   // setDS1307time(30,07,13,2,20,12,21); // или вручную :)
  86.  
  87.   nColor = eeprom_read_byte(0);   // Читаем из памяти 0-вой позиции
  88.   ledColor = ColorTable[nColor];  // ledColor записывается в ячейку
  89.    
  90.   Serial.print("EEPROM(0)= ");Serial.print(nColor);Serial.print(" Color = ");Serial.println(ledColor, HEX);
  91.   // Записать изменения часов и минут в RTC
  92.   // Сначала читаем текущие значения тех параметров, что кнопками не изменяются
  93.   // readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); 
  94.   // Пишем только изменяющиеся параметры часов и минут
  95.   // setDS1307time(second,24,12,dayOfWeek,dayOfMonth,month,year); 
  96.  
  97.   delay(500); // Ждем пока все устаканится
  98. }
  99.  
  100. //*************************************************************************************************
  101. // MAIN
  102. //*************************************************************************************************
  103. void loop() {
  104.   unsigned long currentMillis = millis();
  105.   byte tmp = 33;
  106.   // int tmpTime;
  107.  
  108.   // Опрос часов и вывод на экран происходит один раз в секунду (константа interval)
  109.   if (currentMillis - previousMillis >= interval) {
  110.     previousMillis = currentMillis;
  111.  
  112.     // Установка яркости ленты в зависимости от напряжения на фоторезисторе
  113.     int val = analogRead(PIN_PHOTO_SENSOR);
  114.     if (val <= 40) { LEDS.setBrightness(2); Serial.print(val);}                // Ночной режим
  115.     else if (val>40 and val<=150) { LEDS.setBrightness(35);Serial.println(val);}  // Затененная комната
  116.     else if (val>150 and val<=300) { LEDS.setBrightness(80);Serial.println(val);} // Днем в тени
  117.     else { LEDS.setBrightness(155);Serial.println(val);}                        // Солнечно, максимальный режим
  118.      
  119.     // Смена режима часовых точек
  120.     if (Dot) Dot = false;
  121.         else Dot = true;
  122.     // Или так
  123.     // Dot = !Dot;
  124.      
  125.     readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  126.  
  127.     // Коррекция времени
  128.     /*if((dayOfMonth != tmp) and (hour==3 and minute == 2)) { //Только один раз в сутки!
  129.       tmp = dayOfMonth;
  130.       tmpTime = second*60 + minute - 40; // 40 - настолько убегают часики в сутки :(
  131.       Serial.print("CutTime = ");Serial.print(minute);Serial.print("%");Serial.println(second);
  132.       Serial.print("tmpTime = ");Serial.print(tmpTime);Serial.print("tmpTime/60 = ");Serial.print(tmpTime/60);Serial.print("tmpTime%60 = ");Serial.println(tmpTime%60);
  133.       setDS1307time(tmpTime/60, tmpTime%60, hour, dayOfWeek, dayOfMonth, month, year);
  134.     }*/
  135.  
  136.     //Новая версия коррекции
  137.     if( hour==23 and minute == 48 ) corTime = true; // флаг коррекции
  138.     if( hour==23 and minute == 49 and second == 50 and corTime ) { corTime = false;
  139.       setDS1307time(10, minute, hour, dayOfWeek, dayOfMonth, month, year); // 50-40 = 10 40 секунд назад коррекция
  140.     }
  141.      
  142.     TimeToArray(); FastLED.show();
  143.  
  144.   } // Конец ежесекундной секции
  145.  
  146.   // Здесь опрос кнопок и реакция на нажатия
  147.   btnMin.tick();
  148.   btnHour.tick();
  149.   btnColor.tick();
  150.  
  151.   if (btnMin.isClick()) { minute++; if (minute >= 60) minute = 0;
  152.   //  readDS1307time(&second, &tmp, &hour, &dayOfWeek, &dayOfMonth, &month, &year);   // Читаем снова, чтобы не потерять секунды
  153.     setDS1307time(second, minute, hour, dayOfWeek, dayOfMonth, month, year);        // Пишем, значимо только первые три параметра
  154.     TimeToArray(); FastLED.show(); } // Добавляем минуту и обновляем дисплей
  155.    
  156.   if (btnHour.isClick()) { hour++; if (hour >= 24) hour = 0;
  157.   //  readDS1307time(&second, &minute, &tmp, &dayOfWeek, &dayOfMonth, &month, &year); // Читаем снова, чтобы не потерять секунды
  158.     setDS1307time(second, minute, hour, dayOfWeek, dayOfMonth, month, year);        // Пишем, значимо только первые три параметра
  159.      
  160.     TimeToArray(); FastLED.show(); }  // Добавляем час и обновляем дисплей
  161.   if (btnColor.isClick()) {
  162.     if (nColor < 27) { nColor++; } else { nColor = 0; } // В таблице 28 цветов, дошли до конца, начинаем с начала
  163.  
  164.     eeprom_write_byte(0, nColor);    // Записываем новое значение индекса цвета
  165.     ledColor = ColorTable[nColor];    // ledColor записывается в ячейку
  166.     TimeToArray(); FastLED.show(); }  // Берем следующий цвет их списка и обновляем дисплей
  167. }
  168. //**************************************************************************************************
  169.  
  170. // Функция перевода числа в точки на дисплее
  171. void TimeToArray(){
  172.   int Now = (hour*100+minute);  // Записываем время в виде числа типа 1843 (18:43)
  173.   int cursor = 29;
  174.   //Serial.print(" TIME = ");Serial.print(Now); Serial.print(" LedColor = ");Serial.println(ledColor, HEX);
  175.   //ledColor = 0x0000FF;
  176.   if (Dot){leds[14]=ledColor;}
  177.     else {leds[14]=0x000000; }
  178.      
  179.   for(int i=1;i<=4;i++){
  180.     int digit = Now % 10; // get last digit in time
  181.     if (i==1){
  182.       cursor =22;
  183.       for(int k=0; k<=6;k++){
  184.         if (digits[digit][k]== 1){leds[cursor]=ledColor;}
  185.          else if (digits[digit][k]==0){leds[cursor]=0x000000;};
  186.          cursor ++;
  187.         };
  188.       }
  189.     else if (i==2){
  190.       cursor -=14;
  191.       for(int k=0; k<=6;k++){
  192.         if (digits[digit][k]== 1){leds[cursor]=ledColor;}
  193.          else if (digits[digit][k]==0){leds[cursor]=0x000000;};
  194.          cursor ++;
  195.         };
  196.       }
  197.     else if (i==3){
  198.       cursor =7;
  199.       for(int k=0; k<=6;k++){
  200.         if (digits[digit][k]== 1){leds[cursor]=ledColor;}
  201.          else if (digits[digit][k]==0){leds[cursor]=0x000000;};
  202.          cursor ++;
  203.         };
  204.       }
  205.     else if (i==4){
  206.       cursor =0;
  207.       for(int k=0; k<=6;k++){
  208.         if (digits[digit][k]== 1){leds[cursor]=ledColor;}
  209.          else if (digits[digit][k]==0){leds[cursor]=0x000000;};
  210.          cursor ++;
  211.         };
  212.       }
  213.     Now /= 10;
  214.   }
  215. }
  216.  
  217. // Функции чтения и записи в микросхему RTC DS1307
  218. void setDS1307time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
  219.   // sets time and date data to DS1307
  220.   Wire.beginTransmission(DS1307_I2C_ADDRESS);
  221.   Wire.write(0); // set next input to start at the seconds register
  222.   Wire.write(decToBcd(second)); // set seconds
  223.   Wire.write(decToBcd(minute)); // set minutes
  224.   Wire.write(decToBcd(hour)); // set hours
  225.   Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  226.   Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  227.   Wire.write(decToBcd(month)); // set month
  228.   Wire.write(decToBcd(year)); // set year (0 to 99)
  229.   Wire.endTransmission();
  230. }
  231.  
  232. void readDS1307time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) {
  233.   Wire.beginTransmission(DS1307_I2C_ADDRESS);
  234.   Wire.write(0); // set DS1307 register pointer to 00h
  235.   Wire.endTransmission();
  236.   Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  237.   // request seven bytes of data from DS1307 starting from register 00h
  238.   *second = bcdToDec(Wire.read() & 0x7f);
  239.   *minute = bcdToDec(Wire.read());
  240.   *hour = bcdToDec(Wire.read() & 0x3f);
  241.   *dayOfWeek = bcdToDec(Wire.read());
  242.   *dayOfMonth = bcdToDec(Wire.read());
  243.   *month = bcdToDec(Wire.read());
  244.   *year = bcdToDec(Wire.read());
  245. }
  246.  
  247. // Сервисные функции по преобразованию вида чисел для DS1307
  248. byte decToBcd(byte val) { return( (val/10*16) + (val%10) ); } // Convert normal decimal numbers to binary coded decimal
  249. byte bcdToDec(byte val) { return( (val/16*10) + (val%16) ); } // Convert binary coded decimal to normal decimal numbers
Подсветка програмного кода