Большие часы на адресных светодиодах WS2812B

Большие часы на адресных светодиодах WS2812B
Всем привет, хочу рассказать о том как я попробовал повторить проект, но столкнулся с некоторыми проблемами.

Как-то раз на просторах зарубежного интернета я нашел вот такой проект часов на базе светодиодной ленты WS2812B: Big, Auto Dim, Room Clock, и мне захотелось его повторить. Часы устроены как семи сегментный циферблат и работают на RTC модуле DS3231 . Часы умеют показывать температуру, имеют кнопки для настройки и перевода на зимнее время и обратно, позже я добавил датчик влажности DHT11. Температура уже вместе с влажностью считывалась с этого датчика и выводилась раз в минуту. Хоть и в модуле часов есть температурный датчик, но похоже он показывал температуру не корректно из-за самонагрева (ИМХО).




Untitled Sketch_МП.png
И главное нанести много горячих соплей

IMG_20180907_120755.jpg


Когда все было собрано, повозившись с библиотеками, все заработало. И тут возникло одно большое НО: положения яркости в только в двух позициях меня не устраивало. Тем более на границе значений происходило мерцание. Установка яркости на статичном значении меня тоже не очень устраивала ибо днем при установленном тусклом свете ничего не было видно, а ночью даже со значениями близким к минимуму можно было осветить всю Москву. Поинтересовавшись как в других проектах с этим справляется Alex было решено заменить такой код настройки яркости.

C:
void BrightnessCheck(){
  const byte sensorPin = BRI_PIN; // light sensor pin
  const byte brightnessLow = 1; // Low brightness value
  const byte brightnessHigh = 50; // High brightness value
  int sensorValue = analogRead(sensorPin); // Read sensor
  Serial.print("Sensor is: ");Serial.println(sensorValue);
  sensorValue = map(sensorValue, 0, 255, 1, 100);
  LEDS.setBrightness(sensorValue);
  };
вот такими строчками:
C:
void BrightnessCheck() {

  if (auto_bright) {                         // если включена адаптивная яркость
    if (millis() - bright_timer > 100) {     // каждые 100 мс
      bright_timer = millis();               // сброить таймер
      new_bright = map(analogRead(BRI_PIN), 0, bright_constant, min_bright, max_bright);   // считать показания с фоторезистора, перевести диапазон
      new_bright = constrain(new_bright, min_bright, max_bright);
      new_bright_f = new_bright_f * coef + new_bright * (1 - coef);
      LEDS.setBrightness(new_bright_f);      // установить новую яркость
    }
  }
};

Тут стоит упомянуть что программистом я не являюсь и большинство проблем я пытаюсь решить методом тыка и перебора.

И тут все заработало, моей радости не было придела, пока не наступила ночь. Появилась проблема с отключением ленты при полной темноте. Иногда это было только на минуту, а иногда на целую ночь. Еще есть проблема со слабим мерцанием светодиодов если освещения в комнате было мало (например когда работал телик), но это было редко и длилось это одну минуту.

Что касается кода вот сылка на GitHub. Кое-что я перевел для лучшего понимания.

Давно хотел поделиться готовым и работоспособным проектом в кругах аудитории Алекса, но вышло так что собственно нормальной работоспособностью тут не пахнет. Буду благодарени, если у кто сможет помочь.
 
Изменено:

Комментарии

maksland

★★★✩✩✩✩
13 Янв 2019
513
117
Omsk
У нас отрицательная теперь только в морозильнике :). Теперь датчик давления прикрутить бы и можно Вячеславу ставить памятник !
P.S. только можно и .hex тоже а то у меня криво собирается.
 

maksland

★★★✩✩✩✩
13 Янв 2019
513
117
Omsk
Собрал прошивку, прошил, работает !. Единственное что задержку побольше бы поставить когда в меню работаешь а то кнопку не нажимаешь секунды две и он вываливается сразу в рабочий режим. Хотя бы секунд 15 сделать таймер режима бездействия. Понятно что не каждый день настраивать надо но за месяц уже всё забудешь
if ((millis() - key_pressed) > (TIME_EXIT * 1000)) mode = 0; не тут правится ?
 

kym13

★★✩✩✩✩✩
14 Ноя 2020
472
70
Вячеслав_45) Прошивка из 676 поста на 30 LED? цифру вначале поменять на нужное количество и всё? или в коде ещё что-то менять надо?
 

Вячеслав_45

★★✩✩✩✩✩
10 Июл 2020
72
64
Избыточное цитирование
Собрал прошивку, прошил, работает !. Единственное что задержку побольше бы поставить когда в меню работаешь а то кнопку не нажимаешь секунды две и он вываливается сразу в рабочий режим. Хотя бы секунд 15 сделать таймер режима бездействия. Понятно что не каждый день настраивать надо но за месяц уже всё забудешь
if ((millis() - key_pressed) > (TIME_EXIT * 1000)) mode = 0; не тут правится ?

Вот тут правится

#define TIME_EXIT 4 // Время выхода из меню после последнего нажатия кнопок (секунд)
 
  • Лойс +1
Реакции: maksland

Вячеслав_45

★★✩✩✩✩✩
10 Июл 2020
72
64
Блок настроек:
// Настройки пинов подключения к Ардуино +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define DATA_PIN 6                 // pin вывод данных на светодиоды
#define LIGHT_PIN A0               // pin датчика освещенности
#define TEMP_INSIDE_PIN 10         // pin комнвтного датчика температуры DS18B20 только плюсовая до десятых
#define TEMP_OUTSIDE_PIN 9         // pin уличного датчика температуры DS18B20 плюсовая и минусовая до целых
#define PIN_UP 3                   // pin кнопки прибавить
#define PIN_ST 4                   // pin кнопки выбор
#define PIN_DW 5                   // pin кнопки убавить
// Настройки +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define COLOR_ORDER GRB            // Порядок цветов (если при включении часы не красные менять буквы местами)
#define NUM_LEDS 30                // Количество светодиодов (30, 58, 86, 114, 142...)
#define NUM_COLOR 20               // Количество цветов (должно совпадать с количеством в массиве цветов color_table)
#define LIGHT_MIN 4                // Минимальный уровень яркости (0...255) должно быть меньше максимального
#define LIGHT_MAX 250              // Максимальный уровень яркости (0...255) должно быть больше минимального
#define TIME_EXIT 4                // Время выхода из меню после последнего нажатия кнопок (секунд)
#define TIME_SAVE 15               // Время сохранения настроек в память после последнего нажатия кнопок (секунд)
#define VERSION 18                 // Версия для отображения на часах (две цифры без точки)
#define START_MODE 55              // Отображение версии прошивки при включении (0 - нет, 55 - да)
// Настройки отображения температуры ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define TEMP_INSIDE 10             // Знак градусов комнатной температуры  (10 - "0" 11 - "С")
#define TEMP_OUTSIDE 10            // Знак градусов уличной температуры  (10 - "0" 11 - "С")
#define TEMP_INSIDE_COLOR 1        // Вариант цвета комнатной (0 - как часы, 1 - кр-ор-ж-зел-гол-с, 2 - кр-роз-фиол-с)
#define TEMP_OUTSIDE_COLOR 1       // Вариант цвета уличной (0 - как часы, 1 - кр-ор-ж-зел-гол-с, 2 - кр-роз-фиол-с)
#define TEMP_INSIDE_MIN 15         // Минимальная комнатная температура (отображается синим)
#define TEMP_INSIDE_MAX 35         // Максимальная комнатная температура (отображается красным)
#define TEMP_OUTSIDE_MIN -40       // Минимальная уличная температура (отображается синим)
#define TEMP_OUTSIDE_MAX 40        // Максимальная уличная температура (отображается красным)
// Defauil настройки в часах устанавливаются режимом "----" +++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define TIME_TEMP 4                // Установка времени отображения температуры 0...5 секунд (0 - отк.)
#define TIME_DATE 0                // Установка времени отображения даты 0...5 секунд (0 - отк.)
#define SET_COLOR 0                // Настройка цвета (если 0 то автоматическая) 0...20
#define SET_LIGHT 0                // Настройка яркости (если 0 то автоматическая) 0...25
#define SET_TEMPS 0                // Включение отображения температуры (0 - комнатный, 1 - уличный, 2 - оба)
#define SET_SHOWS 1                // Включение отображения анимации при смене минут (0 - отк. 1 - вкл.)
#define TIME_TIME 3                // Установка количества отображения температуры и даты в минуту 1...6 раз
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Поясню блок настроек для прошивки 1.8
цифру после командного слова #define (например #define DATA_PIN 6) можно менять под свои нужды
// Настройки пинов подключения к Ардуино ++++ здесь думаю понятно настраивается пины подключения

