ESP, IoT [BigClock] Большие часы на WS2812, ESP8266, Народный мониторинг

Какой вариант датчика используется у вас? Интересно, использует ли кто BME280, как у меня?)

  • BMP280

    Голосов: 23 29.1%
  • BME280

    Голосов: 56 70.9%

  • Всего проголосовало
    79
[BigClock] Большие часы на WS2812, ESP8266, Народный мониторинг
Создаю отдельную тему по разработке прошивки на базе NodeMCU.

Мой проект сделан на ДВП, на нее наклеил ленту, объем цифрам сделал из сэндвич панели, поверх белый лист бумаги.
Корпус из дерева, покрашен акриловой краской, смесь белой и коричневой.

Данная прошивка проверяет время по NTP, часы RTC теоретически не нужны.
Барометр на базе BME280.
Имеется датчик освещенности и датчик DS18B20
Clock_схема.pngсхема пайки.jpgClock_схема3.jpg
Плата: NodeMCU 1.0 (ESP 12-E Module)
Если в качестве микроконтроллера вы используете Wemos D1 - в менеджере плат для компиляции все равно выбирайте "NodeMCU v1.0 (ESP-12E)", в противном случае, если выберете плату Wemos D1 (xxxx), - будет работать нестабильно.
Выбирайте ядро ESP версии 2.7.4.

ESP8266 (SDK v2.7+)

Необходимые библиотеки находим в репозитории программы IDE.
Настраиваем прошивку под себя, если нужно, меняем пароли для точки и OTA, WiFi можно не задавать.

Если не задавали настройки WiFi, то стартует точка, адрес стандартный 192.168.4.1 пароль по умолчанию administrator, задавать не менее 8 символов, иначе название точки не отобразится, а будет ее внутреннее имя, типа ESP12345.
Адрес портала http://clock.local/ или по IP адресу, выданному роутером.
Данные для OTA: имя: admin пароль: pass

Для подключения к сервису "Народный мониторинг" MAC адрес отображается на соответствующей странице, вводите этот адрес при регистрации устройства.

Новая версия на гитхаб, последние изменения и публикация свежих версий будет там)

Версия от 16.04.2023 CLOCK_ESP_2.0:
  • оптимизация под новый портал
  • переделано давление с инт на флоат для мониторинга
  • переделан интерфейс на UI
  • добавлена ручная синхронизация времени
  • заменена библиотека rtc на microDS3231
  • багфиксы)
  • добавлена в код точка, для десятичного знака уличной температуры
  • добавлена строка с версией прошивки
  • исправление даты
  • добавление DFPlayer, спасибо: @Maxx1200 и @Romshteks
  • добавлен режим с датой (номер 5)
  • обновлена библиотека EEManager (сбросятся настройки!!!)
  • добавлен режим с показом первого нуля в часах
  • добавлена возможность устанавливать цветовое оформление в настройках прошивки, визуальные правки
  • fix GMT
  • заменены библиотеки датчиков
  • визуальные правки
  • может что-то еще))
Проект на гитхаб со всеми библиотеками и mp3
  • Дофига изменений))
  • Появилась web страничка с настройками на базе GyverPortal.
  • Изменены библиотеки.
  • Переписан код, распределил по вкладкам.
исправлено:
  • баг со сменой цвета на последней цифре
добавлен
  • символ давления, включать в настройках
исправлено:
  • переделан вывод сегментов
  • переделана функция показа точек
добавлено:
  • выбор режима мигания секунд 1 и 2 раза в сек
  • можно вручную задать порядок отображения датчиков и время показа каждого датчика
  • откл. WiFi без мониторинга
  • корректировка показания датчиков
внедрение датчика BME280, добавлен режим влажности с возможностью включить символ проценты
[*]багфиксы
багфиксы
незначительные изменения кода (настройки под себя и комментарии)
  • все настройки вынесены в Constants, вроде:)
  • добавлен web сервер, для обновления через браузер, изначально прошить через кабель, потом можете вносить изменения под себя и обновляться через бинарный файл
  • добавлены библиотеки
  • изменение в коде, из-за выноса настроек:)
  • добавлен НГ режим :)
  • возможно исправлена анимация, про которую писали, с точками и цифрами :)
  • теперь при запуске часов идет проверка с датчика времени, и если все ОК, то запускаются часы без синхронизации
  • исправлена функция освещенности заменой switch на if/else
  • подправлен код с switch в других местах
Увидел в коде небольшую ошибку с НГ режимом, не важно, включен он или нет, все равно будет) только разными методами)
leds[cursor] = (digit & mask) ? CHSV(random(0, 255), random(0, 255), random(0, 255)) : CRGB (0, 0, 0);
leds[cursor] = (digit & mask) ? ledColor : CRGB (0, 0, 0);
  • исправлен НГ режим
  • отключена точка доступа за ненадобностью
  • оптимизирован код
  • выбор в настройках кол-во разделительных точек
  • можно запускать с RTC модулем и без него
  • изменена библиотека NTP
  • поправлен код :)
Внимание: у кого мигает первый светодиод, необходимо изменить ядро ESP на 2.7.4 (инструменты/Плата/Менеджер плат).
Новые версии нестабильные на октябрь 2021г.
 

Вложения

Изменено:

Комментарии

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
накатал такой код, компилятор одобрил)) опять елочка получается)
C++:
uint32_t t = millis();
byte mode = 0; //0 - часы, 1 + темп-ра дома, 2 + ул. темп-ра, 3 + давл-е
byte t_time = 6000;
byte t_sensor = 2000;
byte t_sensors = 2000;
byte t_press = 2000;

void new_loop() {
  switch (mode) {
    case 0:
      {
        if (millis() - t_time > t) {
          TimeToArray();
        }
      }
      break;
    case 1: {
        if (millis() - t_time > t) {
          TimeToArray();
        }
        if (millis() - t_sensor > t) {
          TempToArray();
        }
      }
      break;
    case 2: {
        if (millis() - t_time > t) {
          TimeToArray();
        }
        if (millis() - t_sensor > t) {
          TempToArray();
        }
        if (millis() - t_sensors > t) {
          TempStreetToArray();
        }
      }
      break;
    case 3: {
        if (millis() - t_time > t) {
          TimeToArray();
        }
        if (millis() - t_sensor > t) {
          TempToArray();
        }
        if (millis() - t_sensors > t) {
          TempStreetToArray();
        }
        if (millis() - t_press > t) {
          PressToArray();
        }
      }
      break;
  }
  FastLED.show();
}
хотелось бы так это выразить)
тогда внедрять под каждый датчик свой свитч и два режима, 0 и 1
тогда обработчик лучше каждого датчика в свою функцию и в луп выводить их, намного и проще же? и другим удобнее править)
пока писал это сообщение, несколько идей пришло)
@Старик Похабыч, одобряешь?)
Код:
часы = 1//вкл
время_часы = 5//сек
датчик1 = 1//вкл
время_датчик1 = 2//сек
датчик2 = 1//вкл
время_датчик2 = 2//сек
датчик3 = 0//выкл
время_датчик3 = 2//сек
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
Категорически НЕТ!
К тебя каждый режим (mode ) должен вызывать свою функцию , не это:
if (millis() - t_time > t) {
TimeToArray();
}
if (millis() - t_sensor > t) {
TempToArray();
}
if (millis() - t_sensors > t) {
TempStreetToArray();
}
if (millis() - t_press > t) {
PressToArray();


а просто это:
if (millis() - t_press > t) {
PressToArray();
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
вроде норм, но надо для свитча задать новое название и перебирать в цикле, пускай само проверяется, подходит ли по выбранному режиму или нет)
C++:
  switch (mode) {
    case 0: {
        if (mode == 0 || mode == 1 || mode == 2 || mode == 3) {
          if (millis() - t_time > t) {
            TimeToArray();
          }
        }
      }
      break;
    case 1: {
        if (mode == 1 || mode == 2 || mode == 3) {
          if (millis() - t_sensor > t) {
            TempToArray();
          }
        }
      }
      break;
    case 2: {
        if (mode == 2 || mode == 3) {
          if (millis() - t_sensors > t) {
            TempStreetToArray();
          }
        }
      }
      break;
    case 3: {
        if (mode == 3) {
          if (millis() - t_press > t) {
            PressToArray();
          }
        }
      }
      break;
  }
  FastLED.show();
}
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Хрень какая то...
с чего это вдруг?) это ваши подсказки изложил в коде, все что выше было описано...
Я видимо перестал улавливать твои цели
я же подробно пару постов выше написал)) сделать независимыми датчики.
чтобы не мучался народ, если нет этого датчика просто выключил, и он не участвовал в коде, а также мог задать время показа каждого датчика))
чтобы не стучали в ЛС как да как... ))
Работает -не трогай
рабочий вариант не трогаю, часы работают исправно, немного переделок надо внести, не влияющих на работу) но это ж почти под себя написано))
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
Смотри как я думал
1-ый редим. Вывод часов минут в течении N1 секунд
2-ой режим вывод ds18b20 в течени секунд N2
3-ий режим вывод ds18b20 в течени секунд N3
4-ый режим вывод BME в течени секунд N4

