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

александр1992

✩✩✩✩✩✩✩
12 Янв 2021
2
0
посмотрите пожалуйста в чем может быть косяк? вроде работали и потом заглючили,
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@александр1992, что-то с анимацией, думаю...
я собрал свой стенд, а прошиваться не хочет, ардуинка прошивалась длинным кабелем, эта что-то капризничает, хотя информацию о плате получает)
Serial port COM4
Connecting........_____....._____....._____....._____....._____....._____.....____Traceback (most recent call last):
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
После первого запуска в мониторе все было как надо, после второго запуска и по сей момент
Код:
ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld
непонятно, что за глюки у ESP?)
первый запуск бывает удачным, если подключить питание заново, но после нажатия сброс, снова вылетает эта ошибка, на любом скетче)

Запустил)))
ura.jpg
 
Изменено:

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Весь вечер ломаю голову, ну никак не считывает показания Adafruit_BMP280 с датчика на ESP8266,
походу не реализован, надо искать другую библиотеку))
iarduino_bmp280 на ардуинке считывает, значит датчик живой, а тут ни в какую)

нашел BMx280, работает вроде)

DallasTemperature не хочет считывать с ds18b20, одни проблемы))
 
Изменено:

александр1992

✩✩✩✩✩✩✩
12 Янв 2021
2
0
@александр1992, что-то с анимацией, думаю...
я собрал свой стенд, а прошиваться не хочет, ардуинка прошивалась длинным кабелем, эта что-то капризничает, хотя информацию о плате получает)
Serial port COM4
Connecting........_____....._____....._____....._____....._____....._____.....____Traceback (most recent call last):
там нет анимации вобще

в помещении
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@александр1992, проверь питание и остальные провода, может провод отвалился от ленты. Или влага попала.

Протестировал ds18b20 на ардуинке с 5В, показание 5.5', а при 3.3 показания уже 5' какая большая разница)

очередная версия кода, все работает, но... показания с bmp280 поступают с задержкой в минуту, поэтому первые показания будут с запозданием, пока не разобрался, почему)
C++:
#include <ESP8266WiFi.h>
#include <EasyNTPClient.h>
#include <WiFiUdp.h>
#include <RTClib.h>
RTC_DS3231 rtc;
#include <FastLED.h>
//#include <Adafruit_Sensor.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <Adafruit_BMP280.h>
//Adafruit_BMP280 bmp(0x76);
//Adafruit_BMP280 bmp;
#include <BMP280_DEV.h>
BMP280_DEV bmp280;
#include <OneWire.h>
#include <DallasTemperature.h>
// сигнальный провод подключен к 5 пину на Arduino
#define ONE_WIRE_BUS_2 D5

// настроим библиотеку 1-Wire для связи с датчиком
OneWire oneWire_out(ONE_WIRE_BUS_2);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensors(&oneWire_out); //уличный

float temperature, pressure, altitude;
int UpdatePeriod = 12; //период в часах
int Period = UpdatePeriod * 3600; //вычисление секунд

const char *ssid = "";
const char *password = "";

#define LEDS_IN_SEGMENT 4     // задаём сколько у нас светодиодов в сегменте
#define DOTS_NUM 2            // задаём сколько у нас разделительных точек
#define NUM_LEDS (LEDS_IN_SEGMENT * 28 + DOTS_NUM) // вычисляем кол-во светодиодов
#define COLOR_CHANGE 0
#define NUM_COLORS 16

WiFiUDP udp;
EasyNTPClient ntpClient(udp, "pool.ntp.org", (3 * 60 * 60));

#define COLOR_ORDER GRB  // тип ленты
#define LED_PIN 6  // пин дата от ленты
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; // последний символ равен нулю
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);
  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);                                          // Зацикливаем
    }*/

  //  Serial.println("Обновление");
  syncTime();
  Wire.begin();
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS); // подключение ленты
  LEDS.setBrightness(55);
}

void syncTime() {
  WiFi.begin(ssid, password);
  byte trys = 0;
  Serial.println("");
  while (WiFi.status() != WL_CONNECTED) {
    trys++;
    delay(500);
    Serial.print(".");
    if (trys > 10)
    {
      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 NoSignal() {
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 7));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 14));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM));
  }*/


void TempToArray() { // вывод температуры с датчика BMP280 на экран
  //  bmp.begin(0x76);
  //  int celsius = bmp.readTemperature(); // считываем датчик, датчик за часами, часы на стене, там температура чуть выше, корректировка минус 1
  //Serial.println (celsius);
  //  Serial.println (bmp.readTemperature());

  bmp280.getMeasurements(temperature, pressure, altitude);
  int celsius = temperature - 1; //датчик на стене, выше роста, корректировка минус 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() { // вывод давления на экран
  //  bmp.begin(0x76);
  //  int davlenie = bmp.readPressure();
  //  Serial.println (bmp.readPressure());
  //  Serial.println (davlenie);

  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 body() {
  TimeToArray(); FastLED.show(); delay(1000);
  TimeToArray(); FastLED.show(); delay(1000);
  TimeToArray(); FastLED.show(); delay(1000);
  TimeToArray(); FastLED.show(); delay(1000);
  TempToArray(); FastLED.show(); delay(2000);
  TempStreetToArray(); FastLED.show(); delay(2000);
  PressToArray(); FastLED.show(); delay(2000);
}

void loop() {

  if (millis() % 1000 < Period - 1)
  {
    body();
  }
  else {
    syncTime();
  }
}
 
Изменено:

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
@ASM Протестировал без BMP но с DS18b20, часы работают(пришлось изменить часовой пояс, у меня +6 оказывается), очень часто выводятся показания с датчиков и ещё при переключении минут последняя цифра меняет цвет с задержкой. А автоматическая регулировка яркости будет?
 

Вложения

  • 47.4 KB Просмотры: 4

ASM

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

Обновляю, добавил регулировку яркости) При сборке заменил резистор с 1К на 6К, света немного падает на датчик, должен чувствительнее быть)
И можно будет наводить порядок в коде)
C++:
#include <ESP8266WiFi.h>
#include <EasyNTPClient.h>
#include <WiFiUdp.h>
#include <RTClib.h>
RTC_DS3231 rtc;
#include <FastLED.h>
//#include <Adafruit_Sensor.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <Adafruit_BMP280.h>
//Adafruit_BMP280 bmp(0x76);
//Adafruit_BMP280 bmp;
#include <BMP280_DEV.h>
BMP280_DEV bmp280;
#include <OneWire.h>
#include <DallasTemperature.h>
// сигнальный провод подключен к 5 пину на Arduino
#define ONE_WIRE_BUS_2 D5

// настроим библиотеку 1-Wire для связи с датчиком
OneWire oneWire_out(ONE_WIRE_BUS_2);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensors(&oneWire_out); //уличный

float temperature, pressure, altitude;
int UpdatePeriod = 12; //период в часах
int Period = UpdatePeriod * 3600; //вычисление секунд

const char *ssid = "";
const char *password = "";

#define LEDS_IN_SEGMENT 4     // задаём сколько у нас светодиодов в сегменте
#define DOTS_NUM 2            // задаём сколько у нас разделительных точек
#define NUM_LEDS (LEDS_IN_SEGMENT * 28 + DOTS_NUM) // вычисляем кол-во светодиодов
#define COLOR_CHANGE 0
#define NUM_COLORS 16
#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 - выключить)
/////////////////////////////////////////////
#define BRI_PIN A0 // PIN фоторезистора
WiFiUDP udp;
EasyNTPClient ntpClient(udp, "pool.ntp.org", (3 * 60 * 60));

#define COLOR_ORDER GRB  // тип ленты
#define LED_PIN 6  // пин дата от ленты
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; // переменная для освещенности
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);
  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);                                          // Зацикливаем
    }*/

  //  Serial.println("Обновление");
  syncTime();
  Wire.begin();
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS); // подключение ленты
  //  LEDS.setBrightness(55);
}
void BrightnessCheck() { // функция освещенности
  static uint32_t last_br = millis();
  if ((millis() - last_br) < 10000) return;
  last_br = millis();
  if (auto_bright) {                         // если включена адаптивная яркость
    if (millis() - bright_timer > 100) {     // каждые 100 мс
      bright_timer = millis();               // сбросить таймер
      new_bright = map(analogRead(BRI_PIN), 0, bright_constant, max_bright, min_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);
    Serial.print(".");
    if (trys > 10)
    {
      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 NoSignal() {
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 7));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 14));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM));
  }*/


void TempToArray() { // вывод температуры с датчика BMP280 на экран
  //  bmp.begin(0x76);
  //  int celsius = bmp.readTemperature(); // считываем датчик, датчик за часами, часы на стене, там температура чуть выше, корректировка минус 1
  //Serial.println (celsius);
  //  Serial.println (bmp.readTemperature());

  bmp280.getMeasurements(temperature, pressure, altitude);
  int celsius = temperature - 1; //датчик на стене, выше роста, корректировка минус 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() { // вывод давления на экран
  //  bmp.begin(0x76);
  //  int davlenie = bmp.readPressure();
  //  Serial.println (bmp.readPressure());
  //  Serial.println (davlenie);

  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 body() {
  BrightnessCheck();
  TimeToArray(); FastLED.show(); delay(1000);
  TimeToArray(); FastLED.show(); delay(1000);
  TimeToArray(); FastLED.show(); delay(1000);
  TimeToArray(); FastLED.show(); delay(1000);
  TempToArray(); FastLED.show(); delay(2000);
  TempStreetToArray(); FastLED.show(); delay(2000);
  PressToArray(); FastLED.show(); delay(2000);
}

void loop() {

  if (millis() % 1000 < Period - 1)
  {
    body();
  }
  else {
    syncTime();
  }
}

Если 10 раз не вышло подключиться - надо выходить без обновления времени
вот вспомнил эту фразу, когда подумал такой момент)
представим ситуацию, выключился свет, включился, включились часы, и сразу проверять есть ли связь с роутером, а ее не будет, т.к. еще не поднялось интернет соединение и нет WiFi.
Поэтому предлагаю проверять наличие соединения хотя бы минуту, а не 5 секунд)
При этом можно сделать анимацию на экране в виде загрузки)
 
Изменено:

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
@ASM, На датчик света не реагирует, глюк на последней цифре цвет так и остался, правда не всегда. Кстати глюк на последней цифре был и в последнем скетче который на ардуино. Смена показаний 4 сек часы, 2 сек температура так и будет?
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@kym13, яркость на пине А0. Смену цветов менял?)
4 и 2 сек поменяй в самом низу как нужно.
 

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
@ASM, Я и подключал к А0 (у меня модуль) может ему 3,3В мало? если запитывать от 5в то я так понимаю нужно согласовать уровень выхода. В самом низу кода одинаковых функций на вывод время 4 шт., я пробовал менять на большее время начинает тупить(то точки пропадают, то цвет нет меняют)
Ещё заметил что секунд через 10 яркость сама падает примерно на 50% не зависимо от того подключен фоторезистор или нет. Цвета меняются.
 
Изменено:

ASM

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

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
@ASM, добавил внизу 46 позиций, теперь более менее читабельно. После загрузки яркость сохраняется до первого показа температуры с 18b20, затем падает на 50% и с такой яркостью продолжает постоянно.
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@kym13, ого, как ты решил)) ладно, тогда попробую упростить сегодня) в твоём случае яркость меняется каждую минуту, в зависимости от освещенности. У меня на данный момент каждые 10 секунд, т.к. цикл короче. И добавлю в монитор информацию от датчика освещенности, и будет видно, работает ли у тебя он.
 

maksland

★★★✩✩✩✩
13 Янв 2019
617
145
Omsk
нарисуйте схему пжлста ... а то сами что мутите, мутите :) охота поучаствовать ! помочь хотя бы советами
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@maksland,тут нет схемы) на nodemcu полно питалова в 3В, I2C порты D2 и D1)
может ему 3,3В мало
в схемах подключают к 3,3В, так что норм)
если запитывать от 5в то я так понимаю нужно согласовать уровень выхода
вот это мне не понятно, я запитал от БП, закончились пины)
при переключении минут последняя цифра меняет цвет
этот косяк с других проектов, при смене минут сначала меняет цвет последняя цифра, затем полностью часы, но если выключена смена цвета, то все норм)
поправил код, смотри) сделал вывод автояркости в монитор, сделал под тебя вывод в часы, увидишь там, если что подкорректируй секунды)
C++:
#include <ESP8266WiFi.h>
#include <EasyNTPClient.h>
#include <WiFiUdp.h>
#include <RTClib.h>
RTC_DS3231 rtc;
#include <FastLED.h>
//#include <Adafruit_Sensor.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <Adafruit_BMP280.h>
//Adafruit_BMP280 bmp(0x76);
//Adafruit_BMP280 bmp;
#include <BMP280_DEV.h>
BMP280_DEV bmp280;
#include <OneWire.h>
#include <DallasTemperature.h>
// сигнальный провод подключен к 5 пину на Arduino
#define ONE_WIRE_BUS_2 D5

// настроим библиотеку 1-Wire для связи с датчиком
OneWire oneWire_out(ONE_WIRE_BUS_2);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensors(&oneWire_out); //уличный

float temperature, pressure, altitude;
int UpdatePeriod = 12; //период в часах
int Period = UpdatePeriod * 3600; //вычисление секунд

const char *ssid = "";
const char *password = "";

#define LEDS_IN_SEGMENT 4     // задаём сколько у нас светодиодов в сегменте
#define DOTS_NUM 2            // задаём сколько у нас разделительных точек
#define NUM_LEDS (LEDS_IN_SEGMENT * 28 + DOTS_NUM) // вычисляем кол-во светодиодов
#define NUM_COLORS 16         // количество цветов
#define COLOR_CHANGE 0        // смена цвета ( 0 - никогда, 1 - раз в минуту, 2 - каждые десять минут, 3 - каждый час, 4 - каждые десять часов)
#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 - выключить)
/////////////////////////////////////////////
#define BRI_PIN A0 // PIN фоторезистора
WiFiUDP udp;
EasyNTPClient ntpClient(udp, "pool.ntp.org", (3 * 60 * 60));

#define COLOR_ORDER GRB  // тип ленты
#define LED_PIN 6  // пин дата от ленты
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; // переменная для освещенности
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);
  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);                                          // Зацикливаем
    }*/

  //  Serial.println("Обновление");
  syncTime();
  Wire.begin();
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS); // подключение ленты
  //  LEDS.setBrightness(55);
}
void BrightnessCheck() { // функция освещенности
  static uint32_t last_br = millis();
  if ((millis() - last_br) < 10000) return;
  last_br = millis();
  if (auto_bright) {                         // если включена адаптивная яркость
    if (millis() - bright_timer > 100) {     // каждые 100 мс
      bright_timer = millis();               // сбросить таймер
      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);
    Serial.print(".");
    if (trys > 10)
    {
      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 NoSignal() {
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 7));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 14));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM));
  }*/


void TempToArray() { // вывод температуры с датчика BMP280 на экран
  //  bmp.begin(0x76);
  //  int celsius = bmp.readTemperature(); // считываем датчик, датчик за часами, часы на стене, там температура чуть выше, корректировка минус 1
  //Serial.println (celsius);
  //  Serial.println (bmp.readTemperature());

  bmp280.getMeasurements(temperature, pressure, altitude);
  int celsius = temperature - 1; //датчик на стене, выше роста, корректировка минус 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() { // вывод давления на экран
  //  bmp.begin(0x76);
  //  int davlenie = bmp.readPressure();
  //  Serial.println (bmp.readPressure());
  //  Serial.println (davlenie);

  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 TempShow = true; // флаг для температуры в помещении
  static bool TempSShow = true; // флаг для температуры на улице
  static bool PressShow = 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(); // команда для включения светодиодов
  };
  }
 
Изменено:

maksland

★★★✩✩✩✩
13 Янв 2019
617
145
Omsk
я думал вы к этому проводки припаиваете...ESP8266_3_of_3_1024x1024.jpg
nodemcu для отладки конечно лучше но у меня такой мегаплаты нет
 

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
@ASM, Теперь часы 45 сек, температура 15 сек, тестирую без BMP. В мониторе порта фотодатчик реагирует на изменения но лента яркость не меняет.

@maksland, Примерно это + BMP280 , без бузера на ленте ws2812
 

Вложения

  • 136.2 KB Просмотры: 91
Изменено:

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Теперь часы 45 сек
ну тебе примерно так и надо? как утром писал)
прячь под спойлеры длинные тексты, а то ругаются на вас модеры)
на счет ленты интересно, у меня реагирует) задержку в 10 секунд сделал, чтобы не мерцало)
 
Изменено:

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
@ASM, если запитывать от 5в то я так понимаю нужно согласовать уровень выхода-> при питании модуля от 5в выходной сигнал тоже 5в, а логика ESP работает на 3,3в, можно спалить плату. Поэтому на выход модуля нужно ставить резисторный делитель напряжения чтобы выше 3,3 не поднималось

@kym13, Вообщем с яркостью разобрался уменьшил число в этом параметре <if ((millis() - last_br) < 100) return; // 10000> стала реагировать лента на фоторезистор но ступенчато в такт секундам(не критично, главное гасит ленту)
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@kym13, сам модуль можно запитывать от 5В. Датчики тоже можно, кроме некоторых, на которых указано что 3.3В.
@kym13, 100 означает 100мс, т.е. 10 раз в секунду)