#define COLOR_ORDER GRB тут нужно менять местами буквы GRB (например RGB или BRG) в зависимости от ваших светодиодов если при включении часов версия прошивки ( - 1.8 - ) отображается не красным цветом
#define NUM_LEDS 30 // Количество светодиодов (30, 58, 86, 114, 142...) в скобках указывается возможные варианты параметра
#define LIGHT_MIN 4 и #define LIGHT_MAX 250 это мин (4) и макс (250) соответственно значения яркости при автоматическом регулировании
если в пояснении параметра стоит (секунд) можно ставить сколько угодно
#define TEMP_INSIDE 10 и #define TEMP_OUTSIDE 10 если стоит 10 то при отображении температуры будет рисовать кружок в конце, если 11 то С
#define TEMP_INSIDE_COLOR 1 и #define TEMP_OUTSIDE_COLOR 1 тут три варианта 0 или 1 или 2, при 0 показания температуры отображаются текущим цветом часов, при 1 плавное изменение цвета от красного к синему (как в радуге красный-оранжевый-желтый-зеленый-голубой-синий) с плавным переходом от одного цвета к другому, при 2 тоже самое что и при 1 но цвета другие (красный-розовый-фиолетовый-синий)
#define TEMP_INSIDE_MIN 15 и #define TEMP_INSIDE_MAX 35 это диапазон изменения цвета, то есть 15 градусов и ниже синим цветом, 35 и ваше красным между 15 и 35 отображается выбранный вариант радуги из предыдущих настроек (#define TEMP_INSIDE_COLOR 1), чем меньше диапазон (например между 15 и 35) тем чаще будет меняться цвет температуры
#define TEMP_OUTSIDE_MIN -40 и #define TEMP_OUTSIDE_MAX 40 аналогично для выбранного варианта #define TEMP_OUTSIDE_COLOR 1

// Defauil настройки в часах устанавливаются режимом "----" +++
это те настройки в самих часа которые установятся при выборе пункта меню в часах " - - - - " возможные варианты также указаны в комментарии

Удачной настройки...
 

kym13

★★✩✩✩✩✩
14 Ноя 2020
472
70
Вячеслав_45)
#define NUM_LEDS 30 // Количество светодиодов (30, 58, 86, 114, 142...) ставлю 86 абракатабра на табло. Больше ничего нигде менять не нужно? У меня табло 3 LED на сегмент
 

Вячеслав_45

★★✩✩✩✩✩
10 Июл 2020
72
64
Вячеслав_45)
#define NUM_LEDS 30 // Количество светодиодов (30, 58, 86, 114, 142...) ставлю 86 абракатабра на табло. Больше ничего нигде менять не нужно? У меня табло 3 LED на сегмент
А светодиод лентой или отдельные пиксели. Если лентой надо смотреть сколько контроллеров на отрезке 3 led если один то ставить 30, если на каждый свой контроллер то должно работать, или смотреть последовательность подключения
 

kym13

★★✩✩✩✩✩
14 Ноя 2020
472
70
Подключение как в скетче {G B A F E D C} {G B A F E D C} {верхняя точка} {нижняя точка} {G B A F E D C} {G B A F E D C}. Подумал сначала что диод какой то сдох, проверил табло на другом скетче всё работает. Лента у меня ws2812b