Это к прримеру!
А теперь смотри ,
Берем массив режимы[]={{1,4},{5,2}}
У него 1-ая строка отображаемые режимы , вторая - время в секундах отображения Что бы добавить датчик ds18b20 в достатчоно переписать так:
режимы[]={{1,4,2},{5,2,1}}
И получим вывод его в конце в течении 1 сек.

А режимы меняются с 0 до меньше размерность массива.
А у тебя в каждом режиме какие то
if (mode == 0 || mode == 1 || mode == 2 || mode == 3) {
Как тут mode может быть отличной от 0, если ты по case 0 сюда зашел ? А ??? БЫСТРО ОТВЕЧАЙ!
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Как тут mode может быть отличной от 0, если ты по case 0 сюда зашел ? А ??? БЫСТРО ОТВЕЧАЙ!
но надо для свитча задать новое название и перебирать в цикле
я же специально это отметил, не было времени доделывать) а так, хотел дать другое название и перебирать в цикле, там уже проверялось бы, в зависимости от выбранного режима, включать датчик, или нет)
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
Опять я ничего не понял. Если идем в режим 0, отображения часов. То надо их отображать и все! И только часы, и ничего другого. А вот часы меняют свое содержимое 2-5 раз в секунду, этого выше крыше достаточно. И если они поменяли, то возводится флаг, который говорит фастледу обновить данные.
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
А вот часы меняют свое содержимое 2-5 раз в секунду, этого выше крыше достаточно
согласен, но мы же хотели обновлять точки два раза в секунду, чтобы точки чаще мигали, поэтому и пусть чем чаще опрашивается, тем лучше) пересмотрел несколько готовых кодов из прошлой темы, везде аналогично, раз в секунду мигают...
Если идем в режим 0, отображения часов. То надо их отображать и все! И только часы, и ничего другого.
C++:
    if (change = 0; change < 4; change++)
switch (change) {
    case 0: {
        if (mode == 0 || mode == 1 || mode == 2 || mode == 3) {
          if (millis() - t_time > t) {
            TimeToArray();
          }
        }
      }
      break;
  ...........
без компилятора писал))
 

foka44

✩✩✩✩✩✩✩
1 Мар 2021
10
0
Если в body выводить только TimeToArray(); то секунду моргают как положено, если добавить в body вывод ещё функции для вывода значений с датчиков например TempToArray(); то точки моргают не корректно.
Почему мы в TimeToArray принудительно включаем точки и выключаем
C++:
void TimeToArray() { // вывод времени на экран
  int Now = GetTime(); // получаем время
  boolean color_change_flag = false;
  boolean Dots = true; // точки
    if (Dot == 0) Dots = false; else Dots = true;
      if (Dots) { // показ точек
          for (uint8_t i = 0; i < DOTS_NUM; i++) {
                leds[(LEDS_IN_SEGMENT * 14) + i] = ledColor;
                        }
                      }
         else {
                   Dots_off() ;
                     }
А в TempToArray() только выключаем. а они горят если не вызвать Dots_off().
C++:
void TempToArray() { // вывод температуры с датчика DHT22 на экран

  //tempH = (dht.readTemperature());
  int celsius = (dht.readTemperature());
    //Serial.println ((String) celsius + " | " + tempH);
    Serial.println ((String) "Температура" + " | " + celsius);
     Dots_off(); // выключаем точки
  Digit(digits[10], (NUM_LEDS - LEDS_IN_SEGMENT * 7)); // символ градуса
  int digit = abs (celsius % 10);
    Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 14));
  digit = celsius / 10;
    if (digit == 0)Digit(digits[12], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM)); // если впереди ноль, то выключаем его
      else
          Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM)); // иначе показываем как есть
              Digit(digits[12], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // отключаем 1 сегмент
              };
Где вызывается включение точек?
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@foka44, точки работают так,
Dot = second % 2;
Если Dot = true; то показываются.
Позже обновлю код, там попроще будет вывод, компактнее)
 

foka44

✩✩✩✩✩✩✩
1 Мар 2021
10
0
@foka44, точки работают так,
Dot = second % 2;
Если Dot = true; то показываются.
Позже обновлю код, там попроще будет вывод, компактнее)
Наверное их лучше включать, только тогда когда они нужны (в body там где выводится время), что б не выключать их датчиках. Тогда налаживание включение на выключение не будет.
 

foka44

✩✩✩✩✩✩✩
1 Мар 2021
10
0
никто больше не занимался перенесением кода в прошивку?)
я вот перенес, подправил вывод принта на функции с датчиков, не стабильно работает, какой-то дребезг, анимация)
пока не занимался вплотную...
У меня работает хорошо, пока только при рандомном смене цвета цифр и точек, цвет точек меняется раньше, но это надо просто доделать
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
Вот это имелось ввиду ?
1617992235317.png
Очень интересно. Это идет внутри отображения все того же времени. Как часто такое ?
Перерисовку экрана только по изменению содержимого не стал делать ? Я смотрю фигачишь фастлед.шоу постоянно.
И точки не мигают.
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Это идет внутри отображения все того же времени. Как часто такое ?
Не следил, завтра попробую подольше затестить)
Перерисовку не менял, надо отладить, потом попробую убавить. Вроде FastLED вынес, не должно очень часто вызываться... Точки не мигают...
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
Ну как... постоянно я так думаю.. Если не синхронихация. Ограничений на частоту обновление ленты нет никаких
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@Старик Похабыч,
заменил
C++:
  FastLED.show();
на
C++:
  if (millis() - Ftiming > 100) {
    Ftiming = millis();
    FastLED.show();
  }
глюки с перерисовкой пропали, сейчас буду разбираться с точками)
точки наладил, осталось разобраться почему не работал код, аккумулировать все изменения...
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
Вот куда тебя надо стукнуть что бы ты с 1-го раза слушал, что говорят ? :D
Еще раз. Добавь флаг, который будет тру, если было какое то изменение для матрицы и перерисовывай когда этот флаг тру, не забывая его сбросить в Фальш.
Подумай на счет вынести точки вообще в отдельную процедуру. Будет как то так:

{
блок подготовки данных для матрицы:
время,
температура 1
температура 2
..
давление
}
Каждый блок ставить флаг переисовки в тру, елси были изменения. При этом т.к. температура и давление получаются 1 раз в начале цикла отображения, то ставить тру всегда . Часы ставят тру всегда в начале и в том случае если изменились минуты .
А далее блок изменения точек:
если пора менять точки то
если часы то изменить на противоположное значение
если температуры или давление - выключить
если дата - включить.
И можно выставлять флаг при каждом изменении, вряд ли будут любители стробоочек , что бы менять их состояние чаще 10 раз в секунду. А на все остальное будет норм.
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Еще раз. Добавь флаг, который будет тру, если было какое то изменение для матрицы и перерисовывай когда этот флаг тру, не забывая его сбросить в Фальш.
с этим надо разобраться и понять как работает)
для устранения багов хватит таких заглушек)
для точек тоже вручную прописал, работают, очень не привычно))
что бы менять их состояние чаще 10 раз в секунду
выбрал 10, чтобы попасть под точки, а то мало ли)
вот когда успел ответить таким большим текстом, как будто заранее знал, что надо будет так ответить))
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,251
1,297
Москва
А ты думаешь это ты пишешь программу ? Это я пишу программу твоими руками телепатически направляя куда следует и пробуя разные финтифлюшки. Поэтому и знаю что будет дальше :D
 
  • Лойс +1
Реакции: bort707

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@Старик Похабыч, набросал, как и просил)
C++:
void body() {
  static uint32_t ch_tmr = millis();  //статическую переменную для хранения времени выполнения текущего режима,
  //а так же выбор того, что надо выводить
  if ((millis() - ch_tmr) < (periodDisplay[orderDisplay[mode]] * 1000))
  {
    switch (orderDisplay[mode]) { //вывод режимов
      case 0:
        displayTime(timeToString());
        displayTime(timeToStringDots());
        flag = !flag;
        break;
      case 1:
        displayTime(TemperToString());
        flag;
        break;
      case 2:
        displayTime(TemperOutToString());
        flag;
        break;
      case 3:
        displayTime(PressToString());
        flag;
        break;
    }
  }
  else
  {
    ch_tmr = millis();
    mode++;
    if (sizeof(orderDisplay) == mode) mode = 0;
  }
  if (flag) {
    FastLED.show();
    flag = false;
  }
}
температуру и давление надо в тру только поставить)