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

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

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




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

IMG_20180907_120755.jpg


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

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

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

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

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

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

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

Комментарии

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
скорее всего никогда не сработает
наоборот, у меня сработало, вывод в порт происходил, но по одному разу, изначально делал >=, но не прижилось)
p.s. мне тут программисты посоветовали использовать Thread.h, но что-то я думаю функции тут будут накладываться друг на друга)
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
@bort707,
C++:
    if (millis() - TTime <= 5000)
      TimeToArray();
    if (millis() - TTime <= 7000 && TTime > 5000)
      TempToArray(); 
    if (millis() - TTime <= 9000 && TTime > 7000)
      TempStreetToArray();
    if (millis() - TTime <= 11000 && TTime > 9000)
      PressToArray();
    if (millis() - TTime <= 13000 && TTime > 11000) 
      TTime = millis();
так правильнее?)
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
@bort707,
C++:
    if ((millis() - Timer <= 5000) && (millis() - Timer > 0))
      TimeToArray();
    if ((millis() - Timer <= 7000) && (millis() - Timer > 5000))
      TempToArray(); 
    if ((millis() - Timer <= 9000) && (millis() - Timer > 7000))
      TempStreetToArray();
    if ((millis() - Timer <= 11000) && (millis() - Timer > 9000))
      PressToArray();
    if ((millis() - Timer <= 13000) && (millis() - Timer > 11000))
      Timer = millis();
не работает цикл, в мониторе только TimeToArray(); много-много раз)
 

bort707

★★★★★★✩
21 Сен 2020
2,895
859
не работает цикл, в мониторе только TimeToArray(); много-много раз)
в этом условии ошибок не вижу, ищите в другом месте.
Скорее всего у вас переменная Timer где-то еще сбрасывается в ноль.
Вы ее как описали? Она должна быть или глобальная, или статическая, иначе работать не будет
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
unsigned long Timer;
Поправил один момент, остался кусок от другого примера, итог цикла:
7:21:55.291 -> 17:20:48
.....
17:22:00.793 -> 23
.....
17:22:02.330 -> -1
.....
17:22:04.793 -> 769
.....
17:22:06.375 -> 17:20:59
вроде так) сейчас на FastLED перекину...

Было 18870, стало 18976 байт, думал много меньше памяти станет)
Ну и мерцать стали диоды, т.к. чаще стали идти обращения)
Каким образом уменьшить эти обращения?

C++:
//Скетч использует 18870 байт (61%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 1010 байт (49%) динамической памяти, оставляя 1038 байт для локальных переменных. Максимум: 2048 байт.
//Скетч использует 18976 байт (61%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 1014 байт (49%) динамической памяти, оставляя 1034 байт для локальных переменных. Максимум: 2048 байт.
#include <DS3232RTC.h>
#include <FastLED.h>
#include <microDS18B20.h>
MicroDS18B20 sensors(2);
#include <iarduino_Pressure_BMP.h>
iarduino_Pressure_BMP sensor(0x76); //Барометр

#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 200        // максимальная яркость (0 - 255)
#define min_bright 5          // минимальная яркость (0 - 255)

#define COLOR_ORDER GRB  // Тип ленты
#define LED_PIN 6  // Пин дата от ленты
#define MIN_PIN 5  // Пин минутной кнопки
#define HUR_PIN 4  // Пин часовой кнопки
#define BRI_PIN A0 // PIN фоторезистора

CRGB leds[NUM_LEDS]; // Define LEDs strip

uint8_t  digits[] = {
  0b00111111,     // Digit 0
  0b00100001,     // Digit 1
  0b01110110,     // Digit 2
  0b01110011,     // Digit 3
  0b01101001,     // Digit 4
  0b01011011,     // Digit 5
  0b01011111,     // Digit 6
  0b00110001,     // Digit 7
  0b01111111,     // Digit 8
  0b01111011,     // Digit 9
  0b01111000,     // Digit * градус  10
  0b00011110,     // Digit C         11
  0b01111100,     // Digit P         12
  0b00000000,     // Blank           13
  0b01000000      // Digit -         14
};

bool Dot = true;  //переменная для точек
//bool TempShow = true;  //переменная для температуры
//bool PressShow = true; //переменная для давления
int last_digit = 0;
byte set_light;
byte brightness;
unsigned long Timer;

//управление цветом
//int ledColor = 0x00FFFF; // Color used (in hex)
long ledColor = CRGB::Blue; // Color used (in hex)
//массив цветов, для рандом при включенном режиме cylon(); ledColor =  ColorTable[random(16)];
long 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(9600);
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS);
  pinMode(MIN_PIN, INPUT_PULLUP); // Define Minutes adjust button pin
  pinMode(HUR_PIN, INPUT_PULLUP); // Define Hours adjust button pin

  pinMode(A3, OUTPUT); //контакт GND барометра
  digitalWrite(A3, LOW);//подача земли на барометр

  pinMode(9, OUTPUT); //контакт VCC датчика осв
  digitalWrite(9, HIGH);//подача питания на датчик осв
}

int GetTime() {
  tmElements_t Now;
  RTC.read(Now);
  int hour = Now.Hour;
  int minute = Now.Minute;
  int second = Now.Second;
  Serial.print(hour);   Serial.print(":");  // Вывод часов
  Serial.print(minute); Serial.print(":");  // Вывод минут
  Serial.print(second); Serial.println(""); // Вывод секунд
  Dot = second % 2;
  return (hour * 100 + minute);
};

int GetSecond() {
  tmElements_t Now;
  RTC.read(Now);
  int second = Now.Second;
  return (second);
};

void BrightnessCheck() {  // Установка яркости по датчику освещенности
  int sensor_value = analogRead(BRI_PIN);
  if (set_light == 0) brightness = map(sensor_value, 1023, 0, min_bright, max_bright);
  else brightness = set_light * 10;
  LEDS.setBrightness(brightness);
}

void TimeToArray()
{
  int Now = GetTime(); // Получаем время
  Dots(Dot);
  for (int i = 1; i <= 4; i++) {
    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[13], cursor); //Если впереди ноль, то выключаем его
    else
      Digit(digits[digit], cursor);                     //Иначе показываем символ
    if ( i == COLOR_CHANGE) {                           //Как часто менять цвет
      if (digit != last_digit) {
        ledColor =  ColorTable[random(NUM_COLORS)];    // Случайный цвет из таблицы
      }
      last_digit = digit;
    }
    Now /= 10;
  };
};

void TempStreetToArray() {
  sensors.requestTemp();
  int celsius = sensors.getTemp();
  Serial.println (celsius);
  Dots(0);
  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[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM)); //Если впереди ноль, то выключаем его
  else
    Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - 2));
  if (sensors.getTemp() <= -1)Digit(digits[14], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM));//если < или = -1, то показываем -
  else
    Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); //иначе выключаем
};

void TempToArray() {
  sensor.begin();
  int celsius = sensor.temperature - 1; // датчик за часами, часы на стене, там температура чуть выше
  Serial.println (celsius);
  Dots(0);
  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[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM)); //Если впереди ноль, то выключаем его
  else
    Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); //отключаем
};

void PressToArray() {
  sensor.begin();
  int davlenie = sensor.pressure;
  Serial.println (davlenie);
  Dots(0);
  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[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); //отключаем
};

void TimeAdjust() {
  int buttonH = digitalRead(HUR_PIN);
  int buttonM = digitalRead(MIN_PIN);
  if (buttonH == LOW || buttonM == LOW) {
    delay(200);
    tmElements_t Now;
    RTC.read(Now);
    int hour = Now.Hour;
    int minutes = Now.Minute;
    int second = Now.Second;
    if (buttonH == LOW) {
      if (Now.Hour == 23) {
        Now.Hour = 0;
      }
      else {
        Now.Hour += 1;
      };
    } else {
      if (Now.Minute == 59) {
        Now.Minute = 0;
      }
      else {
        Now.Minute += 1;
      };
    };
    RTC.write(Now);
  }
}

void Dots (boolean Dot_On) {
  leds[56] = (Dot_On) ? ledColor : 0;
  leds[57] = (Dot_On) ? ledColor : 0;
}

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 : 0;
      cursor ++;
    }
  }
}

void loop()
{
  BrightnessCheck();
  TimeAdjust();
  /*
  TimeToArray();FastLED.show();delay(1000);
  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);
  */
    if ((millis() - Timer <= 5000) && (millis() - Timer > 0))
      TimeToArray();FastLED.show();
    if ((millis() - Timer <= 7000) && (millis() - Timer > 5000))
      TempToArray();FastLED.show(); 
    if ((millis() - Timer <= 9000) && (millis() - Timer > 7000))
      TempStreetToArray();FastLED.show();
    if ((millis() - Timer <= 11000) && (millis() - Timer > 9000))
      PressToArray();FastLED.show();
    if ((millis() - Timer <= 13000) && (millis() - Timer > 11000))
      Timer = millis();
}
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
2,895
859
Ну и мерцать стали диоды, т.к. чаще стали идти обращения)
ну еще бы, вы же теперь при каждом проходе картинку на матрице обновляете, даже если она не изменилась
Каким образом уменьшить эти обращения?
используй флаги
C++:
void loop()
{
  static byte key =0;
  BrightnessCheck();
  TimeAdjust();
    if ((millis() - Timer <= 5000) && (key ==0))
      TimeToArray();FastLED.show();key++;
    if ((millis() - Timer <= 7000) && (key ==1))
      TempToArray();FastLED.show();key++;
   // ....и так далее
  
  // в последнем условии - возвращаем key на ноль
    
}
 
  • Лойс +1
Реакции: ASM

maksland

★★★✩✩✩✩
13 Янв 2019
458
105
Omsk
у меня прошивка 1.6 работать не хочет - светодиоды не горят, прошиваю 1.5 - работает
фьюзы не надо менять для 1.6 ?
 
Изменено:

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
@maksland, что-то не понятно, о чем речь... Clock_1.7 есть...

@bort707, спасибо, поставил на флаги, вроде норм получилось)
Монитор:
13:07:51.533 -> 13:6:40
13:07:53.111 -> 13:6:42
13:07:54.663 -> 13:6:43
13:07:56.258 -> 13:6:45
13:07:58.327 -> 23
13:07:59.890 -> -7
13:08:01.999 -> 765
13:08:05.135 -> 13:6:54
13:08:06.688 -> 13:6:55
13:08:08.252 -> 13:6:57
13:08:10.379 -> 23
13:08:11.926 -> -7
13:08:14.040 -> 765
Дополнительно подправил вывод отрицательной температуры уличного датчика.
Теперь появился баг с индикацией точек секунд, не мигают каждую секунду)
C++:
#include <DS3232RTC.h>
#include <FastLED.h>
#include <microDS18B20.h>
MicroDS18B20 sensors(2);
#include <iarduino_Pressure_BMP.h>
iarduino_Pressure_BMP sensor(0x76); //Барометр

#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 200        // максимальная яркость (0 - 255)
#define min_bright 10         // минимальная яркость (0 - 255)
#define bright_constant 1000  // константа усиления от внешнего света (0 - 1023), чем МЕНЬШЕ константа, тем "резче" будет прибавляться яркость
#define coef 0.4              // коэффициент фильтра (0.0 - 1.0), чем больше - тем медленнее меняется яркость
int new_bright, new_bright_f;
#define auto_bright 1         // автоматическая подстройка яркости от уровня внешнего освещения (1 - включить, 0 - выключить)
unsigned long bright_timer, off_timer;


#define COLOR_ORDER GRB  // Тип ленты
#define LED_PIN 6  // Пин дата от ленты
#define MIN_PIN 5  // Пин минутной кнопки
#define HUR_PIN 4  // Пин часовой кнопки
#define BRI_PIN A0 // PIN фоторезистора

CRGB leds[NUM_LEDS]; // Define LEDs strip

uint8_t  digits[] = {
  0b00111111,     // Digit 0
  0b00100001,     // Digit 1
  0b01110110,     // Digit 2
  0b01110011,     // Digit 3
  0b01101001,     // Digit 4
  0b01011011,     // Digit 5
  0b01011111,     // Digit 6
  0b00110001,     // Digit 7
  0b01111111,     // Digit 8
  0b01111011,     // Digit 9
  0b01111000,     // Digit * градус  10
  0b00011110,     // Digit C         11
  0b01111100,     // Digit P         12
  0b00000000,     // Blank           13
  0b01000000      // Digit -         14
};

bool Dot = true;  //переменная для точек
//bool TempShow = true;  //переменная для температуры
//bool PressShow = true; //переменная для давления
int last_digit = 0;
byte set_light;
byte brightness;
unsigned long Timer;

//управление цветом
//int ledColor = 0x00FFFF; // Color used (in hex)
long ledColor = CRGB::Blue; // Color used (in hex)
//массив цветов, для рандом при включенном режиме cylon(); ledColor =  ColorTable[random(16)];
long 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(9600);
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS);
  pinMode(MIN_PIN, INPUT_PULLUP); // Define Minutes adjust button pin
  pinMode(HUR_PIN, INPUT_PULLUP); // Define Hours adjust button pin

  pinMode(A3, OUTPUT); //контакт GND барометра
  digitalWrite(A3, LOW);//подача земли на барометр

  pinMode(9, OUTPUT); //контакт VCC датчика осв
  digitalWrite(9, HIGH);//подача питания на датчик осв
}

int GetTime() {
  tmElements_t Now;
  RTC.read(Now);
  int hour = Now.Hour;
  int minute = Now.Minute;
  int second = Now.Second;
  Serial.print(hour);   Serial.print(":");  // Вывод часов
  Serial.print(minute); Serial.print(":");  // Вывод минут
  Serial.print(second); Serial.println(""); // Вывод секунд
  Dot = second % 2;
  return (hour * 100 + minute);
};

void BrightnessCheck() {
  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 TimeToArray(){
  int Now = GetTime(); // Получаем время
  Dots(Dot);
  for (int i = 1; i <= 4; i++) {
    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[13], cursor); //Если впереди ноль, то выключаем его
    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 (boolean Dot_On) {
  leds[56] = (Dot_On) ? ledColor : 0;
  leds[57] = (Dot_On) ? ledColor : 0;
}

void TempStreetToArray() {
  sensors.requestTemp();
  int celsius = sensors.getTemp();
  Serial.println (celsius);
  Dots(0);
  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[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM)); //Если впереди ноль, то выключаем его
  else
    Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - 2));
  if (sensors.getTemp() <= -1)Digit(digits[14], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM));//если < или = -1, то показываем -
  else
    Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); //иначе выключаем
};

void TempToArray() {
  sensor.begin();
  int celsius = sensor.temperature - 1; // датчик за часами, часы на стене, там температура чуть выше
  Serial.println (celsius);
  Dots(0);
  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[13], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM)); //Если впереди ноль, то выключаем его
  else
    Digit(digits[digit], (NUM_LEDS - LEDS_IN_SEGMENT * 21 - DOTS_NUM));
  Digit(digits[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); //отключаем
};

void PressToArray() {
  sensor.begin();
  int davlenie = sensor.pressure;
  Serial.println (davlenie);
  Dots(0);
  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[13], (NUM_LEDS - LEDS_IN_SEGMENT * 28 - DOTS_NUM)); //отключаем
};

