简体   繁体   中英

How to read from Serial port in FreeRTOS on Arduino using Semaphores?

I'm trying to control a task blinking depending on a command received from the Serial port. The idea is to get 0 from the serial port to blink a led once.

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

// define tasks
void TaskReadFromSerial( void *pvParameters ); // Get commands
void TaskBlink( void *pvParameters ); // LED as actuator


//define smaphore handlers
SemaphoreHandle_t activateActuatorSem;

//define global variable
String input = "-1";

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  while (!Serial) {
    ; // wait for serial port to connect.
  }

  activateActuatorSem = xSemaphoreCreateBinary();

    if ( activateActuatorSem != NULL ) {
      xSemaphoreGive( activateActuatorSem );  // Make the Serial Port available for use, by "Giving" the Semaphore.
  }

  // Now set up tasks to run independently.
  
  xTaskCreate(
    TaskBlink
    ,  (const portCHAR *) "Blink"   // A name just for humans
    ,  128  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 1 being the highest, and 4 being the lowest.
    ,  NULL );

   xTaskCreate(
    TaskReadFromSerial
    ,  (const portCHAR *) "ReadFromSerial"
    ,  128  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL );

  // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop()
{
  // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void TaskReadFromSerial( void *pvParameters )
{
  (void) pvParameters;

  for (;;)
  {
    if(Serial.available()>0) {
      input = Serial.readString();
      Serial.println("read");
      if (xSemaphoreTake(activateActuatorSem, portMAX_DELAY) == pdTRUE) {
        Serial.println("Input:");
        Serial.println(input);
        Serial.println("sema");
        xSemaphoreGive(activateActuatorSem);
      }
    }
    vTaskDelay(1); 
  }
}

void TaskBlink(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);

  for (;;) // A Task shall never return or exit.
  {
    if (xSemaphoreTake(activateActuatorSem, portMAX_DELAY) == pdTRUE) {
      if (input.equals("1\n")) {
        digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
        vTaskDelay( 250 / portTICK_PERIOD_MS ); // wait for one second
        digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
        vTaskDelay( 250 / portTICK_PERIOD_MS ); // wait for one second 
      }
      xSemaphoreGive(activateActuatorSem);
    }
    
  }
}

Loading the code above, I cannot see anything in the monitor either sending command from my computer.

Finally, I could fix the code above.

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

// define tasks
void TaskReadFromSerial( void *pvParameters ); // Get commands
void TaskBlink( void *pvParameters ); // LED as actuator

//define smaphore handlers
SemaphoreHandle_t activateActuatorSem;

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  while (!Serial) {
    ; // wait for serial port to connect.
  }

  activateActuatorSem = xSemaphoreCreateBinary();

  if ( activateActuatorSem != NULL )
    xSemaphoreGive( activateActuatorSem );  // Make the Serial Port available for use, by "Giving" the Semaphore.

  // Now set up tasks to run independently.
  
  xTaskCreate(
    TaskBlink
    ,  (const portCHAR *) "Blink"   // A name just for humans
    ,  256  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 1 being the highest, and 4 being the lowest.
    ,  NULL );

   xTaskCreate(
    TaskReadFromSerial
    ,  (const portCHAR *) "ReadFromSerial"
    ,  256  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL );

  // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop()
{
  // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void TaskReadFromSerial( void *pvParameters )
{
  (void) pvParameters;
  
  for (;;)
  {   
    if(Serial.available()>0){
      char c = Serial.read();
      if (c == '1')
        xSemaphoreGive(activateActuatorSem);
    }
    vTaskDelay( 250 / portTICK_PERIOD_MS ); 
  }
}

void TaskBlink(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);

  for (;;) // A Task shall never return or exit.
  {
     xSemaphoreTake(activateActuatorSem, portMAX_DELAY);
     digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
     vTaskDelay( 250 / portTICK_PERIOD_MS ); // wait for one second
     digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
     vTaskDelay( 250 / portTICK_PERIOD_MS ); // wait for one second  
  }
}

The ReadFromSerial task gets stuck because of the string. It is better to use char instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM