I have three independent tasks depicted in Fig-1, which have equal priorities and are running concurrently very well being responsive to interrupt button K1 and Pot1 under "Arduino UNO R3 + Arduino_FreeRTOS.h" multi-tasking environment. The tasks are:
(1) LED2 freely blinks at 4 sec interval,
(2) LED1's blink rate depends on ADC-Ch1 voltage, and
(3) L (built-in LED of UNOR3) blinks five times at 1-sec interval when interrupt button K1 is pressed.
The complete sketch is given below, which I have prepared by consulting the examples of the Arduino IDE.
Now, I want to blink LED3 freely of Fig-1 at 1-sec interval by including the following codes in the loop() function. The result is this that the system becomes hanged (no activities of LED1, LED2, and LED3) after the uploading of the sketch.
digitalWrite(12, HIGH);
vTaskDelay(1000 / portTICK_PERIOD_MS );
digitalWrite(12, LOW);
vTaskDelay(1000 / portTICK_PERIOD_MS );
I would appreciate to receive your guidance (solution hints along with underlying theory) to make the above codes working in the loop() function.
Figure-1:
Complete Sketch:
#include <Arduino_FreeRTOS.h>
#include <queue.h>
#include <semphr.h>
QueueHandle_t integerQueue;
SemaphoreHandle_t interruptSemaphore;
#define INT0 2
// define three tasks for Blink & AnalogRead
void TaskBlinkL( void *pvParameters ); //blinks L at 1 sec interval
void TaskBlinkLED2( void *pvParameters ); //blinks LED2 at 2 sec interval
void TaskAnalogReadA1( void *pvParameters ); //task that publiseh value of A1-pin in Queue
void TaskPwm( void *pvParameters ); //blink rate of LED1 depends on value of A1-pin
void setup()
{
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect.
}
pinMode(11, OUTPUT);
pinMode(12, OUTPUT); //output line for LED3
pinMode(13, OUTPUT); //built-in LED (L)
pinMode(INT0, INPUT_PULLUP);
//----initialize PWM (Mode 14 FPWM) at DPin-9 -----
pinMode(9, OUTPUT); //Ch-A
TCCR1A = 0x00; //reset
TCCR1B = 0x00; //TC1 reset and OFF
//fOC1A/B = clckSys/(N*(1+ICR1); Mode-14 FPWM; OCR1A controls duty cycle
// 1 Hz = 16000000/(256*(1+ICR1) N=1,8,64,256,1024==> ICR1 = 62499
// 20 Hz ; ICR1 = 3124
TCCR1A |= (1 << WGM11); //Mode-14 Fast PWM
TCCR1B |= (1 << WGM13) | (1 << WGM12); //Mode-14 Fast PWM
TCCR1A |= (1 << COM1A1) | (0 << COM1A0); //Non-invert: HIGH-LOW
ICR1 = 62499; // TOP for 1Hz frequnecy
OCR1A = 31250; //= 50% duty cycle
TCNT1 = 0;
TCCR1B |= (1 << CS12);//TC1 statrt with N = 256;
//--------------------------------------------
// Now set up tasks to run independently.
interruptSemaphore = xSemaphoreCreateBinary();
if (interruptSemaphore != NULL)
{
attachInterrupt(digitalPinToInterrupt(2), interruptHandler, LOW);// Attach interrupt
}
//-----------------------------------------------
integerQueue = xQueueCreate(
10,
sizeof (int)); //Queue length, queue item size
if (integerQueue != NULL)
{
xTaskCreate( // Create task that consumes the queue if it was created.
TaskPwm, // Task function
"PWMLED1", // A name just for humans
128,
NULL,
1, // Priority
NULL);
xTaskCreate( // Create task that publish data in the queue if it was created.
TaskAnalogReadA1,
"AnalogReadA1",
128, // Stack size
NULL,
1, // Priority
NULL );
}
//----------------------------------------------------
xTaskCreate(
TaskBlinkL,
"BlinkL", // A name just for humans
128,
NULL,
1, // Priority
NULL );
xTaskCreate(
TaskBlinkLED2,
"BlinkLED2",
128,
NULL,
1, // Priority
NULL );
// Now the task scheduler, which takes over control
//of scheduling individual tasks, is automatically started.
}
void loop() //called upon by Task Idle of FreeRTOS
{
/*digitalWrite(12, HIGH);
vTaskDelay(1000 / portTICK_PERIOD_MS );
digitalWrite(12, LOW);
vTaskDelay(1000 / portTICK_PERIOD_MS );*/
}
//---------------------------------------------
void TaskBlinkLED2(void *pvParameters) // This is a task.
{
(void) pvParameters;
while (true) // A Task shall never return or exit.
{
digitalWrite(11, HIGH);
vTaskDelay( 2000 / portTICK_PERIOD_MS ); // wait for 2 second
digitalWrite(11, LOW);
vTaskDelay( 2000 / portTICK_PERIOD_MS ); // wait for 2 second
}
}
//--------------------------------------------
void TaskAnalogReadA1(void *pvParameters)
{
(void) pvParameters;
while (true)
{
int adcValue = analogRead(A1);
xQueueSend(integerQueue, &adcValue, portMAX_DELAY);
vTaskDelay(1);// One tick delay (15ms) in between reads for stability
}
}
void TaskPwm(void * pvParameters)
{
(void) pvParameters;
int valueFromQueue = 0;
while (true)
{
if (xQueueReceive(integerQueue, &valueFromQueue, portMAX_DELAY) == pdPASS)
{
Serial.print("ADC-A1 value received via Queue: ");
Serial.println(valueFromQueue, DEC); //0 to 1023
Serial.println("===================");
ICR1 = map(valueFromQueue, 0, 1023, 62499, 3124); //1Hz (FCCW) - 20Hz(FCW)
OCR1A = ICR1 / 2; //maintains 50% duty cycle
vTaskDelay(1000 / portTICK_PERIOD_MS );
}
}
}
//------------------------------
void interruptHandler()
{
xSemaphoreGiveFromISR(interruptSemaphore, NULL);
}
//-------------------------------
void TaskBlinkL(void *pvParameters)
{
(void) pvParameters;
while (true)
{
if (xSemaphoreTake(interruptSemaphore, portMAX_DELAY) == pdPASS)
{
for (int i = 0; i < 5; i++)
{
digitalWrite(13, HIGH);
vTaskDelay(500 / portTICK_PERIOD_MS ); //500 ms delay
digitalWrite(13, LOW);
vTaskDelay(500 / portTICK_PERIOD_MS );
}
}
}
}