mailgoe wrote on Monday, January 07, 2019:
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/sonoff_dual_garage_door/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
_heap_start 0x3fff1688 brk 0x3fff6f78 supervisor sp 0x40000000 sp-brk 37000 bytes
arena (total_size) 22768 fordblks (free_size) 12744 uordblocks (used_size) 10024
Code:
void gpio_intr_handler(uint8_t gpio_num);
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_intr_handler(uint8_t gpio_num)
{
uint32_t now = xTaskGetTickCountFromISR();
xQueueSendToBackFromISR(tsqueue, &now, NULL);
}
void button_task(void *pvParameters)
{
printf("Waiting for button press interrupt on gpio %d...\r\n", button_gpio);
QueueHandle_t *tsqueue = (QueueHandle_t *)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 = CLOSING\n");
local_current_state = CLOSING;
vTaskDelay(garage_runtime / portTICK_PERIOD_MS);
printf("State = CLOSED\n\n");
local_current_state = CLOSED;
}
else if (local_current_state == CLOSED) {
printf("Button pressed!\nState = OPENING\n");
local_current_state = OPENING;
vTaskDelay(garage_runtime / portTICK_PERIOD_MS);
printf("State = OPEN\n\n");
local_current_state = OPEN;
}
else if (local_current_state == CLOSING || local_current_state == OPENING) {
lastState = local_current_state-2;
printf("Button pressed!\nState = STOPPED\n\n");
local_current_state = STOPPED;
}
else if (local_current_state == STOPPED) {
printf("Button pressed!\nState = %d\n", !lastState+2);
local_current_state = !lastState+2;
vTaskDelay(garage_runtime / portTICK_PERIOD_MS);
printf("State = OPEN\n\n");
local_current_state = !lastState;
}
vTaskDelete(buttonTaskHandle);
}