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

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

  • BMP280

    Голосов: 26 26.8%
  • BME280

    Голосов: 71 73.2%

  • Всего проголосовало
    97

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@bort707,это и называется псевдо рандом)
в таких случаях советуют сбрасывать значение каждый раз или привязывать ко времени.
вот это и планирую к реализации...
по высшей математике тоже что-то было про случайные числа... тоже занимательные были лекции...
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
@bort707, @ASM,
Если задача сводится к тому чтобы добавить разнообразия в цветах относительно заданного кол-ва, то имеет смысл добавлять рандомное смещение относительно текущего индекса, взятое по модулю максимального индекса. Если же для смещения исключить 0 и макс. индекс, то подряд идущих одинаковых цветов не будет.

Ну и отдельно - в контроллерах попросту нет случайных значений, а есть ГПСЧ. Поскольку настоящую случайность получить достаточно непростая задача.
 
  • Лойс +1
Реакции: Lumenjer и bort707

bort707

★★★★★★✩
21 Сен 2020
3,299
958
в таких случаях советуют сбрасывать значение каждый раз или привязывать ко времени.
вот это и планирую к реализации...
значительно проще отбрасывать значение, если оно совпадает с предыдущим. И никакой "высшей математики"...

Ну или как предлагает @kDn выше - результат будет тот же
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
219
110
это и называется псевдо рандом)
Может псевдо-псевдо рандом?) Т.к:
Ну и отдельно - в контроллерах попросту нет случайных значений, а есть ГПСЧ.

А вообще, о рандоме можете почитать тут почитать, а о том, как примерно добиваются "настоящего" рандома - тут
 
  • Лойс +1
Реакции: ASM

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Какие сложные реализации для массива из 0-15 чисел) даже если кто-то добавит количество цветов, всё равно, небольшое количество будет) Индексы, модули, исключение мин и макс... Тогда цветов будет меньше на 2...
Отбросить предыдущее ещё более реальнее выглядит, можно подумать над реализацией кода))

C++:
void Digit (uint8_t digit, uint8_t cursor) { // функция отображения символов

  for (uint8_t mask = 0b01000000; mask > 0; mask = mask >> 1) {
    for (uint8_t i = 0; i < LEDS_IN_SEGMENT; i++) {
      if (new_god) {
        leds[cursor] = (digit & mask) ? ColorTable[random(NUM_COLORS)] : CRGB (0, 0, 0);
      }
      else {
        leds[cursor] = (digit & mask) ? ledColor : CRGB (0, 0, 0);
      }
      cursor ++;
    }
  }
}
byte new = 0;
if (LEDS_IN_SEGMENT [ i ] != LEDS_IN_SEGMENT[ i - 1 ]){
LEDS_IN_SEGMENT[ new ++] = LEDS_IN_SEGMENT[ i ];
}
}
return new;
Как-то так)
Вот от этого будем отталкиваться)
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
3,299
958
Вот от этого будем отталкиваться)
ерунда какая-то...
Что такое LEDS_IN_SEGMENT ? - судя по коду выше - это целое, число светиков в сегменте.
Тогда почему вы обращаетесь с ним, как с массивом?
Вы что пытаетесь добиться вот этой записью? - - LEDS_IN_SEGMENT [ i ]
 

balent

✩✩✩✩✩✩✩
29 Ноя 2021
53
7
@kym13,MAX -это уже на заднем плане, все руки не дойдут переделать их на большие матрицы,есть уже, остается снять маленькие и приколхозить большие, думаю, потянет. Не пробовал никто?
 
Изменено:

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Не добрался до ПК, не экспериментировал больше с НГ.
Вчера выключил НГ режим, мерцания, на которые я указывал, пропали.
Посмотрю режим со сменой цветов, а то никто не отписался, исправилось ли, заодно проверю, как работает)

Увидел этот баг) либо точки сначала меняют цвет, либо часы) не помогла рекомендация поменять местами значит)
Мерцания пару раз увидел)
 
Изменено:

kamikadzze

✩✩✩✩✩✩✩
3 Ноя 2020
23
1
У меня 4 платы осталось, могу выслать конвертом. Конечно не идеально разведено и монтаж компактный но работает
прошивку бы допилить и я корпус буду новый рисовать
если есть платка на этот проект-дайте знать
 

Divin

★★★★✩✩✩
30 Янв 2021
459
204
@ASM, У меня к вам "деловое" предложение - Я рисую схему подключения
Lamp+TM1637.jpg
А вы добавите к прошивке датчик bmp 280 , если конечно вы захотите этим заниматься , я полный профан в программировании.
 