Вячеслав_45)
byte digits[21][7] = {{0,1,1,1,1,1,1}, // Digit 0
{0,1,0,0,0,0,1}, // Digit 1
{1,1,1,0,1,1,0}, // Digit 2
В этом массиве разве ничего менять не нужно?

Когда ставишь значение 86 горят только несколько диодов в каждом сегменте и моргают точки.
Подключение должно быть такое? Слева на право
 

Вложения

maksland

★★★✩✩✩✩
13 Янв 2019
513
117
Omsk
давление будет ?
Вопрос - с какой частотой опрашиваются DS18B20 ?
 
Изменено:

Вячеслав_45

★★✩✩✩✩✩
10 Июл 2020
72
64
Перебрал всю прошивку
все мне известные баги и косяки устранил.
маленько ужал прошивку
цвета меняет в зависимости от температуры уличной и внутренней
сделал адекватную работу с DS3231 и памятью

изменил порядок настроек в часах и прошивке

З.Ы. уличный датчик подключил по 4-х жильному телефонному проводу 15 метров - работает стабильно.
 

Вложения

Александр Злюс

✩✩✩✩✩✩✩
10 Фев 2020
19
1
Избыточное цитирование
Перебрал всю прошивку
все мне известные баги и косяки устранил.
маленько ужал прошивку
цвета меняет в зависимости от температуры уличной и внутренней
сделал адекватную работу с DS3231 и памятью

изменил порядок настроек в часах и прошивке

З.Ы. уличный датчик подключил по 4-х жильному телефонному проводу 15 метров - работает стабильно.
огромное спасибо за размер прошивки !!!! компиляция без ошибок .
 

maksland

★★★✩✩✩✩
13 Янв 2019
513
117
Omsk
я мониторю только прошивки Вячеслава
и ладно - пусть будет не prefinal а lite версия !
и еще ... цены на bme280 какие то запредельные стали ! в феврале брал за 296 а сейчас 600-700 + доставка ? дефицит чипов ?
в 2018 отдал всего 173 рубля :)
 
Изменено:

Александр Злюс

✩✩✩✩✩✩✩
10 Фев 2020
19
1
я мониторю только прошивки Вячеслава
и еще ... цены на bme280 какие то запредельные стали ! в феврале брал за 296 а сейчас 600-700 + доставка ? дефицит чипов ?
в 2018 отдал всего 173 рубля :)
я за 40 р брал наверное повезло но у меня на 168 не влазит прошивка с таким датчиком bme280 . мониторьте у asm тоже
 

bort707

★★★★★★✩
21 Сен 2020
3,046
909
@Вячеслав_45, критика по коду нужна?

@Вячеслав_45, я особо нападать не собираюсь.
Хотел только отметить вот какой момент - имхо, очень много лишних действий в loop().
- при каждом проходе цикла (то есть сотни раз в секунду) - читаете время с RTC - зачем? для показа времени это не нужно, а для RTC может быть вредно, на некотрых мождулях начинают отставать часы при слишком частом обращении. Если у вас часы только с минутами - уж точно нет смысла читать время чаще чем раз 30 секунд, а вообще лучше делать это раз в 2-4 часа, а секунды и минуты отсчитывать через миллис.

- то же самое про проверку переменных в ЕЕПРОМ(процедура EepromTick()) - зачем это делать при каждом обороте ЛУП? Сбрасывайте данные только когда они поменялись
-тоже самое про вывод на ленту. Зачем делать show() каждые несколько миллисекунд, если у вас данные на часах не изменились?

Теперь по режимам. Если правильно понял код, например вот тут
C++:
case 20: {            // Режим вывода температуры внутри
      TempColor(TEMP_INSIDE_COLOR, temp1, TEMP_INSIDE_MIN, TEMP_INSIDE_MAX);
      if (temp1 < 100) DigitOut(18, (temp1 % 100) / 10, temp1 % 10, TEMP_INSIDE, 1, temp_color);
      else DigitOut(temp1 / 100, (temp1 % 100) / 10, temp1 % 10, TEMP_INSIDE, 1, temp_color);
        if (millis() - t > time_tp) {
          if (setups[5] == 2) {
            mode = 21;
            t = millis();}
          else if (setups[2] != 0) mode = 25;
          else mode = 0;}
      break;}
первые три строчки этого блока при каждом проходе loop обновляются снова и снова и снова...

Еще - верно ли я вижу, что если датчика внешней температуры нет - то и дата не показывается? - режимы связаны.

Остальное мелочи...
 
Изменено: