Hello,
I’m new to FreeRTOS and trying to simulate a Garage Door Opener, using one button to iterate between 5 states.
Usual behaviour for the garage door started by a button press would be:
Open –> Closing –> Closed
Closed –> Opening –> Open
However while moving you can stop the garage door with another button press and start again moving in the opposite direction with another press:
Closing / Opening –> Stopped
Stopped –> Opening / Closing
The button is handled with an interrupt. When the button gets pressed while moving, I want the previous opened task
button_callback to be deleted, since otherwise it will not stay in the state “stopped”. Somehow I must use the xTaskCreate, xTaskDelete and the according TaskHandle wrong, since the serial console of my ESP8266 is giving the following errors:
Console output:
~~~
Waiting for button press interrupt on gpio 10…
Button pressed!
State = OPENING
State = OPEN
Task exists!
Fatal exception (28):
epc1=0x40216e92
0x40216e92: uxListRemove at /Volumes/case-sensitive/esp-open-rtos/FreeRTOS/Source/list.c:183
epc2=0x00000000
epc3=0x402035c1
0x402035c1: prvIdleTask at /Volumes/case-sensitive/esp-open-rtos/FreeRTOS/Source/tasks.c:4687
excvaddr=0x00000004
depc=0x00000000
excsave1=0x4020384f
0x4020384f: vTaskDelete at /Volumes/case-sensitive/esp-open-rtos/FreeRTOS/Source/tasks.c:4687
Registers:
a0 4020384f a1 3fff4910 a2 3fff254c a3 00000000
0x4020384f: vTaskDelete at /Volumes/case-sensitive/esp-open-rtos/FreeRTOS/Source/tasks.c:4687
a4 3fff0e38 a5 3fff0e38 a6 00000000 a7 00000000
a8 00000000 a9 60000000 a10 00000000 a11 0000000a
a12 3fff2548 a13 3fff0fb4 SAR 00000000
Stack: SP=0x3fff4910
0x3fff4910: ffffff38 3fff123c 00003430 4021501c
0x4021501c: button
task at /Volumes/case-sensitive/esp-homekit-demo/examples/sonoffdual
garagedoor/main.c:191
0x3fff4920: 00003430 00000000 00000000 00000000
0x3fff4930: 00000000 00000000 00000000 00000000
0x3fff4940: 00000000 00000000 00000000 00000000
0x3fff4950: 00000000 a5a5a5a5 0000014c fffffffc
0x3fff4960: 3fff48c0 091c47b9 3fff0eb8 3fff0eb8
0x3fff4970: 3fff4960 3fff0eb0 0000000d 3ffee50c
0x3fff4980: 3ffee50c 3fff4960 00000000 00000002
Free Heap: 49744
heapstart 0x3fff1688 brk 0x3fff6f78 supervisor sp 0x40000000 sp-brk 37000 bytes
arena (total
size) 22768 fordblks (freesize) 12744 uordblocks (used_size) 10024
~~~
Code:
~~~
void gpio
intrhandler(uint8
t gpionum);
TaskHandle_t buttonTaskHandle = NULL;
enum {OPEN, CLOSED, OPENING, CLOSING, STOPPED};
bool lastState;
/* initialize button */
void button_init() {
// enable button and enable pullup
gpio_enable(button_gpio, GPIO_INPUT);
gpio_set_pullup(button_gpio, true, true);
// initialize queue which holds timestamp
tsqueue = xQueueCreate(1, sizeof(uint32_t));
// start button_task
xTaskCreate(button_task, "buttonTask", 1024, &tsqueue, 2, NULL);
}
static QueueHandle_t tsqueue;
void gpio
intrhandler(uint8
t gpionum)
{
uint32_t now = xTaskGetTickCountFromISR();
xQueueSendToBackFromISR(tsqueue, &now, NULL);
}
void button
task(void *pvParameters)
{
printf(“Waiting for button press interrupt on gpio %d…rn”, buttongpio);
QueueHandle
t *tsqueue = (QueueHandlet *)pvParameters;
gpio_set_interrupt(button_gpio, GPIO_INTTYPE_EDGE_NEG, gpio_intr_handler);
uint32_t last = 0;
while(1) {
uint32_t button_ts;
xQueueReceive(*tsqueue, &button_ts, portMAX_DELAY);
button_ts *= portTICK_PERIOD_MS;
if (last < button_ts-200) {
last = button_ts;
if (buttonTaskHandle != NULL) {
printf("Task exists!n");
vTaskDelete(buttonTaskHandle);
}
xTaskCreate(button_callback, "buttonCallback", 2048, NULL, 2, &buttonTaskHandle);
}
}
}
void button_callback() {
if (local_current_state == OPEN) {
printf("Button pressed!nState = CLOSINGn");
local_current_state = CLOSING;
vTaskDelay(garage_runtime / portTICK_PERIOD_MS);
printf("State = CLOSEDnn");
local_current_state = CLOSED;
}
else if (local_current_state == CLOSED) {
printf("Button pressed!nState = OPENINGn");
local_current_state = OPENING;
vTaskDelay(garage_runtime / portTICK_PERIOD_MS);
printf("State = OPENnn");
local_current_state = OPEN;
}
else if (local_current_state == CLOSING || local_current_state == OPENING) {
lastState = local_current_state-2;
printf("Button pressed!nState = STOPPEDnn");
local_current_state = STOPPED;
}
else if (local_current_state == STOPPED) {
printf("Button pressed!nState = %dn", !lastState+2);
local_current_state = !lastState+2;
vTaskDelay(garage_runtime / portTICK_PERIOD_MS);
printf("State = OPENnn");
local_current_state = !lastState;
}
vTaskDelete(buttonTaskHandle);
}
~~~