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

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Получается что key всегда увеличивается и FastLED.show(); происходит 4 раза за цикл ?
да, после вызова функции идет ее показ, теоретически можно попробовать вынести ее в сами функции, а не в loop
Посмотри отметки времени
хорошо, попробую завтра
которая в промежуток между 0-5 секундой вызывается опять же с бешеной частотой.
в мониторе не часто выводит, вроде 2 раза, проверю
а есть ли разница? я думаю нет?
 

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
а есть ли разница? я думаю нет?
Разбери этот код, что бы было понятно все, сначала подумай что будет выведено, потом сравни с тем, что выведет монитор порта.
C++:
void setup() {
  Serial.begin(115200);
  bool f = false;
  int key = 0;
  if (f)
    TimeToArray(); Serial.println("-1111-"); key++;
  if (f)
  {
    TimeToArray(); Serial.println("-2222-"); key++;
  }
  f = true;
  if (f)
    TimeToArray(); Serial.println("-3333-"); key++;
  if (f)
  {
    TimeToArray(); Serial.println("-4444-"); key++;
  }
  Serial.println(key);
}

void loop() {

}

void TimeToArray()
{
  Serial.println("TimeToArray");
}
 

bort707

★★★★★★✩
21 Сен 2020
3,298
958
Разбери этот код, что бы было понятно все, сначала подумай что будет выведено, потом сравни с тем, что выведет монитор порта.
а, ну да :) не заметил :)
Я ж говорю, когда мы писали вместе, все было правильно , сравни :)
https://community.alexgyver.ru/thre...yx-svetodiodax-ws2812b.233/page-11#post-63021
 

ASM

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

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
Вообще мне цикл loop не нравится совсем.
Как сделал бы я, примерно:
C++:
void setup() {
  Serial.begin(115200);
}

void loop() {
uint32_t tmrall=millis()%14000/1000;
String out_str;
static String old_out_str;
switch (tmrall)
  {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    {
      out_str="Время:"+String(tmrall);
    }
    break;
    case 6:
    case 7:
    {
      out_str="Температура:"+String(tmrall);
    }
    break;
    case 8:
    case 9:
    {
      out_str="Улица:"+String(tmrall);
    }
    break;

    case 10:
    case 11:
    {
      out_str="Давление:"+String(tmrall);
    }
    break;
    case 12:
    case 13:
    {
      out_str="Что то еще:"+String(tmrall);
    }
    break;
   
  }

if (old_out_str!=out_str)
  {
    Serial.println(out_str);
    old_out_str=out_str;
  }


}
Тут я убрал условия if, но можно сделать и с ним, не проблема. Я захотел использовать switch, т.к. на мой взгляд это более наглядно и менее запутано
Далее. Я сделал изменение в 1 секунду ("/1000" в коде) , можно делить на 2000, тогда дискретность будет 2 секунды и меньше case писать. Тут не принципиально. если бы случаев было больше, я бы делал с if

Второй момент. Вывод на экран. я храню последнее выведенное значение, и вывожу только если оно изменилось. В случае с часами это будет затруднительно. Что можно сделать:
1) ни в коем случае не использовать фастлед.шоу внутри switch.
2) Перерисовывать матрицу с какой то частотой. Например 20 раз в секунду независимо от всего. как монитор, который всегда гоняет луч. Для этого в конце добавить что то типа:
if (millis()-last_show>50)
{
Fastled.show();
last_show=millis();
}
Этого вполне должно хватить для корректного вывода изображения на ленту. Можно сделать и 50 раз в сек, тогда 50 сменить на 20. Но чаще уже нет смысла.

Или все же завести переменную, которая будет отвечать за то, что состояние матрицы изменилось. Тогда так:
if (matrix_change)
{
Fastled.show();
matrix_change=false;
}

Второй способ более трудоёмкий, но позволит быстрее реагировать на изменения. Быстрее на 50 мс, для 20 кадров в сек.
Внутри после case следует делать соотв. вычисления времени, давления, температуры, прыщей и вообще чего требуется. и занести нужное в массив ленты. Опять же, температуру и давление можно вычислить только 1 раз в начале вывода, а далее ее только выводить. Вряд ли за 2 секунды она существенно изменится, но тут хозяин-барин.

В целом идея такая: ограничить частоту вывода матрицы до минимально необходимой, а свободное время потратить на что то полезное.
 
Изменено:
  • Лойс +1
Реакции: bort707 и ASM

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Переписал код с точками, останется отладить)
C++:
void Dots_on()  {
  leds[56] = ledColor;
  leds[57] = ledColor;
     static uint32_t last_dot = millis();
    if ((millis() - last_dot) > 1000);
    last_dot = millis();
    Dots_off();
}

void Dots_off()  {
  leds[56] = 0x000000;
  leds[57] = 0x000000;
}
Я захотел использовать switch, т.к. на мой взгляд это более наглядно и менее запутано
мне вообще не понравились эти switch и case, у bort вроде код на них, такая каша, как по мне и весь код в loop)
поэтому я и отказался от этого варианта
если подскажете хорошее описание, может разберусь и переделаю)

Разбери этот код
почему-то не выводит TimeToArray в первый раз)

появилась еще такая мысль, что, если millis преобразовать в целые секунды и уже проверять секунды, может корректнее будет обрабатываться?
C++:
uint32_t sec = millis() / 1000ul;
  int timeSecs = (sec % 3600ul) % 60ul;
вот такой вариант придумал, работает, но с точками бывают недочеты, как на видео)
В мониторе часы выводятся 3 раза, на старте 4 (из-за неточности в millis, это понятно), температуры по 2 раза и давление 1 раз, похоже надо в этом направлении и решать, т.к. тут ничего не меняется
C++:
Dot = second % 2; //из GetTime()

boolean Dots = true;
  if (Dot == 0) Dots = false; else Dots = true;
     if (Dots){leds[56] = ledColor;
               leds[57] = ledColor;}
         else {leds[56] = 0x000000;
               leds[57] = 0x000000;}
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
3,298
958
мне вообще не понравились эти switch и case, у bort вроде код на них, такая каша,
:)))
каша в коде не моя, я уже после руку приложил :)
моя задача была только убрать зависимость от числа диодов в сегменте. До меня тут все сегменты были прямо в тексте числами закодированы. А остальное я не трогал, общую логуику оригинального кода не менял.
Как говорится... "авторская орфорграфия и пунктуация сохранена"
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@bort707,если переделать на switch, то все функции с датчиками просто перенести в case?
Хотя можно же просто сделать ссылки на них добавив millis?)

поразобрался немного с синтаксисом, только пока непонятно, как будет работать вывод на экран)

на данный момент сделал так)
C++:
 byte mode;

    switch (mode){
        case 0:{
        uint32_t Timer_Time;
        Timer_Time = millis();
        if (millis() - Timer_Time <=5000)
        Timer_Time = millis();
        TimeToArray();
        break;
        }
        case 1:{
        uint32_t Timer_Temp;
        Timer_Temp = millis();
        if (millis() - Timer_Temp <=2000)
        TempToArray();
        break;
        }
        case 2:{
        uint32_t Timer_TempS;
        Timer_TempS = millis();
        if (millis() - Timer_TempS <=2000)
        TempStreetToArray();
        break;
        }
        case 3:{
        uint32_t Timer_Press;
        Timer_Press = millis();
        if (millis() - Timer_Press <=2000)
        PressToArray();
        break;
        }
        }
      FastLED.show();
точки работают идеально, но монитор забит функцией TimeToArray(); другие не включаются)

куда запихнуть?)
C++:
for (mode = 0; mode <=3; mode++)
 
Изменено:

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
У тебя тут несколько другой подход, чем предлагал я. Но тоже имеет право налево.
Но ошибка прежняя!
if (millis() - Timer_Time <=5000)
Timer_Time = millis(); <- это выполниться по условию!
TimeToArray(); <- это выполниться всегда!
а т.к. в начале стоит Timer_Time = millis(); то условие тут вообще не играет ни какой роли
 

kym13

★★★✩✩✩✩
14 Ноя 2020
716
118
min и max меняешь местами, посмотрел код, закомментировано немного не то)

в конце видео отчетливо заметны точки, которые передержались)