void TimeAdjust() {
  int buttonH = digitalRead(HUR_PIN);
  int buttonM = digitalRead(MIN_PIN);
  if (buttonH == LOW || buttonM == LOW) {
    delay(200);
    tmElements_t Now;
    RTC.read(Now);
    int hour = Now.Hour;
    int minutes = Now.Minute;
    int second = Now.Second;
    if (buttonH == LOW) {
      if (Now.Hour == 23) {
        Now.Hour = 0;
      }
      else {
        Now.Hour += 1;
      };
    } else {
      if (Now.Minute == 59) {
        Now.Minute = 0;
      }
      else {
        Now.Minute += 1;
      };
    };
    RTC.write(Now);
  }
}

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 : 0;
      cursor ++;
    }
  }
}

void loop(){
  static byte key =0;
  BrightnessCheck();
  TimeAdjust();

    if ((millis() - Timer <= 5000) && (key ==0))
      TimeToArray();FastLED.show();key++;
    if ((millis() - Timer <= 7000) && (millis() - Timer > 5000)&& (key ==1))
      TempToArray();FastLED.show();key++;
    if ((millis() - Timer <= 9000) && (millis() - Timer > 7000)&& (key ==2))
      TempStreetToArray();FastLED.show();key++;
    if ((millis() - Timer <= 11000) && (millis() - Timer > 9000)&& (key ==3))
      PressToArray();FastLED.show();key++;
   if ((millis() - Timer <= 13000) && (millis() - Timer > 11000)&& (key ==4))
      Timer = millis();key==0;
}
 
Изменено:

maksland

★★★✩✩✩✩
13 Янв 2019
458
105
Omsk
У меня плата под 1 датчик разведена .
Увидел что можно отключать второй, буду прошивать
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
Пора готовить проект под НГ))
сделал разноцветными диоды
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++) {
      leds[cursor] = (digit & mask) ? ledColor : 0;
      ledColor =  ColorTable[random(NUM_COLORS)];    // Случайный цвет из таблицы
      cursor ++;
    }
  }
}
единственный минус, соседние диоды могут совпадать, выглядит не красиво и нет того постоянного мерцания, местами происходит смена цвета, но хочется с периодичностью)
можно попробовать запустить
C++:
 CRGB ledColor  = CHSV(random(0, 255), 255, 255);
только как правильно описать эту строку?)
Также есть мысль брать цвета последовательно из таблицы, тогда должна получиться красивая гирлянда, что-то вроде
C++:
 ledColor =  ColorTable[sequence (NUM_COLORS)];
но sequence похоже не заложена в библиотеку)

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

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

★★★★★★★
14 Авг 2019
4,184
1,278
Москва
Это вполне корректная строка:
CRGB ledColor = CHSV(random(0, 255), 255, 255);
В чем сомнения ?
Только значение H будет выдаваться в диапазоне 0-254, т.к. значение 255 не выходит в диапазон.
 

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

★★★★★★★
14 Авг 2019
4,184
1,278
Москва
Я в одном проекте храню 2 значения случайного цвета в RGB и HSV формате.
C++:
GlobalColor_HSV = CHSV(random(0, 256), 255, 255);
GlobalColor_RGB = GlobalColor_HSV;
А потом использую его где надо:
for (uint8_t i = 0; i < NUM_LEDS; i++) leds[i] = GlobalColor_RGB ;
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
@Старик Похабыч,
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++) {
      leds[cursor] = (digit & mask) ? ledColor : 0;
      leds[i] = CHSV(random(0, 256), 255, 255);
//      ledColor =  ColorTable[random(NUM_COLORS)];    // Случайный цвет из таблицы
      cursor ++;
    }
  }
}
работает гирлянда только в первом сегменте первой цифры, но даже в нем и то повторяются соседние цвета, в 4 то диодах)
похоже надо статично задавать несколько ярких насыщенных цветов и выводить последовательно в цепочку)
for (uint8_t k = 0; k < NUM_COLORS-1; k++)ledColor = ColorTable[k]; как тут будет правильнее? минус 1 сделал чтобы уменьшить число и не вылететь за границы)
 

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

★★★★★★★
14 Авг 2019
4,184
1,278
Москва
Задача что бы цвет был совсем разный ? Ну вот смотри, цвет 0 и цвет 255 в HSV будет практически один и тот же. Тут надо правильно поставить задачу, а их тут 2: 1) определить случайный цвет не равный соседнем, 2) понять какой цвет соседний.
Если взять все цвета HSV максимальной чистоты и яркости, то их будет 256. Допустим нас устроитразнсть в 16 между соседними цветами. Тогда у нас будет диапазон в 16 цветов (всего то!) Если брать рандом (0,16)*16-8, то получим средний цвет. Так же надо запоминать цвет который уже выпал и в сл. раз можно а) кидать рандом пока он равен предыдущему, это может быть долго, а может быть коротко. зато просто реализуется. б) Выбрать рандом от 0 до 15 и пропускать предыущий номер. Реализуется несколько сложнее, но время затраченное на поиск нового цвета стабильнее.
Ну и нужен алгоритм проверки цветов пред. диодов. Елси идти с верхнего левого угла, сначала по строке, потом на строку вниз, то проверять надо будет максимум по 3 светодиода, для текущего это левый, верхний и левый верхний по диагонали. Да, если один из тех светодиодов потушен, то его цвет не учитывать. Ну и "тухлые" светодиоды пропускать конечно. Я как то так вижу. Тут нужна будет процедура получения номера свтодиода по координатам или получение цвета по координатам.
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
@Старик Похабыч, понял, много сложностей получается.
А если реализовать последнюю идею, только не random брать из таблицы, а значения по порядку, цвета потом подберу, можно реализовать без много кода? аналогично
C++:
for (uint8_t k = 0; k < NUM_COLORS-1; k++)ledColor = ColorTable[k];
тут же идет выборка значений из таблицы от 0 до 15
 

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

★★★★★★★
14 Авг 2019
4,184
1,278
Москва
Конечно можно! только цикл я бы делал не так, ведь не известно сколько точек надо зажечь для буквы ? тогда надо просто иметь статическую или глобальную переменную с номером цвета из таблицы и ее при каждом использовании увеличивать на 1 вот по такой формуле : номер=(номер+1)%16; будет бесконечная смена чисел от 0 до 15

Добавлено часом позже...
Кстати.. еще один аналогичный способ, но без таблицы и с рандомом.
H=random(0,256) - начальное значение цвета
и далее
H=(H+random(16,240))%256;
По идее должен давать случайный цвет на расстоянии не менее 16 единиц от предыдущего , при этом не будет выходить за диапазон 0-255
 
Изменено:
  • Лойс +1
Реакции: ASM

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
@Старик Похабыч,
C++:
long randomcolor = (random(0, 256));
     randomcolor = (randomcolor + random (16, 240))%256;
CHSV ledColor = CHSV (randomcolor, 255, 255);
вроде так мысли изложил, но код не работает, запускается стартовый синий)
 

bort707

★★★★★★✩
21 Сен 2020
2,895
859
@ASM, а зачем randomcolor имеет тип long., если значения у него в диапазоне 0-255?
так не проще:
C++:
byte randomcolor = (random(0, 256));
     randomcolor = randomcolor + random (16, 240);
а что касается того, почему не срабатывает - видимо где-то еще есть ошибки.
Покажите весь код, что ли...
 

ASM

★★★★✩✩✩
26 Окт 2018
1,507
293
long, это остаток от переборки, перебирал различные варианты, компилятор все ругался на long int)) Так же пытался проверить в сериал ledColor, но он ругался на формат CHSV)) В сериал от randomcolor сыплются множество значений, там все ровно, похоже все застряло в
C++:
CHSV  ledColor = CHSV (randomcolor, 255, 255);
вечером поэкспериментирую с CHSV, может какие специфичные типы нужны)