freeRTOS hand issue

Hi There,
I have two task. task2 works fine, but when task1 trigger then CPU got hang.
How to fix it?

CPU: Arduino UNO (ATmega328P)
Code is following:

#include <Arduino_FreeRTOS.h>


/*******************xTask for ****************************/
void scanButton(void *pvParameters)  
{
  int  itr=0;
  bool readBtnStatus;
  
  pinMode(11, INPUT);
  pinMode(0,  OUTPUT);

  while(1)
  {
    readBtnStatus = digitalRead(11);   
    vTaskDelay( 100);

    if(readBtnStatus)
    {
      
      if(itr >= 2)
      {
        digitalWrite(0, HIGH);
        itr = 0;
      }

      else
      {
        digitalWrite(0, LOW);
        itr++;
      }
      
    }
 
    //vTaskDelay(10);
     
  }

}


/*******************xTask for ****************************/
void controlLoad(void *pvParameters)  
{
  bool lowswitch  = 0;
  bool highswitch = 0;
  bool passswitch = 0;
  
  pinMode(1,INPUT); //low switch
  pinMode(2,INPUT); //pass switch
  pinMode(4,INPUT); //high switch

  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  

  while(1)
  {
    lowswitch  = digitalRead(1);
    passswitch = digitalRead(2);
    highswitch = digitalRead(4);

    if (lowswitch == 1 && highswitch == 0 && passswitch == 0)
    {
      digitalWrite(10,LOW);
      digitalWrite(9,HIGH);
    }

    else if (lowswitch == 0 && highswitch == 1 && passswitch == 0)
    {
      digitalWrite(10,HIGH);
      digitalWrite(9,LOW);
    }

    else if (lowswitch == 0 && highswitch == 0 && passswitch == 1)
    {
      digitalWrite(10,HIGH);
      vTaskDelay( 150 );
      digitalWrite(10,LOW);
      vTaskDelay( 150 );
      digitalWrite(9,LOW);
    }

    else if (lowswitch == 1 && highswitch == 0 && passswitch == 1)
    {
      digitalWrite(9,LOW);
      digitalWrite(10,HIGH);
      vTaskDelay( 150 );
      digitalWrite(10,LOW);
      digitalWrite(9,HIGH);
      vTaskDelay( 150 );
    }

    else if (lowswitch == 0 && highswitch == 1 && passswitch == 1)
    {
      
      digitalWrite(10,LOW);
      digitalWrite(9,HIGH);
      vTaskDelay( 150 );
      digitalWrite(9,LOW);
      digitalWrite(10,HIGH);
      vTaskDelay( 150 );
    }

    else if (lowswitch == 1 && highswitch == 1)
    {
      digitalWrite(10,HIGH);
      digitalWrite(9,HIGH);
    }

    
    else
    {
      digitalWrite(10,LOW);
      digitalWrite(9,LOW);
    }
    
    vTaskDelay(10);
  }

}


/******************* Setup ****************************/
void setup()
{
  Serial.begin(9600);

  xTaskCreate(scanButton,  "task1", 512,  NULL, 2,  NULL );
  xTaskCreate(controlLoad, "task2", 512,  NULL, 1,  NULL );
}


void loop()
{

}

Take that line out if you plan to use pins 0 and 1. Serial comes on 0 and 1 so you can either use those pins or you can use Serial but you can't use both.

This would probably be a lot easier to do without the rtos

I'm concerned about the RAM usage of this sketch. It uses at least 1kB for the two task stacks. Then there is however much RAM is used for the loop stack. And finally there is the RAM used by any global variables. The ATmega328P only has 2kB of RAM. Are you sure that the stacks of both of these tasks fit?

Also, when calling vTaskDelay, you should use vTaskDelay(pdMS_TO_TICKS(x)) rather than passing the number of ticks directly.

1 Like

IMO, trying to create any significant application on an Uno using FreeRTOS is a pointless exercise.

Move to an ESP32 board that has FreeRTOS built in and a lot more memory. Or, drop FreeRTOS and use traditional "Arduino Multitasking".

3 Likes

Can you please share the Idea or Any library on traditional "Arduino Multitasking"?

How can I check it?

There are literally dozens of tutorials and examples on the subject, both in this forum and other sites. A few:
https://forum.arduino.cc/t/demonstration-code-for-several-things-at-the-same-time/217158

https://roboticsbackend.com/how-to-do-multitasking-with-arduino/

https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017

https://circuitdigest.com/microcontroller-projects/arduino-multitasking-using-millis-in-arduino

I'm not sure of a direct way. I would start by trying to decrease the stack sizes and see if that makes it start working. But I think it's fair to assume that is the issue. If you want to use FreeRTOS I would recommend any of the many inexpensive and much more powerful chips that have Arduino cores.

Hi @io_rony ,

Welcome to the forum..

should not use pins 0 and 1..

here's a shot for you..

/*
  https://forum.arduino.cc/t/freertos-hand-issue/1323658
*/


#define BTN_PIN 11
#define LED_PIN 13 //was 0
#define LO_SW 3 // was 1
#define PASS_SW 2
#define HI_SW 4
#define OUT_1 9
#define OUT_2 10

#define LO_BIT 2
#define HI_BIT 1
#define PASS_BIT 0


byte lastBtn = 0;
unsigned long lastBtnRead;
unsigned long btnDebounce = 100;
byte itr = 0;

byte clState = 0;
byte step = 0;
unsigned long lastPass;
unsigned long passInterval = 10;
unsigned long lastStep;
unsigned long stepInterval = 150;


void setup() {

  Serial.begin(115200);
  Serial.println("ready..");

  pinMode(LO_SW, INPUT); //low switch
  pinMode(PASS_SW, INPUT); //pass switch
  pinMode(HI_SW, INPUT); //high switch

  pinMode(OUT_1, OUTPUT);
  pinMode(OUT_2, OUTPUT);


  pinMode(BTN_PIN, INPUT);
  pinMode(LED_PIN,  OUTPUT);

}

void loop() {


  unsigned long now = millis();

  if (now - lastBtnRead >= btnDebounce) {
    byte b = digitalRead(BTN_PIN);
    if (b != lastBtn) {
      lastBtnRead = now;
      lastBtn = b;
      if (b == HIGH) {
        if (itr >= 2)
        {
          digitalWrite(LED_PIN, HIGH);
          itr = 0;
        }
        else
        {
          digitalWrite(LED_PIN, LOW);
          itr++;
        }
      }
    }
  }

  if (now - lastPass >= passInterval) {
    lastPass = now;
    switch (clState) {
      case 0: if (digitalRead(LO_SW)) bitSet(clState, LO_BIT);
        if (digitalRead(HI_SW)) bitSet(clState, HI_BIT);
        if (digitalRead(PASS_SW)) bitSet(clState, PASS_BIT);
        step = 0;
        break;
      case 1: switch (step) {
          case 0: digitalWrite(OUT_2, HIGH);
            lastStep = now;
            step++;
            break;
          case 1: if (now - lastStep >= stepInterval) {
              digitalWrite(OUT_2, LOW);
              lastStep = now;
              step++;
            }
            break;
          case 2: if (now - lastStep >= stepInterval) {
              digitalWrite(OUT_1, LOW);
              clState = 0;
              step = 0;
            }
            break;
        }
        break;
      case 2: digitalWrite(OUT_2, HIGH);
        digitalWrite(OUT_1, LOW);
        clState = 0;
        break;
      case 3: switch (step) {
          case 0: digitalWrite(OUT_2, LOW);
            digitalWrite(OUT_1, HIGH);
            lastStep = now;
            step++;
            break;
          case 1: if (now - lastStep >= stepInterval) {
              digitalWrite(OUT_1, LOW);
              digitalWrite(OUT_2, HIGH);
              lastStep = now;
              step++;
            }
            break;
          case 2: if (now - lastStep >= stepInterval) {
              clState = 0;
              step = 0;
            }
            break;
        }
        break;
      case 4: digitalWrite(OUT_2, LOW);
        digitalWrite(OUT_1, HIGH);
        clState = 0;
        break;
      case 5: switch (step) {
          case 0: digitalWrite(OUT_1, LOW);
            digitalWrite(OUT_2, HIGH);
            lastStep = now;
            step++;
            break;
          case 1: if (now - lastStep >= stepInterval) {
              digitalWrite(OUT_2, LOW);
              digitalWrite(OUT_1, HIGH);
              lastStep = now;
              step++;
            }
            break;
          case 2: if (now - lastStep >= stepInterval) {
              clState = 0;
              step = 0;
            }
            break;
        }
        break;
      case 6: digitalWrite(OUT_2, HIGH);
        digitalWrite(OUT_1, HIGH);
        clState = 0;
        break;
      case 7: digitalWrite(OUT_2, HIGH);//same as 6
        digitalWrite(OUT_1, HIGH);
        clState = 0;
        break;
      default: digitalWrite(OUT_2, LOW);
        digitalWrite(OUT_1, LOW);
        clState = 0;
        break;
    }
  }
}

simulated here..

hope it gives you the some ideas anyways..

good luck.. ~q

Hard agree! I didn't even know it would run on a Mega328.

Thank you so much.
Can you please share the Algorithm?
Or related article? Where I can learn more about it.

1 Like

I just merged your 2 tasks together..
basically just a big state machine constructed with switch statements..

I did do a bit of creativity, when I was looking at you if's, I was seeing bit patterns, so I went with that..
case 0 reads the switches into the 1st 3 bits. low nibble of the clState byte (state machine var)..
don't think the default will ever be reached but should mimic your original code..
was thinking you may want to check the value of clState after switches are read and if it's still 0 then lower both outputs, like the default case??

using millis timers instead of delay functions which blocks..
1 for the button to stop the bounce..
1 around the state machine so it only enters every 10ms..
the last is used inside the state machine for the 150ms delays between output toggles..

good luck.. ~q

Hello io_rony

Do you have experience by coding in C++?

You can design and code a TaskControlBlock by using a structured array to handle the task and the behaviour of the task.
A small task scheduler will call the tasks based on the TaskControlBlock information.