Closed emrahduruer closed 5 years ago
Can you show code of your motion detector?
Sure. Not that I was having the problem without the motion detector as well.
homekit_value_t motion_get() {
return HOMEKIT_BOOL(motion_detected);
}
homekit_characteristic_t motion = HOMEKIT_CHARACTERISTIC_(
MOTION_DETECTED, false,
.getter = motion_get);
...
HOMEKIT_SERVICE(MOTION_SENSOR,
.characteristics = (homekit_characteristic_t*[]) {
HOMEKIT_CHARACTERISTIC(NAME, "Motion Sensor"),
&motion,
NULL
}),
...
void homekit_gpi_callback(uint8_t gpio_num, gpi_event event, void* cprm) {
if (event == gpi_event_activated) {
DEBUG_PRINT("gpi_event_activated");
motion_detected = true;
homekit_characteristic_notify(&motion, HOMEKIT_BOOL(motion_detected));
} else if (event == gpi_event_deactivated) {
DEBUG_PRINT("gpi_event_deactivated");
motion_detected = false;
homekit_characteristic_notify(&motion, HOMEKIT_BOOL(motion_detected));
}
}
register_digital_sensor(MOTION_SENSOR_PIN, HIGH, &homekit_gpi_callback, NULL);
Ok, I do not see anything criminal here, but last reset that you showed was caused by watchdog, so maybe you're doing too much in an interrupt or something. It would help if you'd show the whole code.
ok. here is the code where I control all my interrupts. This code is calling the callback funtion in the homekit code to notify the clients. DHT data changes is running in different task and calling another callback method in homekit code to notify.
#include <common.h>
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <esp/gpio.h>
#include <gpi.h>
#include <timers.h>
digital_gpi *gpis = NULL;
static void gpi_intr_callback_tick(digital_gpi *gpi) {
gpi->prev_on_state_time = 0;
gpi->callback(gpi->gpio_num,
gpi_event_single_press, gpi->callback_param);
}
/* The callback function that will execute in the context of the daemon task.
Note callback functions must all use this same prototype. */
void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) {
uint8_t gpio = *((uint8_t*) pvParameter1);
/* ...Perform the processing here... */
digital_gpi *gpi = find_gpi_by_gpio_num(gpio);
if (gpi == NULL) {
return;
}
uint32_t now = xTaskGetTickCountFromISR();
if ((now - gpi->last_event_time) * portTICK_PERIOD_MS <
gpi->debounce_time) {
// debounce time, ignore events
return;
}
gpi->last_event_time = now;
// Wait until the input changes...
if (gpi->type == gpi_toggle_switch) {
while(gpio_read(gpi->gpio_num) == gpi->last_state_value) {
}
gpi->last_state_value = gpio_read(gpi->gpio_num);
}
if (gpio_read(gpi->gpio_num) == gpi->on_state_value) {
if (gpi->type == gpi_button) {
gpi->prev_on_state_time = gpi->last_on_state_time;
}
gpi->last_on_state_time = now;
if (gpi->type == gpi_digital_sensor) {
// This is a sensor or any input...
gpi->callback(gpi->gpio_num,
gpi_event_activated, gpi->callback_param);
} else if (gpi->type == gpi_toggle_switch) {
// This is a toggle switch...
gpi->callback(gpi->gpio_num,
gpi_event_toggled_on, gpi->callback_param);
}
} else {
if (gpi->type == gpi_button) {
// This is a button...
if (gpi->prev_on_state_time > 0 &&
(gpi->last_on_state_time
- gpi->prev_on_state_time) * portTICK_PERIOD_MS <=
DOUBLE_CLICK_TIME) {
// Double click is detected.
gpi->prev_on_state_time = 0;
sdk_os_timer_disarm(&gpi->timer);
gpi->callback(gpi->gpio_num,
gpi_event_double_press, gpi->callback_param);
} else if (gpi->long_press_time > 0 && // If the long press time is set.
(now - gpi->last_on_state_time) * portTICK_PERIOD_MS >
gpi->long_press_time) {
// Long press is detected.
gpi->callback(gpi->gpio_num,
gpi_event_long_press, gpi->callback_param);
} else {
sdk_os_timer_arm(&gpi->timer, DOUBLE_CLICK_TIME + 50, 0);
}
} else if (gpi->type == gpi_toggle_switch) {
// This is a toggle switch...
gpi->callback(gpi->gpio_num,
gpi_event_toggled_off, gpi->callback_param);
} else {
// This is a sensor or any input...
gpi->callback(gpi->gpio_num,
gpi_event_deactivated, gpi->callback_param);
}
}
}
void gpi_intr_callback(uint8_t gpio) {
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xTimerPendFunctionCallFromISR(vProcessInterface,
&gpio,
NULL,
&xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD();
}
}
digital_gpi* register_gpi(uint8_t gpio_num,
gpi_type type,
int on_state_value,
gpi_callback cb, void* cb_param) {
// If it is already registered, we just returned the register one.
digital_gpi *gpi = find_gpi_by_gpio_num(gpio_num);
if (gpi) {
return gpi;
}
gpi = malloc(sizeof(digital_gpi));
memset(gpi, 0, sizeof(*gpi));
gpi->gpio_num = gpio_num;
gpi->type = type;
gpi->callback = cb;
gpi->callback_param = cb_param;
gpi->on_state_value = on_state_value;
gpi->debounce_time = DEBOUNCE_TIME;
gpi->last_state_value = gpio_read(gpi->gpio_num);
uint32_t now = xTaskGetTickCountFromISR();
gpi->last_event_time = now;
gpi->last_on_state_time = now;
if (type == gpi_button) {
sdk_os_timer_setfn(&gpi->timer, (void (*)(void *))gpi_intr_callback_tick,
gpi);
}
gpi->next = gpis;
gpis = gpi;
if (type == gpi_toggle_switch || type == gpi_digital_sensor) {
gpio_enable(gpi->gpio_num, GPIO_INPUT);
} else {
gpio_set_pullup(gpi->gpio_num, true, true);
}
gpio_set_interrupt(gpi->gpio_num, GPIO_INTTYPE_EDGE_ANY,
gpi_intr_callback);
return gpi;
}
digital_gpi* register_button(uint8_t gpio_num,
int on_state_value,
uint16_t long_press_time,
gpi_callback cb, void* cb_param) {
digital_gpi* gpi = register_gpi(gpio_num,
gpi_button,
on_state_value,
cb, cb_param);
if (gpi != NULL) {
gpi->long_press_time = long_press_time;
}
return gpi;
}
digital_gpi* register_switch(uint8_t gpio_num,
int on_state_value,
gpi_callback cb, void* cb_param) {
return register_gpi(gpio_num,
gpi_toggle_switch,
on_state_value,
cb, cb_param);
}
digital_gpi* register_digital_sensor(uint8_t gpio_num,
int on_state_value,
gpi_callback cb, void* cb_param) {
return register_gpi(gpio_num,
gpi_digital_sensor,
on_state_value,
cb, cb_param);
}
digital_gpi* find_gpi_by_gpio_num(uint8_t gpio_num) {
digital_gpi *gpi = gpis;
while (gpi && gpi->gpio_num != gpio_num) {
gpi = gpi->next;
}
return gpi;
}
After you told me about the interrupt, while I am checking my code, I realized that in fact, the problem was the DHT data notifications.
Thank you for your quick responses.
Consider it closed? Would you mind sharing your findings so that other can benefit?
Hello,
I experience this problem; As soon as the second client connected, I get cpu reset Fatal Exception(29) at 0x402410c2: uxListRemove at /tools/esp-open-rtos/FreeRTOS/Source/list.c:176.
So, I have read issue #13 and issue #10. I followed all the suggestions in there. No luck so far. I have the latest esp-homekit code including your March 14 update.
I tried to explain what I see so far. Please advise.
In one scenerio, the second client connects and it works fine for a while. `>>> HomeKit: Got new client connection: 5 [hermes-beryllium] [] on_homekit_event: HOMEKIT_EVENT_CLIENT_CONNECTED
Other one, if the client connected automatically, I notice that GET /accessories command does not come from the client. After that, in the first attemp to send EVENT command, the code crashes. Not that it happens even there is one client connected.
`>>> HomeKit: Got new client connection: 4 [hermes-beryllium] [] on_homekit_event: HOMEKIT_EVENT_CLIENT_CONNECTED
wdt reset load 0x40100000, len 2292, room 16 tail 4 chksum 0x57 load 0x3ffe8000, len 772, room 4 tail 0 chksum 0x0b csum 0x0b `