Как бы красиво расставить приоритеты?

78125

✩✩✩✩✩✩✩
1 Дек 2019
76
2
Добрый день.
UNO с Modbus Master опрашивает датчики и раздает команды нескольким устройствам.
Все телеграммы идут одна за другой, те с равным приоритетом.
Мне необходимо как то запрограммировать очередь, чтобы одни датчики опрашивались часто, хоть каждый первый/второй запрос.
А неважные данные обновлялись редко, но скажем гарантированно не реже раз в 10 секунд.
Есть еще команды, которые можно выполнять однократно и после отправки - вообще не выполнять телеграмму до следующего изменения данных.
C++:
#include <ModbusRtu.h>
Modbus master(0,Serial,4); // 0 this is master
modbus_t telegram[9]; // посылка данных для modbus
unsigned long u32wait; //таймер modbus
uint8_t u8query=0; //pointer to message query
byte u8state;

void modbussend() {
  switch ( u8state ) {
    case 0:
      if (millis() > u32wait) u8state++; // wait state
      break;
    case 1:
      master.query( telegram[u8query] ); // send query (only once)
      u8state++;
      u8query++; //номер запроса телеграммы
      if (u8query > 8) u8query = 0;
      break;
    case 2:
      master.poll(); // check incoming messages
      if (master.getState() == COM_IDLE) {
                                          u8state = 0;
                                          u32wait = millis() + 10;
                                         }
      break;
  }
}

void setup()
{
  //rs485
  Serial.begin( 19200 ); // baud-rate at 19200
  master.start();
  master.setTimeOut(20); // таймаут мастера
  Serial.println("Start");

  //тееграммы
  // telegram 0: write registers
      telegram[0].u8id = 2;
      telegram[0].u8fct = 6; // function code (this one is registers write)
      telegram[0].u16RegAdd = 0; // start address in slave
      telegram[0].u16CoilsNo = 1; // number of elements (coils or registers) to write
      telegram[0].au16reg = &motorSpeed; // pointer to a memory array in the Arduino

  // telegram : read registers
      telegram[1].u8id = 1;
      telegram[1].u8fct = 3; // function code (this one is registers read)
      telegram[1].u16RegAdd = 3328; // = 0D00 start address in slave
      telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read
      telegram[1].au16reg = busread; // pointer to a memory array in the Arduino
    
    //и тд
    
      telegram[8].u8id = 3;
      telegram[8].u8fct = 4; // function code (this one is registers read)
      telegram[8].u16RegAdd = 11; // start address in slave
      telegram[8].u16CoilsNo = 1; // number of elements (coils or registers) to read
      telegram[8].au16reg = &GetSize; // pointer to a memory array in the Arduino
}

void loop() {
  modbussend();
}
 

rkit

★★★✩✩✩✩
5 Фев 2021
510
127
Ну и напиши какие тебе нужно интервалы цифрами, не придумывай сложностей на ровном месте.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,975
634
45
Самое простое что то типа такого (псевдокод):
C++:
void do_job() {
    // задача1
    if (время с последнего запуска задачи1 больше N) {
        // делаем задачу1
        return;
    }

    // задача2
    if (время с последнего запуска задачи2 больше N) {
        // делаем задачу2
        return;
    }
    
    // задача3
    if (время с последнего запуска задачи3 больше N) {
        // делаем задачу3
        return;
    }
}
Ну и в основном цикле вызываем эту функцию.
 

78125

✩✩✩✩✩✩✩
1 Дек 2019
76
2
Получилось как то так:
Я организовал выбор задачи от приоритета, сначала редкие чтобы их частые не забили.
Все верно?
Почему то компилятор выдает ворнинг.
C++:
unsigned int QuerySelect() {
                    
                    if (millis()-TelegramTimer[1]>5000) {TelegramTimer[1] = millis(); return 1;}
                    if (millis()-TelegramTimer[2]>5000) {TelegramTimer[2] = millis(); return 2;}
                    if (millis()-TelegramTimer[3]>5000) {TelegramTimer[3] = millis(); return 3;}
                    if (millis()-TelegramTimer[4]>1000) {TelegramTimer[4] = millis(); return 4;}
                    if (millis()-TelegramTimer[5]>1000) {TelegramTimer[5] = millis(); return 5;}
                    if (millis()-TelegramTimer[6]>1000) {TelegramTimer[6] = millis(); return 6;}
                    if (millis()-TelegramTimer[7]>1000) {TelegramTimer[7] = millis(); return 7;}
                    if (millis()-TelegramTimer[8]>50) {TelegramTimer[8] = millis(); return 8;}
                    if (millis()-TelegramTimer[0]>50) {TelegramTimer[0] = millis(); return 0;}
                     }

void modbussend() {
  switch ( u8state ) {
    case 0:
      if (millis() > u32wait) u8state++; // wait state
      break;
    case 1:
      u8query = QuerySelect();
      master.query( telegram[u8query]); // send query (only once)
      u8state++;
      break;
    case 2:
      master.poll(); // check incoming messages
      if (master.getState() == COM_IDLE) {
                                          u8state = 0;
                                          u32wait = millis() + 10;
                                         }
      break;
  }
}
Z:\arduino\Speed_Main_ETB05\Speed_Main.ino: In function 'unsigned int QuerySelect()':
Z:\arduino\Speed_Main_ETB05\Speed_Main.ino:125:22: warning: control reaches end of non-void function [-Wreturn-type]
}
^
 

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

★★★★★★★
14 Авг 2019
4,272
1,303
Москва
@78125,
Я бы еще в самом конце setup задал начальные значения для TelegramTimer, особенно для тех, которые с большим интервалом, примерно рассчитать так, что бы они не выполнялись за один цикл.
Для 5 сек примерно так: 0, 1800, 3600 ,
Для секундных тоже можно, для 50мс не имеет смысла, потом все равно перемешается, но в начале будет как то поприличнее.
 

Сотнег

★★★★★★★
15 Янв 2020
4,446
1,520
@78125,
с типами проблем нет.
Недочёт только в том, что в большинстве случаев вызова функции QuerySelect у неё не будет возвращаемого значения (return не присвоен).
 

78125

✩✩✩✩✩✩✩
1 Дек 2019
76
2
@78125,
с типами проблем нет.
Недочёт только в том, что в большинстве случаев вызова функции QuerySelect у неё не будет возвращаемого значения (return не присвоен).
Спасибо!
Сделал тогда возврат самого нужного датчика по дефотлту
C++:
byte QuerySelect() {
                    if (millis()-TelegramTimer[1]>5000) {TelegramTimer[1] = millis(); return 1;}
                    if (millis()-TelegramTimer[2]>5000) {TelegramTimer[2] = millis(); return 2;}
                    if (millis()-TelegramTimer[3]>5000) {TelegramTimer[3] = millis(); return 3;}
                    if (millis()-TelegramTimer[4]>1000) {TelegramTimer[4] = millis(); return 4;}
                    if (millis()-TelegramTimer[5]>1000) {TelegramTimer[5] = millis(); return 5;}
                    if (millis()-TelegramTimer[6]>1000) {TelegramTimer[6] = millis(); return 6;}
                    if (millis()-TelegramTimer[7]>1000) {TelegramTimer[7] = millis(); return 7;}
                    if (millis()-TelegramTimer[0]>50) {TelegramTimer[0] = millis(); return 0;}
                    return 8;
                     }