Divin

★★★★✩✩✩
30 Янв 2021
459
204
@ASM, я нашел варианты подключения этого датчика, но как интегрировать его в прошивку абсолютно без понятия, если не будете против в личку скину ссылку на библиотеку и подключение. Прошу прощения а ТМ это что?
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@Divin, надо изучать логику работы) я не интересовался этим модулем)
вот есть тема у Алекса
лучше создать новую тему, если нет аналогичной и ждать помощи там) совсем разные схемы и компоненты, код будет другой)
 

Divin

★★★★✩✩✩
30 Янв 2021
459
204
@ASM, Вы меня не так поняли - я рисую схему подключения именно для этого проекта, схема которую я указал в сообщении только для примера - образец, естественно что в проекте часов с большим индикатором маленький дисплей не нужен :)
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@Divin, тогда просто заменить датчик и библиотеки, изначально у меня было вроде на нем, сейчас поищу примеры...

C++:
/*Блокнотик
  +  задержка wifi при вкл эл-ва
  +  загрузка при старте
  + ограничение по току
  - MQTT
  + IoT
  секунды 500мс
*/
#include <ESP8266WiFi.h>
#include <EasyNTPClient.h>
#include <WiFiUdp.h>
#include <RTClib.h>
RTC_DS3231 rtc;
#include <FastLED.h>
//#include <BMP280_DEV.h>
//BMP280_DEV bmp280;
#include <Wire.h>
#include <SparkFunBME280.h>
BME280 bmp280;
#include <OneWire.h>
#include <DallasTemperature.h>
WiFiUDP udp;

/////////////////////НАСТРОЙКИ И СХЕМА//////////////////
//питание платы от БП не выше 5В
//DS3231 SDA=>D2 SCL+>D1 питание с 5В БП или с 3.3В
//BMP/BME 280 SDA=>D2 SCL+>D1 питание 3.3В
//DS18B20 питание 5В, если уличный без модуля ставим резистор между питанием и сигнальным на 4.7К
const char *ssid = "";  //имя WiFi сети вашего роутера
const char *password = "";    //пароль от сети
#define ONE_WIRE_BUS_2 D5     // PIN датчика ds18b20
int UpdatePeriod = 12;        // период в часах, как часто обновлять время из интернета, лучше не пишите маленькие числа:)
#define LEDS_IN_SEGMENT 4     // задаём сколько у нас светодиодов в сегменте
#define DOTS_NUM 2            // задаём сколько у нас разделительных точек
#define NUM_COLORS 16         // количество цветов, записаны в ColorTable
#define COLOR_CHANGE 0        // смена цвета ( 0 - никогда, 1 - раз в минуту, 2 - каждые десять минут, 3 - каждый час, 4 - каждые десять часов)
// если в схеме один фоторезистор не модулем, то вешаем резистор от 1К до 10К. Если у вас высокая освещенность, то 1К, если слабая, то до 10К
// один вывод фоторезистора на пин A0, или любой другой, второй на GND. Между GND и питанием ставим резистор
#define BRI_PIN A0            // PIN фоторезистора
#define max_bright 255        // максимальная яркость (0 - 255)
#define min_bright 5          // минимальная яркость (0 - 255)
#define bright_constant 1023  // константа усиления от внешнего света (0 - 1023), чем МЕНЬШЕ константа, тем "резче" будет прибавляться яркость
#define coef 0.4              // коэффициент фильтра (0.0 - 1.0), чем больше - тем медленнее меняется яркость
#define auto_bright 1         // автоматическая подстройка яркости от уровня внешнего освещения (1 - включить, 0 - выключить)
EasyNTPClient ntpClient(udp, "pool.ntp.org", (3 * 60 * 60)); //заменить первую цифру на свой часовой пояс, 3 для МСК
#define COLOR_ORDER GRB       // тип ленты, поменять порядок GRB на свой тип, если неправильные цвета
#define LED_PIN 6             // PIN дата от ленты, подключать через резистор 330Ом
int brg = 10000;              // как часто проверять изменение по датчику освещенности в мс, 10000 соответствуют 10сек
byte type_brg = 0;            // выбрать тип датчика, 0 - аналог, 1 - цифровой
byte cnctd = 20;              // кол-во попыток подключиться к роутеру, 2 запроса в сек
uint32_t milliamps = 1000;    // ограничение по току в мА
int delay_narod = 600;        // как часто отправлять значения датчиков на мониторинг, минимум 5 минут, значение в секундах, плюс запас в 5 сек, на всякий случай, получается минимум 305
// при отправке больше 2х запросов в 5 минут, получите бан по IP
// регистрирумся на narodmon.ru, загружаем настроенный скетч, в меню профиль, отладка по IP копируем Mac
// снова профиль, мои датчики, вводим Mac и настраиваем датчики по усмотрению и радуемся их работе :)
static bool Monitoring = true; // включаем мониторинг, иначе false
byte prs = 0;                  // 0 - не показываем символ давления, 1 - показать
/////////////////////КОНЕЦ НАСТРОЕК/////////////////

// настроим библиотеку 1-Wire для связи с датчиком
OneWire oneWire_out(ONE_WIRE_BUS_2);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensors(&oneWire_out); //уличный ds18b20
int Period = UpdatePeriod * 3600; //вычисление секунд
#define NUM_LEDS (LEDS_IN_SEGMENT * 28 + DOTS_NUM) // вычисляем кол-во светодиодов
/////////////////////////////////////////////
CRGB leds[NUM_LEDS];  // определение СД ленты
uint8_t  digits[] = { // определяем символы для отображения
  // код начинается с 0b0, далее идут 7 цифр, каждая цифра это номер фрагмента, 1 - включен, 0- отключен
  // далее указан получающийся символ и порядковый номер в массиве
  0b00111111,     // Символ 0          0
  0b00100001,     // Символ 1          1
  0b01110110,     // Символ 2          2
  0b01110011,     // Символ 3          3
  0b01101001,     // Символ 4          4
  0b01011011,     // Символ 5          5
  0b01011111,     // Символ 6          6
  0b00110001,     // Символ 7          7
  0b01111111,     // Символ 8          8
  0b01111011,     // Символ 9          9
  0b01111000,     // Символ * градус  10
  0b00011110,     // Символ C         11
  0b00000000,     // Без символа      12
  0b01000000,     // Символ -         13
  0b01111100      // Символ P         14
};
bool Dot = true;    // переменная для точек
int last_digit = 0; // последний символ равен нулю
byte set_light;     // переменная для освещенности
byte brightness;    // переменная для освещенности
int new_bright, new_bright_f; // переменная для освещенности
unsigned long bright_timer, off_timer; // переменная для освещенности
unsigned long timing;                  // переменная для мониторинга
float temperature, pressure, altitude; // переменные для библиотеки датчика bmp280
float tempH, tempS, presH;             // переменные для мониторинга
CRGB ledColor = CRGB::Blue;   // цвет в hex
CRGB ColorTable[NUM_COLORS] = { // Таблица цветов
  CRGB::Amethyst,
  CRGB::Aqua,
  CRGB::Blue,
  CRGB::Chartreuse,
  CRGB::DarkGreen,
  CRGB::DarkMagenta,
  CRGB::DarkOrange,
  CRGB::DeepPink,
  CRGB::Fuchsia,
  CRGB::Gold,
  CRGB::GreenYellow,
  CRGB::LightCoral,
  CRGB::Tomato,
  CRGB::Salmon,
  CRGB::Red,
  CRGB::Orchid
};
/////////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  Wire.begin();
  bmp280.setI2CAddress(0x76); //Connect to a second sensor
  if (bmp280.beginI2C() == false) Serial.println("Sensor B connect failed");

  LEDS.setBrightness(50);
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS); // подключение ленты
  FastLED.setMaxPowerInVoltsAndMilliamps (5, milliamps);
  //  bmp280.begin(BMP280_I2C_ALT_ADDR);
  //  bmp280.setTimeStandby(TIME_STANDBY_2000MS);
  //  bmp280.startNormalConversion();
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  /*
    if (!bmp.begin()) {                               // Проверка инициализации датчика
    Serial.println("Could not find a valid BME280 sensor, check wiring!"); // Печать, об ошибки инициализации.
    while (1);                                          // Зацикливаем
    }*/
  syncTime();

}
/////////////////////////////////////////////
void BrightnessCheck() { // функция освещенности
  static uint32_t last_br = millis();
  if ((millis() - last_br) < brg) return;
  last_br = millis();
  if (auto_bright) {                         // если включена адаптивная яркость
    if (millis() - bright_timer > 100) {     // каждые 100 мс
      bright_timer = millis();               // сбросить таймер
      switch (type_brg) {
        case 1:
          new_bright = map(digitalRead(BRI_PIN), 0, bright_constant, max_bright, min_bright);   // считать показания с фоторезистора, перевести диапазон
          break;
        default:
          new_bright = map(analogRead(BRI_PIN), 0, bright_constant, max_bright, min_bright);   // считать показания с фоторезистора, перевести диапазон
      }
      //      Serial.println((String)"Освещенность: " + new_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);      // установить новую яркость
    }
  }
};
/////////////////////////////////////////////
void syncTime() {
  WiFi.begin(ssid, password);
  byte trys = 0;
  Serial.println("");
  while (WiFi.status() != WL_CONNECTED) {
    trys++;
    //    delay(500);
    NoSignal();
    Serial.print(".");
    if (trys > cnctd)
    {
      Serial.println("Нет связи с роутером при старте!");
      return;
    }
  }
  long ntpTime = ntpClient.getUnixTime();
  if (ntpTime > 1609459200) {
    rtc.adjust(DateTime(ntpTime));
    Serial.println("");
    Serial.println("Время записано!");
    //    Serial.println(WiFi.localIP());
    //    Serial.println(udp.localPort());
  }
  else
  {
    Serial.println("");
    Serial.println("Отказ в записи! Время получено неправильное!");
    GetTime();
  }/*
  // Выключаем WIFI после обновления
  // похоже теперь не нужна, раз подключили мониторинг :)
  WiFi.disconnect();
  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();
  delay(1000);*/
}
/////////////////////////////////////////////
int GetTime() {
  DateTime now = rtc.now();
  int hour = now.hour();
  int minute = now.minute();
  int second = now.second();
  Serial.println((String)hour + ":" + minute + ":" + second);
  Dot = second % 2; // точки мигают раз в сек
  return (hour * 100 + minute);
};
/////////////////////////////////////////////
void TimeToArray() { // вывод времени на экран
  int Now = GetTime(); // получаем время
  boolean Dots = true; // точки
  boolean color_change_flag = false;
  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(); // выключение точек
  }
  for (int i = 1; i <= 4; i++) { // 4 сегмента
    int digit = Now % 10; // получаем последнюю цифру в времени
    int cursor = NUM_LEDS - i * LEDS_IN_SEGMENT * 7;
    if (i > 2) {
      cursor -= DOTS_NUM;
    }
    if ( i == 4 & digit == 0)Digit(digits[12], cursor); // если впереди ноль, то выключаем его, например 01:23 будет как 1:23
    else
      Digit(digits[digit], cursor);                     // иначе показываем символ

    if ( i == COLOR_CHANGE) {                           // как часто менять цвет
      if (digit != last_digit) {
        color_change_flag = true;
        last_digit = digit;
      }
    }
    Now /= 10;
  };
  if (color_change_flag) ledColor =  ColorTable[random(NUM_COLORS)];     // случайный цвет из таблицы
};
/////////////////////////////////////////////
void Dots_off()  { // отключаем точки принудительно, где не нужны
  for (uint8_t i = 0; i < DOTS_NUM; i++) {
    leds[(LEDS_IN_SEGMENT * 14) + i] = 0x000000;
  }
}
/////////////////////////////////////////////
void Digit (uint8_t digit, uint8_t cursor) { // функция отображения символов
  for (uint8_t mask = 0b01000000; mask > 0; mask = mask >> 1) {
    for (uint8_t i = 0; i < LEDS_IN_SEGMENT; i++) {
      leds[cursor] = (digit & mask) ? ledColor : CRGB (0, 0, 0);
      cursor ++;
    }
  }
}
/////////////////////////////////////////////
void TempToArray() { // вывод температуры с датчика BMP280 на экран
  bmp280.beginI2C();
  //  bmp280.getMeasurements(temperature, pressure, altitude);
  tempH = (bmp280.readTempC());
  int celsius = tempH;
  //  int celsius = temperature; //датчик на стене, выше роста, корректировка минус 1 градус, сейчас на столе стенд
  //  tempH = temperature;


  Serial.println ((String) celsius + " | " + tempH);
  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 сегмент
};
/////////////////////////////////////////////
void PressToArray() { // вывод давления на экран
  bmp280.beginI2C();
  presH = (bmp280.readFloatPressure() * 0.0075);
  int davlenie = presH;
  //  bmp280.getMeasurements(temperature, pressure, altitude);
  //  int davlenie = pressure * 0.75;

  //  presH = pressure * 0.75;

  Serial.println ((String) davlenie + " | " + presH);

  Dots_off(); // выключаем точки

  int digit = davlenie % 10;
  Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 7));

  digit = davlenie % 100 / 10;
  Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 14));

  digit = davlenie / 100;
  Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  switch (prs) {
    case 1:
      Digit(digits[14], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // показываем символ P
      break;
    default:
      Digit(digits[12], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // отключаем первый сегмент
  }
};
/////////////////////////////////////////////
void TempStreetToArray() { // вывод уличной температуры на экран
  sensors.requestTemperatures(); // опрос датчика уличной температуры
  int celsius = sensors.getTempCByIndex(0); // чтение уличной температуры с датчика 0, налогично следующий будет 1
  tempS = sensors.getTempCByIndex(0);
  Serial.println ((String) celsius + " | " + sensors.getTempCByIndex(0));

  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 = abs (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)); // иначе показываем как есть

  if (sensors.getTempCByIndex(0) <= -1)Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // если < или = -1, то показываем -
  else
    Digit(digits[12], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // иначе выключаем 1 сегмент
};
/////////////////////////////////////////////
void body() { // вывод информации
  static bool TempShow = true; // флаг для температуры в помещении
  static bool TempSShow = true; // флаг для температуры на улице
  static bool PressShow = true; // флаг для давления
  uint32_t tmrall = millis() % 12000 / 1000; //берем интервал в 12сек
  static uint32_t tmrall_old = 10000;        //в расчет берутся 10сек, в исключение 2 сек, ниже будет понятно:)
  if (tmrall_old != tmrall)
  {
    tmrall_old = tmrall;
    if (tmrall < 6) //6 сек показывают часы
    {
      TimeToArray();
      TempShow = true;
      TempSShow = true;
      PressShow = true;
    }
    else if (tmrall < 8) //2 секунды показывается температура, добавляем +2
    {
      if (TempShow)
      {
        TempToArray();
        TempShow = false;
      }
    }
    else if (tmrall < 10) //2 секунды показывается температура, добавляем +2
    {
      if (TempSShow)
      {
        TempStreetToArray();
        TempSShow = false;
      }
    }
    else
    {
      if (PressShow) // остальное время показывается давление
      {
        PressToArray();
        PressShow = false;
      }
    }
    FastLED.show(); // команда для включения светодиодов
  };
}
/////////////////////////////////////////////
void loop() {
  BrightnessCheck();
  if (millis() % 1000 < Period - 1)
  {
    body();
  }
  else {
    syncTime();
  }

  if (Monitoring) {
    if (millis() - timing > delay_narod * 1000) {
      timing = millis();
      narod();
    }
  }
}
/////////////////////////////////////////////
void narod() { //функция для народного мониторинга
  WiFi.begin(ssid, password);
  byte tryss = 0;
  Serial.println("Start_narod");
  while (WiFi.status() != WL_CONNECTED) {
    tryss++;
    delay(500);
    Serial.print("_");
    if (tryss > 20)
    {
      Serial.println("Нет связи с роутером, narod!");
      return;
    }
  }
  String buf = "#" + WiFi.macAddress();
  // добавление и удаление датчиков по шаблону
  buf = buf + "\n#T1#" + tempH;
  buf = buf + "\n#T2#" + tempS;
  buf = buf + "\n#T3#" + presH;
  buf = buf + "\n##";
  WiFiClient client;
  client.connect("narodmon.ru", 8283);
  client.print(buf);
  Serial.println("Показания отправлены!");
}
/////////////////////////////////////////////
void NoSignal() { // анимация загрузки :)
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM));
  FastLED.show(); delay(125);
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  FastLED.show(); delay(125);
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 14));
  FastLED.show(); delay(125);
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 7));
  FastLED.show(); delay(125);
  LEDS.clear();
}
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
и более ранний
C++:
#include <ESP8266WiFi.h>
#include <EasyNTPClient.h>
#include <WiFiUdp.h>
#include <RTClib.h>
RTC_DS3231 rtc;
#include <FastLED.h>
#include <BMP280_DEV.h>
BMP280_DEV bmp280;
#include <OneWire.h>
#include <DallasTemperature.h>
WiFiUDP udp;

/////////////////////НАСТРОЙКИ И СХЕМА//////////////////
//питание платы от БП не выше 5В
//DS3231 SDA=>D2 SCL+>D1 питание с 5В БП или с 3.3В
//BMP/BME 280 SDA=>D2 SCL+>D1 питание 3.3В
//DS18B20 питание 5В, если уличный без модуля ставим резистор между питанием и сигнальным на 4.7К
const char *ssid = "";        //имя WiFi сети вашего роутера
const char *password = "";    //пароль от сети
#define ONE_WIRE_BUS_2 D5     //PIN датчика ds18b20
int UpdatePeriod = 12;        //период в часах, как часто обновлять время из интернета, лучше не пишите маленькие числа:)
#define LEDS_IN_SEGMENT 4     // задаём сколько у нас светодиодов в сегменте
#define DOTS_NUM 2            // задаём сколько у нас разделительных точек
#define NUM_COLORS 16         // количество цветов, записаны в ColorTable
#define COLOR_CHANGE 0        // смена цвета ( 0 - никогда, 1 - раз в минуту, 2 - каждые десять минут, 3 - каждый час, 4 - каждые десять часов)
//если в схеме один фоторезистор не модулем, то вешаем резистор от 1К до 10К. Если у вас высокая освещенность, то 1К, если слабая, то до 10К
//один вывод фоторезистора на пин A0, или любой другой, второй на GND. Между GND и питанием ставим резистор
#define BRI_PIN A0            // PIN фоторезистора
#define max_bright 255        // максимальная яркость (0 - 255)
#define min_bright 10         // минимальная яркость (0 - 255)
#define bright_constant 1023  // константа усиления от внешнего света (0 - 1023), чем МЕНЬШЕ константа, тем "резче" будет прибавляться яркость
#define coef 0.4              // коэффициент фильтра (0.0 - 1.0), чем больше - тем медленнее меняется яркость
#define auto_bright 1         // автоматическая подстройка яркости от уровня внешнего освещения (1 - включить, 0 - выключить)
EasyNTPClient ntpClient(udp, "pool.ntp.org", (3 * 60 * 60)); //заменить первую цифру на свой часовой пояс, 3 для МСК
#define COLOR_ORDER GRB       // тип ленты, поменять порядок GRB на свой тип, если неправильные цвета
#define LED_PIN 6             // PIN дата от ленты, подключать через резистор 330Ом
int brg = 10000;              // как часто проверять изменение по датчику освещенности в мс, 10000 соответствуют 10сек
byte type_brg = 0;            // выбрать тип датчика, 0 - аналог, 1 - цифровой
byte cnctd = 20;              // кол-во попыток подключиться к роутеру, 2 запроса в сек
uint32_t milliamps = 1000;    // ограничение по току в мА
/////////////////////КОНЕЦ НАСТРОЕК/////////////////