может тогда запихнуть вызов в функцию с датчиками или часами?
ASM
Спасибо
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@Старик Похабыч, так лучше?)
C++:
  byte mode;
  uint32_t Timer_Time,Timer_Temp,Timer_TempS,Timer_Press;
  for (mode = 0; mode <= 3; mode++) {          //выводим по порядку
    switch (mode) {
      case 0:
          Timer_Time = millis();               //сбросим счетчик
          if (millis() - Timer_Time <= 5000) { //выводим в течении 5 секунд
            TimeToArray();                     //показания часов
          }                
          break;
      case 1:
          Timer_Temp = millis();               //сбросим счетчик
          if (millis() - Timer_Temp <= 2000) { //выводим в течении 2 секунд
            TempToArray();                     //показания датчика
          }              
          break;
      case 2:
          Timer_TempS = millis();               //сбросим счетчик
          if (millis() - Timer_TempS <= 2000) { //выводим в течении 2 секунд
            TempStreetToArray();                //показания датчика
          }          
          break;
      case 3:
          Timer_Press = millis();               //сбросим счетчик
          if (millis() - Timer_Press <= 2000) { //выводим в течении 2 секунд
            PressToArray();                     //показания датчика
          }                
          break;
    }
  }
  FastLED.show();
@kym13, лучше просто лайкнуть мой ответ, чем так отвечать)
на прошлое сообщение, просто спасибо на форумах не принято отвечать, модеры ругаются)
 
Изменено:
  • Лойс +1
Реакции: kym13

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
Нет! Так ничем не лучше. Ты сперва берешь
Timer_Time = millis();
а потом его же с миллис сравнваешь. Какой смысл ? понятно что там разница будет всегда одна и та же. И меньше 5 сек.
 

ASM

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

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
На пальцах
Сейчас время 0 часов 0 мину 10 секунд
Timer_Time = millis(); // в Timer_Time 0 0 10
Следующая строка:
if (millis() - Timer_Time <= 5000) // миллис изменится 2-3-4 мс. И условие всегда, понимаешь, ВСЕГДА будет выполняться.
Цикл for там вообще не нужен. Ты очень сильно усложняешь код, его можно довести до ума в таком виде. но потребуется тонна ...земли и палок.

Поэтому.. ЗАБЫЛИ !

Берем за основу код из п. 332. и адаптируем его к твоим значениям. 6 секунд, 2, 22, и вырезаем то, что тебе НЕ надо
будет вот что:

C++:
void setup() {
  Serial.begin(115200);
}

void loop() {
  uint32_t tmrall = millis() % 12000 / 1000;
  static uint32_t tmrall_old = 10000;
  if (tmrall_old != tmrall)
  {
    tmrall_old = tmrall;

    if (tmrall < 6)
    {
      Serial.println("Заносим  время в матрицу");
      //TimeToArray();
    } else if (tmrall < 8)
    {
      Serial.println("Заносим  темепературу в матрицу");
      //TempToArray();
    }
    else if (tmrall < 10)
    {
      Serial.println("Заносим  уличную темепературу в матрицу");
      //TempStreetToArray();
    }
    else
    {
      Serial.println("Заносим  давление в матрицу");
      //PressToArray();
    }
  };

  /*
    if (tmrall_old != tmrall)
    {
      tmrall_old = tmrall;
      switch (tmrall)
      {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
          {
            Serial.println("Заносим  время в матрицу");
            //TimeToArray();
          }
          break;
        case 6:
        case 7:
          {
            Serial.println("Заносим  темепературу в матрицу");
            //TempToArray();
          }
          break;
        case 8:
        case 9:
          {
            Serial.println("Заносим  уличную темепературу в матрицу");
            //TempStreetToArray();
          }
          break;

        case 10:
        case 11:
          {
            Serial.println("Заносим  давление в матрицу");
            //PressToArray();
          }
          break;

      }

      Serial.println("Обновление!");
      // тут надо фастледшоу раз в секунду
    }*/
}
Тут 2 варианта и с if и с switch, какой хочешь такой и используй.
Тут все данные получаются и заносятся в матрицу раз в секунду, по единому таймеру. И соотв. отрисовываются они тоже раз в секунду.
А точки у тебя дурили видимо потому что время ты считал до 13 секунд, а реально использовал до 11, вот 2 секунды точки и не знали что делать.

Как всегда есть НО! Это только вывод на матрицу. А надо еще корректировать часы. Раз в секунду этого мало. Поэтому подумай как бы это сделать.
Подсказка. Вспони. что я говорил про 20 кадров в секунду. Для этого надо вывести фастлед.шоу из условия и наложить свое отдельное.
 
  • Лойс +1
