Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

Вопрос multiloop

Тема в разделе "NodeMCU-32S", создана пользователем igorlab, 28 ноя 2018.

  1. igorlab

    igorlab Новичок

    Сообщения:
    23
    Симпатии:
    1
    Доброго дня!
    Помогите разобраться с многопоточностью (если правильно назвал) на ESP32.
    немного изменил скрипт примера

    Код (C):
    1. int i = 0;
    2.  
    3. void setup() {
    4.   Serial.begin(115200);
    5.   xTaskCreatePinnedToCore(loop1, "loop1", 4096, NULL, 1, NULL, 1);
    6.   xTaskCreatePinnedToCore(loop2, "loop2", 4096, NULL, 1, NULL, 1);
    7. }
    8. void loop() {
    9.   while (true) {  
    10.     int command = Serial.read();//read a command  
    11.     if (command == -1) break;//if no more commands, then exit
    12.     else if (command == 't') {
    13.       Serial.println("read 't'");
    14.       i = -1;
    15.     }
    16.   }
    17. }
    18.  
    19. void loop1(void *pvParameters) {
    20.   while (1) {
    21.     if (i == -1 ){
    22.       Serial.println("loop изменил i на -1");
    23.       i = 0;
    24.     }  
    25.     delay(100);
    26.   }
    27. }
    28.  
    29. void loop2(void *pvParameters) {
    30.   while (1) {
    31.     Serial.print("loop2 i = "); Serial.println(i);
    32.     delay(500);
    33.   }
    34. }
    35.  
    код работает, при отправке из терминала 't' - loop1 реагирует только в том случае, если строка delay(100); не закомментирована - подскажите зачем там этот делей? и можно ли подобным образом сделать три loops - в одном будет код обработки датчиков, во втором код веб сервера, а в третьем код бота для телеграмма?
     
  2. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    972
    Симпатии:
    163
    Cлово 'loop' в этом примере вас здорово запутало

    Код (Text):
    1. int i = 0;
    2. // это setup Arduino
    3. void setup() {
    4.     // инициализация устройств
    5.     Serial.begin(115200);
    6.     // а также датчиков и т.п.
    7.  
    8.     // пристегивание задач на выполнение операционной системе
    9.     xTaskCreatePinnedToCore(task1, "task1", 4096, NULL, 1, NULL, 1);
    10.     xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 1, NULL, 1);
    11.     xTaskCreatePinnedToCore(task3, "task3", 4096, NULL, 1, NULL, 1);
    12. }
    13. // это loop Arduino - он должен быть пустым !
    14. void loop() {}
    15.  
    16. // а вот это три задачи, в них то все и работает
    17.  
    18. // читает байт из serial, ждет команду 't' и  устанавливает флаг
    19. void task3(void *pvParameters) {
    20.     int command = -1;
    21.     while (true) {
    22.         if( Serial.available())
    23.         {
    24.             command = Serial.read();
    25.             if(command == 't')
    26.             {
    27.                 Serial.println("read 't'");
    28.                 i = -1;
    29.             }
    30.         }
    31.         delay(10); // отпустите цикл, дайте драйверу Serial достучаться до процессора
    32.     }
    33. }
    34. // время от времени отрабатывает команду и сбрасывает флаг
    35. void task1(void *pvParameters) {
    36.     while (1)
    37.     {
    38.         if (i == -1 )
    39.         {
    40.             Serial.println("task3 изменил i на -1");
    41.             i = 0;
    42.         }
    43.         delay(100);
    44.     }
    45. }
    46.  
    47. // периодическая задача
    48. void task2(void *pvParameters) {
    49.     while (1)
    50.     {
    51.         Serial.print("task2 i = "); Serial.println(i);
    52.         delay(500);
    53.     }
    54. }
    К слову, в freertos есть специальные "флаги" не позволяющие наделать глупостей при "мультипоточности". Вариант с целой переменной может вызвать непредсказуемые ошибки (оптимизатор компилятора может засунуть ваш флажок в регистр и при выходе из прерывания или смене контекста флаг будет перезаливаться старый - неизмененный)
     
    Последнее редактирование: 28 ноя 2018
    igorlab нравится это.
  3. Алексей.

    Алексей. Активный участник сообщества

    Сообщения:
    410
    Симпатии:
    40
    @igorlab,
    В setup-е запускаете таски на первом ядре, а на каком работает loop не очевидно.
    Для передачи флагов между тасками безболезненно использовать EventGroupHandle_t, а для передачи данных xQueueHandle.

    П.С.
    Результат запуска таска вы не проверяете, вдруг он (xTaskCreatePinnedToCore) вернет не pdPASS, а вы и не узнаете.
    Может так и надо...
     
    Последнее редактирование: 28 ноя 2018
    igorlab нравится это.
  4. igorlab

    igorlab Новичок

    Сообщения:
    23
    Симпатии:
    1
    спасибо за ответы, и комментарии в коде!
    / это loop Arduino - он должен быть пустым ! - инересно, почему должен быть пустым? тем более, со знаком восклицания))
    про xQueueHandle нагуглил здесь, сейчас знакомлюсь как его юзать
     
  5. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    972
    Симпатии:
    163
    Должен быть пустым потому что "тасками"(tasks) операционка может корректно управлять: вытеснять их при необходимости, и т.п. а этот "квази loop" с точки зрения FreeRTOS это просто продолжение setup... он имеет право все нафиг завесить или к нему могут просто не вернуть управление если если при создании taskXX изменили приоритет на более высокий...
     

Поделиться этой страницей