// настроим библиотеку 1-Wire для связи с датчиком
OneWire oneWire_out(ONE_WIRE_BUS_2);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensors(&oneWire_out); //уличный ds18b20
int Period = UpdatePeriod * 3600; //вычисление секунд
#define NUM_LEDS (LEDS_IN_SEGMENT * 28 + DOTS_NUM) // вычисляем кол-во светодиодов
/////////////////////////////////////////////
CRGB leds[NUM_LEDS];  // определение СД ленты
uint8_t  digits[] = { // определяем символы для отображения
  // код начинается с 0b0, далее идут 7 цифр, каждая цифра это номер фрагмента, 1 - включен, 0- отключен
  // далее указан получающийся символ и порядковый номер в массиве
  0b00111111,     // Символ 0          0
  0b00100001,     // Символ 1          1
  0b01110110,     // Символ 2          2
  0b01110011,     // Символ 3          3
  0b01101001,     // Символ 4          4
  0b01011011,     // Символ 5          5
  0b01011111,     // Символ 6          6
  0b00110001,     // Символ 7          7
  0b01111111,     // Символ 8          8
  0b01111011,     // Символ 9          9
  0b01111000,     // Символ * градус  10
  0b00011110,     // Символ C         11
  0b00000000,     // Без символа      12
  0b01000000      // Символ -         13
};
bool Dot = true;    // переменная для точек
int last_digit = 0; // последний символ равен нулю
byte set_light;     // переменная для освещенности
byte brightness;    // переменная для освещенности
int new_bright, new_bright_f; // переменная для освещенности
unsigned long bright_timer, off_timer; // переменная для освещенности
float temperature, pressure, altitude;
CRGB ledColor = CRGB::Blue;   // цвет в hex
CRGB ColorTable[NUM_COLORS] = { // Таблица цветов
  CRGB::Amethyst,
  CRGB::Aqua,
  CRGB::Blue,
  CRGB::Chartreuse,
  CRGB::DarkGreen,
  CRGB::DarkMagenta,
  CRGB::DarkOrange,
  CRGB::DeepPink,
  CRGB::Fuchsia,
  CRGB::Gold,
  CRGB::GreenYellow,
  CRGB::LightCoral,
  CRGB::Tomato,
  CRGB::Salmon,
  CRGB::Red,
  CRGB::Orchid
};
/////////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  Wire.begin();
  LEDS.setBrightness(50);
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS); // подключение ленты
  FastLED.setMaxPowerInVoltsAndMilliamps (5, milliamps);
  bmp280.begin(BMP280_I2C_ALT_ADDR);
  bmp280.setTimeStandby(TIME_STANDBY_2000MS);
  bmp280.startNormalConversion();
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  /*
    if (!bmp.begin()) {                               // Проверка инициализации датчика
    Serial.println("Could not find a valid BME280 sensor, check wiring!"); // Печать, об ошибки инициализации.
    while (1);                                          // Зацикливаем
    }*/
  syncTime();

}
/////////////////////////////////////////////
void BrightnessCheck() { // функция освещенности
  static uint32_t last_br = millis();
  if ((millis() - last_br) < brg) return;
  last_br = millis();
  if (auto_bright) {                         // если включена адаптивная яркость
    if (millis() - bright_timer > 100) {     // каждые 100 мс
      bright_timer = millis();               // сбросить таймер
      switch (type_brg) {
        case 1:
          new_bright = map(digitalRead(BRI_PIN), 0, bright_constant, max_bright, min_bright);   // считать показания с фоторезистора, перевести диапазон
          break;
        default:
          new_bright = map(analogRead(BRI_PIN), 0, bright_constant, max_bright, min_bright);   // считать показания с фоторезистора, перевести диапазон
      }
      Serial.println((String)"Освещенность: " + new_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);      // установить новую яркость
    }
  }
};
/////////////////////////////////////////////
void syncTime() {
  WiFi.begin(ssid, password);
  byte trys = 0;
  Serial.println("");
  while (WiFi.status() != WL_CONNECTED) {
    trys++;
    //    delay(500);
    NoSignal();
    Serial.print(".");
    if (trys > cnctd)
    {
      Serial.println("Нет связи с роутером!");
      return;
    }
  }
  long ntpTime = ntpClient.getUnixTime();
  if (ntpTime > 1609459200) {
    rtc.adjust(DateTime(ntpTime));
    Serial.println("");
    Serial.println("Время записано!");
  }
  else
  {
    Serial.println("");
    Serial.println("Отказ в записи! Время получено неправильное!");
    GetTime();
  }
  // Выключаем WIFI после обновления
  WiFi.disconnect();
  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();
  delay(1000);
}
/////////////////////////////////////////////
int GetTime() {
  DateTime now = rtc.now();
  int hour = now.hour();
  int minute = now.minute();
  int second = now.second();
  Serial.println((String)hour + ":" + minute + ":" + second);
  Dot = second % 2; // точки мигают раз в сек
  return (hour * 100 + minute);
};
/////////////////////////////////////////////
void TimeToArray() { // вывод времени на экран
  int Now = GetTime(); // получаем время
  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(); // выключение точек
  }
  for (int i = 1; i <= 4; i++) { // 4 сегмента
    int digit = Now % 10; // получаем последнюю цифру в времени
    int cursor = NUM_LEDS - i * LEDS_IN_SEGMENT * 7;
    if (i > 2) {
      cursor -= DOTS_NUM;
    }
    if ( i == 4 & digit == 0)Digit(digits[12], cursor); // если впереди ноль, то выключаем его, например 01:23 будет как 1:23
    else
      Digit(digits[digit], cursor);                     // иначе показываем символ

    if ( i == COLOR_CHANGE) {                           // как часто менять цвет
      if (digit != last_digit) {
        ledColor =  ColorTable[random(NUM_COLORS)];     // случайный цвет из таблицы
      }
      last_digit = digit;
    }
    Now /= 10;
  };
};
/////////////////////////////////////////////
void Dots_off()  { // отключаем точки принудительно, где не нужны
  for (uint8_t i = 0; i < DOTS_NUM; i++) {
    leds[(LEDS_IN_SEGMENT * 14) + i] = 0x000000;
  }
}
/////////////////////////////////////////////
void Digit (uint8_t digit, uint8_t cursor) { // функция отображения символов
  for (uint8_t mask = 0b01000000; mask > 0; mask = mask >> 1) {
    for (uint8_t i = 0; i < LEDS_IN_SEGMENT; i++) {
      leds[cursor] = (digit & mask) ? ledColor : CRGB (0, 0, 0);
      cursor ++;
    }
  }
}
/////////////////////////////////////////////
void TempToArray() { // вывод температуры с датчика BMP280 на экран
  bmp280.getMeasurements(temperature, pressure, altitude);
  int celsius = temperature; //датчик на стене, выше роста, корректировка минус 1 градус, сейчас на столе стенд

  Serial.println ((String) celsius + " | " + temperature);
  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 сегмент
};
/////////////////////////////////////////////
void PressToArray() { // вывод давления на экран
  bmp280.getMeasurements(temperature, pressure, altitude);
  int davlenie = pressure * 0.75;
  Serial.println ((String) davlenie + " | " + pressure * 0.75);

  Dots_off(); // выключаем точки

  int digit = davlenie % 10;
  Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 7));

  digit = davlenie % 100 / 10;
  Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 14));

  digit = davlenie / 100;
  Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));

  Digit(digits[12], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // отключаем первый сегмент
};
/////////////////////////////////////////////
void TempStreetToArray() { // вывод уличной температуры на экран
  sensors.requestTemperatures(); // опрос датчика уличной температуры
  int celsius = sensors.getTempCByIndex(0); // чтение уличной температуры
  Serial.println ((String) celsius + " | " + sensors.getTempCByIndex(0));

  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 = abs (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)); // иначе показываем как есть

  if (sensors.getTempCByIndex(0) <= -1)Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // если < или = -1, то показываем -
  else
    Digit(digits[12], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); // иначе выключаем 1 сегмент
};
/////////////////////////////////////////////
void Asm() { //мой образец вывода
  static bool TempShow = true; // флаг для температуры в помещении
  static bool TempSShow = true; // флаг для температуры на улице
  static bool PressShow = true; // флаг для давления
  uint32_t tmrall = millis() % 12000 / 1000; //берем интервал в 12сек
  static uint32_t tmrall_old = 10000;        //в расчет берутся 10сек, в исключение 2 сек, ниже будет понятно:)
  if (tmrall_old != tmrall)
  {
    tmrall_old = tmrall;
    if (tmrall < 6) //6 сек показывают часы
    {
      TimeToArray();
      TempShow = true;
      TempSShow = true;
      PressShow = true;
    }
    else if (tmrall < 8) //2 секунды показывается температура, добавляем +2
    {
      if (TempShow)
      {
        TempToArray();
        TempShow = false;
      }
    }
    else if (tmrall < 10) //2 секунды показывается температура, добавляем +2
    {
      if (TempSShow)
      {
        TempStreetToArray();
        TempSShow = false;
      }
    }
    else
    {
      if (PressShow) // остальное время показывается давление
      {
        PressToArray();
        PressShow = false;
      }
    }
    FastLED.show(); // команда для включения светодиодов
  };
}
/////////////////////////////////////////////
void loop() {
  BrightnessCheck();
  if (millis() % 1000 < Period - 1)
  {
    Asm();
    //kym13();
  }
  else {
    syncTime();
  }
}
/////////////////////////////////////////////
void kym13() {
  static bool TempSShow = true; // флаг для температуры на улице
  uint32_t tmrall = millis() % 60000 / 1000;
  static uint32_t tmrall_old = 46000;
  if (tmrall_old != tmrall)
  {
    tmrall_old = tmrall;
    if (tmrall < 46) //46 сек показывают часы
    {
      TimeToArray();
      TempSShow = true;
    }
    else
    {
      if (TempSShow) // остальное время показывается давление
      {
        TempStreetToArray();
        TempSShow = false;
      }
    }
    FastLED.show(); // команда для включения светодиодов
  };
}
/////////////////////////////////////////////
void NoSignal() {
  for (int i = 0; i < 4; i++)
  {
    leds[i] = ledColor;
    FastLED.show();
    delay(40);
  }
  for (int i = 28; i < 32; i++)
  {
    leds[i] = ledColor;
    FastLED.show();
    delay(40);
  }
  for (int i = 58; i < 62; i++)
  {
    leds[i] = ledColor;
    FastLED.show();
    delay(40);
  }
  for (int i = 86; i < 90; i++)
  {
    leds[i] = ledColor;
    FastLED.show();
    delay(40);
  }
  LEDS.clear();
}
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@Divin,да, смотри, должна быть в менеджере библиотек
 
  • Лойс +1
Реакции: Divin

Divin

★★★★✩✩✩
30 Янв 2021
459
204
Внес изменения в последний скетч, все компилируется - с меня схема, постараюсь сделать в до среды!
C++:
#include "Constants.h"
#include "ESP8266WiFi.h"
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
const char* host = "web";
const char* ssid = STASSID;
const char* password = STAPSK;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
#include "EasyNTPClient.h"
#include <WiFiUdp.h>
#include "RTClib.h"
RTC_DS3231 rtc;
#include "FastLED.h"
//#include <BMP280_DEV.h>
//BMP280_DEV bmp280;
#include <Wire.h>
#include "SparkFunBME280.h"
BME280 bmp280;
#include "OneWire.h"
#include "DallasTemperature.h"
 
  • Лойс +1
Реакции: vvmxx и maksland

Divin

★★★★✩✩✩
30 Янв 2021
459
204
А кто нибудь может подсказать схему подключения диодов в индикаторе
Резервная_копия_clock.jpg