// See https://forum.arduino.cc/t/traffic-light-time-to-green-count-down/1168737
// See https://www.circuitstate.com/tutorials/how-to-write-parallel-multitasking-applications-for-esp32-using-freertos-arduino/
#include <LiquidCrystal_I2C.h>
const uint8_t redPin = 14 ;
const uint8_t amberPin = 12 ;
const uint8_t greenPin = 13 ;
int32_t counter = 0 ;
uint32_t redStartAtMs = 0 ;
LiquidCrystal_I2C lcd(0x27, 16, 2);
SemaphoreHandle_t xSemaphore = NULL; // Create a semaphore object
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode (LED_BUILTIN, OUTPUT);
pinMode( redPin, OUTPUT) ;
pinMode( amberPin, OUTPUT) ;
pinMode( greenPin, OUTPUT) ;
lcd.init( );
lcd.backlight();
xSemaphore = xSemaphoreCreateBinary(); // Set the semaphore as binary
Serial.begin (115200);
xTaskCreatePinnedToCore (
task1, // Function to implement the task
"task1", // Name of the task
1000, // Stack size in bytes
NULL, // Task input parameter
0, // Priority of the task
NULL, // Task handle.
0 // Core where the task should run
);
xTaskCreatePinnedToCore (
task2, // Function to implement the task
"task2", // Name of the task
4000, // Stack size in bytes LCD needs more space
NULL, // Task input parameter
0, // Priority of the task
NULL, // Task handle.
0 // Core where the task should run
);
}
void loop() {
// this gives task1 and task2 a chance to run
digitalWrite (LED_BUILTIN, HIGH);
delay (1000);
digitalWrite (LED_BUILTIN, LOW);
delay (1000);
}
void task1 (void* pvParameters) {
while (1) {
redStartAtMs = millis() ;
counter = 7 ;
xSemaphoreGive (xSemaphore); // Release the semaphore
digitalWrite( redPin, HIGH) ;
delay(8000UL) ;
digitalWrite( amberPin, HIGH) ;
delay(3000UL) ;
digitalWrite( redPin, LOW) ;
digitalWrite( amberPin, LOW) ;
digitalWrite( greenPin, HIGH) ;
delay(9000UL) ;
digitalWrite( greenPin, LOW) ;
digitalWrite( amberPin, HIGH) ;
delay(3000) ;
digitalWrite( amberPin, LOW) ;
}
}
void task2 (void* pvParameters) {
while (1) {
if (xSemaphoreTake (xSemaphore, 22000UL )) { // timeout just under cycle time
while ( counter > 0) {
lcd.setCursor(0, 0);
lcd.print(" ") ;
lcd.setCursor(0, 0);
lcd.print( counter -- );
delay(1000UL);
if ( counter <= 0 ) {
lcd.clear() ;
}
}
}
}
}