прием/передача данных на ардуино через com порт

Тема в разделе "Arduino & Shields", создана пользователем Silentium, 31 окт 2018.

  1. Откопал вот старый код на rtos и привел к виду примера, решающего поставленную задачу, чтобы кто сдуру паровоза не послушал.
    Одновременно читает ацп и управляет выводом, и реализует два способа остановки процессов для команды "остановить все" - через паузу потока и через передачу сигнала потоку, который сам засыпает до следующего сигнала.

    Код (C++):

    #include <Arduino_FreeRTOS.h>
    #include <semphr.h>


    // Для работы с serial-выводом нужен семафор, чтобы два потока не принялись писать одновременно
    // То же самое понадобится, если будет работа с АЦП из разных потоков
    SemaphoreHandle_t serial_w;
    #define PRINT(x) xSemaphoreTake(serial_w, portMAX_DELAY); Serial.print(x); xSemaphoreGive(serial_w);
    #define PRINTLN(x) xSemaphoreTake(serial_w, portMAX_DELAY); Serial.println(x); xSemaphoreGive(serial_w);


    // Типы
    void TaskBlink( void *pvParameters );
    void TaskAnalogRead( void *pvParameters );
    void TaskSerialRead( void *pvParameters );
    TaskHandle_t blink_h, analogRead_h, serialRead_h;



    void setup() {
      serial_w = xSemaphoreCreateMutex();
      xTaskCreate(TaskBlink, (const portCHAR *)"Blink", 64,  NULL,  1,  &blink_h);
      xTaskCreate(TaskAnalogRead, (const portCHAR *)"AnalogRead", 128,  NULL,  1,  &analogRead_h);
      xTaskCreate(TaskSerialRead, (const portCHAR *)"SerialRead", 512, NULL,  1,  &serialRead_h);
    }


    // Поток мигания светодиодом
    void TaskBlink(void *pvParameters) {
      pinMode(LED_BUILTIN, OUTPUT);
      int x, i = -1;
      for (;;) {
        if (i > 0) {
          digitalWrite(LED_BUILTIN, HIGH);
          vTaskDelay( i / portTICK_PERIOD_MS );
          digitalWrite(LED_BUILTIN, LOW);
          vTaskDelay( i / portTICK_PERIOD_MS );
          x = ulTaskNotifyTake(pdTRUE, 0);
        } else {
          x = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        }
        if (x != 0) {
          i = x;
        }
      }
    }

    // Поток чтения датчика
    void TaskAnalogRead(void *pvParameters) {
      pinMode(A0, INPUT);
      vTaskSuspend(NULL);
      for (;;) {
        xSemaphoreTake(serial_w, portMAX_DELAY);
        taskENTER_CRITICAL();
        auto val = analogRead(A0);
        Serial.print("analog: ");
        Serial.println(val);
        xSemaphoreGive(serial_w);
        taskEXIT_CRITICAL();
        vTaskDelay( 5000 / portTICK_PERIOD_MS );
      }
    }

    // Поток обработки ввода
    void TaskSerialRead(void *pvParameters) {
      Serial.begin(9600);
      while(!Serial);
      char buf[64];
      int x;
      for (;;) {
        auto s = Serial.readBytesUntil('\n', buf, sizeof buf - 1);
        if (s > 0) {
          buf[s] = 0;
          PRINT(">");
          PRINTLN(buf);
         
          if (sscanf(buf, "blink %d", &x) == 1) {
            if (x != 0) {
              while(xTaskNotify(blink_h, x, eSetValueWithoutOverwrite) != pdPASS);
            }
            PRINTLN("ok");
           
          } else if (strcmp(buf, "analog start") == 0) {
            vTaskResume(analogRead_h);
            PRINTLN("ok");
           
          } else if (strcmp(buf, "analog stop") == 0) {
            vTaskSuspend(analogRead_h);
            PRINTLN("ok");
           
          } else if (strcmp(buf, "all stop") == 0) {
            while(xTaskNotify(blink_h, -1, eSetValueWithoutOverwrite) != pdPASS);
            vTaskSuspend(analogRead_h);
            PRINTLN("ok");
           
          } else {
            PRINTLN("blink 123 | blink -1 | analog start | analog stop | all stop");
          }
        }
      }
    }


    void loop() {
    }
     
     
    Silentium нравится это.