Временные интервалы

Тема в разделе "Arduino & Shields", создана пользователем r0c, 17 фев 2022.

  1. r0c

    r0c Гик

    Здравствуйте!
    Прошу подсказки.
    Есть устройство- выносной дисплей(индикатор состояния) для котла отопления. Они общаютcя между собой по UART.
    индикатор шлет запрос статуса готовности котла- в ответ(через пол секунды) получает "OK"- готов к приему команды. Затем отправляется запрос температуры- в ответ(через пол секунды) приходит значение температуры и отображается на дисплее. Аналогично с напряжением котла, оборотами насоса и некоторыми другими параметрами( может код ошибки прислать ).
    Нет необходимости каждую секунду запрашивать температуру- она все равно изменяется медленно( и непрерывные запросы приводят котел в ступор), а вот давление воды и напряжение хотелось бу узнавать почаще.
    Я делал отправку команд:
    Код (C++):
     if (millis() - temperatureTimer >= 30000) { // таймер на 30  сек)
    temperatureTimer = millis();              // сброс таймера
    Serial.print("Temp?\r\n");
    по одиновчке все работает корректно и без проблем.
    Но если запрос температуры- раз в 30 сек., давления- раз в 4,5 секунд, напряжения- раз в 2,7 секунд и т.д.- возникает проблема.
    Суть проблемы- какие бы цифры таймера не ставил, когда нибудь запросы совпадают по времени , в результате в UART каша и на дисплее путаница.
    Как сделать так, что бы запросы( у четом задержки ответа котла) не пересекались по времени? Заранее спасибо.
     
  2. b707

    b707 Гуру

    не посылать нового запроса, пока не получен ответ от предыдущего.
    Для этого завести переменную-флаг, запрещающую посылку новых запросов. Когда отслылаете запрос - выставляете флаг. Каждый следующий запрос сначала проверяет флаг, если выставлен - ждет
     
    r0c нравится это.
  3. SergeiL

    SergeiL Оракул Модератор

    Так сделайте "таймер millis()" на 1 секунду, а внутри счетчик до 59, с инкрементом в конце блока таймера, достиг 60 - сбрасываете его на 0.
    Дальше расписываете на какой секунде минуты, что запрашивать.
    Проверяете счетчик , если он равен 0, 5, 10, 15, и т.д. до 55 - шлете запрос напряжения.
    Если равен 7, 17, 27 и т.д. шлете запрос давления.
    Если равен 29, 59 - шлете запрос температуры.
    Это как один, из самых простых вариантов. ;)
     
    r0c нравится это.
  4. parovoZZ

    parovoZZ Гуру

    а в чём сакральный смысл в разных интервалах? Почему нельзя всё опрашивать раз в 5 секунд?
     
  5. r0c

    r0c Гик

    спасибо за интересные идеи.
    может оказаться, что уже минуту назад аварийная ситуация, если вот так в порядке очереди не торопясь опрашивать по каждому параметру.
    Поэтому- критичные параметры почти онлайн, не критичные- изредка, для справочной информации
     
  6. r0c

    r0c Гик

    так переменная счетчика равна 5 (ну или 15, 25) в течении интервала времени 1000 милисекунд, за это время десятки раз выполнится условие сравнения и десятки раз уйдет запрос в uart
    Код (C++):
     if (T= 5||10||15) Serial.print("Temp?\r\n")
     
  7. Рокки1945

    Рокки1945 Гуру

    Вы что не знаете что такой прерывание по сравнению или переполнению таймера?
    В обработчике прерывания инкрементируете счётчик (переменная) -
    - когда счётчик стал равен 27 (если таймер сконфигурирован на 100 мс) - считываете давление в основном цикле отправляете на дисплей -
    - когда счётчик стал равен 50 - считывает ещё что-нибудь - потом обнуляете его и так по кругу.
     
  8. SergeiL

    SergeiL Оракул Модератор

    ну что вы написали??? где вы такому условию в if научились?
    Вот разбирайтесь:
    Код (C++):

    void setup() {
      Serial.begin(115200);
      Serial.println("Start!");
    }

    void loop()
    {
      static uint32_t prev_timer = 0;
      static uint8_t  sec_counter = 0;
      uint32_t        cur_timer = millis();

      if (cur_timer - prev_timer >= 1000)  // таймер на 1  сек)
      {
        prev_timer = cur_timer;
        Serial.print("Counter = ");
        Serial.println(sec_counter);
        switch (sec_counter)
        {
          case 0:
          case 5:
          case 10:
          case 15:
          case 20:
          case 25:
          case 30:
          case 35:
          case 40:
          case 45:
          case 50:
          case 55:
            Serial.println("Case 5 sec");
            break;

          case 3:
          case 13:
          case 23:
          case 33:
          case 43:
          case 53:
            Serial.println("Case 10 sec");
            break;
          case 27:
          case 57:
            Serial.println("Case 30 sec");
            break;

        }
        sec_counter++;
        if (sec_counter == 60)
          sec_counter = 0;
      }
    }
     
    Когда разберетесь, можно будет упростить и убрать siwtch().
    Пока так нагляднее.
     
    r0c нравится это.
  9. parovoZZ

    parovoZZ Гуру

    Не занимайтесь ерундой. Опрашивай поочередно все параметры через 5 секунд. При аварии котёл сам все сделает.
     
  10. r0c

    r0c Гик

    Разумеется можно. Штатного дисплея вообще не предусмотрено. Но хочется красиво , понятно и удобно для человека. Просто складывается впечатление, что все эти железки производитель выпускает вообще не для обычного человека.
     
  11. parovoZZ

    parovoZZ Гуру

    У меня на котле тоже нет дисплея. Не парит абсолютно. За последние лет 8 в ошибку падал всего один раз: когда вырубили газ.
     
  12. Igor68

    Igor68 Гуру

    Прошу прощения! На котле так же Ваша прошивка, или заводская?
     
  13. r0c

    r0c Гик

    заводская. Какой то ноунейм котел. Две лампочки-зеленя и красная. все хорошо-все плохо. 5 миганий красной- плохо насосу, 3 долгих, 3 коротких миганий красной- плохо датчику еще какому то. А теперь на дисплее все видно.