Реакции: ASM

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
@Старик Похабыч, сделал по первому варианту
C++:
  uint32_t tmrall = millis() % 12000 / 1000;
  static uint32_t tmrall_old = 10000;
  if (tmrall_old != tmrall)
  {
    tmrall_old = tmrall;
    if (tmrall < 6)
    {
      TimeToArray(); FastLED.show();
    }
    else if (tmrall < 8)
    {
      TempToArray(); FastLED.show();
    }
    else if (tmrall < 10)
    {
      TempStreetToArray(); FastLED.show();
    }
    else
    {
      PressToArray(); FastLED.show();
    }
  };
вроде все работает, на часах с точкой все норм, только лог интересный)
Код:
13:08:53.676 -> 13:9:28
13:08:54.660 -> 13:9:29
13:08:55.692 -> 13:9:30
13:08:56.675 -> 13:9:31
13:08:57.658 -> 13:9:32
13:08:58.690 -> 13:9:33
13:09:00.174 -> 23
13:09:01.206 -> 23
13:09:01.672 -> 2
13:09:02.696 -> 2
13:09:04.198 -> 744
13:09:05.183 -> 744
 
Изменено:

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
А что в нем такого интересного ?
Все как положено. Т.к. каждое из значений запрашивается раз в секунду то и лог показывает эти значения раз в секунду. Не чаще. Время, температура внутри, уличная и давление. Далее по кругу должно быть.
Или еще что то странное и непонятное есть ?
 

ASM

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

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

★★★★★★★
14 Авг 2019
4,323
1,319
Москва
@ASM, Кнопки то есть какие ? Я думал время надо по кнопкам выставлять.. или не надо ? Я не во все вникал.

А интервалы можно сделать и чаще.
Вот смотри
uint32_t tmrall = millis() % 12000 / 1000;
тут 12000 это полный цикл в секундах. При получении остатка от него у нас будут числа от 0 до 11999. Далее делю на 1000 и получаю целое число в диапазоне от 0 до 11.
Тогда если делить на 2000 то то же будет целое число , но уже в другом диапазоне, от 0 до 5, но интервал будет 2 секунды на одно изменение числа.
Можно сделать чаще, делить на 500. Тогда будут числа от 0 до 23, изменение раз в секунду.
Далее если добавиь для температур и давлений для каждого свой флаг, сделать вместо
{
TempToArray(); FastLED.show();
}
что то типа:
C++:
void loop ()
{
static bool f1=true; // флаг для температуры в помещении
static bool f2=true;// флаг для температуры на улице
...
if (tmrall < 6)
    {
      TimeToArray(); [S]FastLED.show();[/S]
f1=true;
f2=true;
    }

...
 else if (tmrall < 8)
{
     if (f1)
    {
      TempToArray(); 
f1=false;
 }
...
    }
[CODE]

То частота запросов времени будет 2 раза в секунду, а запросы температур  будут только при 1-ом выводе и все. И давления туда же.

ДА! И только что заметил! Уберите на FastLED.show(); из каждого if  и поставьте в одном месте, в куске кода между 21 и 22 строкой в посте 342
 
  • Лойс +1
Реакции: ASM

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Кнопки то есть какие ?
кнопки есть, но корректировка времени происходит раз в несколько месяцев, добавляю не более 2 минут)
если код без delay, думаю можно будет в любой момент добавить, а не раз за цикл, как раньше)
Вывод на экран вынес, все работает.
С флагами подумаю...
 

bort707

★★★★★★✩
21 Сен 2020
3,298
958
Вот смотри
uint32_t tmrall = millis() % 12000 / 1000;
тут 12000 это полный цикл в секундах. При получении остатка от него у нас будут числа от 0 до 11999. Далее делю на 1000 и получаю целое число в диапазоне от 0 до 11.
развивая эту идею - можно по этому целому числу выбирать что показывать с помощью switch()
 

ASM

★★★★★✩✩
26 Окт 2018
1,918
422
Теперь при отвале датчика уличной температуры показывает нуль, ране было '-27 (-127)', надо будет заменить на черточки или может кто предложит иной вариант символов?) Будет время, доберусь)

Библиотека была другая, сейчас на microDS18B20, возможно и из-за этого разный ответ получился)

Как реализовать данный момент и возможно ли?
if (!sensors.requestTemp()) Serial.println("No signal"); //если нет ответа с датчика, обрыв провода
 
Изменено: