Closed AchimPieters closed 5 years ago
According to this invaluable reference it looks like GPIO16 does not have an interrupt support. That's why your UP button (which is connected to it) does not work. I recommend using the other unused pin - GPIO5 for that.
A few suggestions on the code:
void relays_write(int state) {
gpio_write(relay_up, state == POSITION_STATE_OPENING);
gpio_write(relay_down, state == POSITION_STATE_CLOSING);
}
int8_t direction = position_state.value.int_value == POSITION_STATE_OPENING ? 1 : -1;
I would do this:
int8_t direction = current_position.value.int_value < target_position.value.int_value ? 1 : -1;
to prevent runaway. In general, I would just use current_position & target_position to control movements and would derive position_state based on the other two.
Snap, I forgot about the gpio16 interrupt support. I will look in to your code suggestions.
Thank you so much!
@maximkulkin
It works! thank you so much, now I have to figure out how to implement this in a real life setup for my curtains / Blinds.
Here's my working code:
#include <stdio.h>
#include <stdlib.h>
#include <espressif/esp_common.h>
#include <esp/uart.h>
#include <esp8266.h>
#include <FreeRTOS.h>
#include <task.h>
#include <homekit/homekit.h>
#include <homekit/characteristics.h>
#include <wifi_config.h>
#include "button.h"
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define POSITION_OPEN 100
#define POSITION_CLOSED 0
#define POSITION_STATE_CLOSING 0
#define POSITION_STATE_OPENING 1
#define POSITION_STATE_STOPPED 2
// number of seconds the blinds take to move from fully open to fully closed position
#define SECONDS_FROM_CLOSED_TO_OPEN 15
TaskHandle_t updateStateTask;
homekit_characteristic_t current_position;
homekit_characteristic_t target_position;
homekit_characteristic_t position_state;
homekit_accessory_t *accessories[];
const int relay0_gpio = 12;
const int relay1_gpio = 13;
const int led_gpio = 2;
const int button_gpio = 4;
const int button1_gpio = 5;
const int button0_gpio = 14;
const int button_up = 5;
const int button_down = 14;
const int relay_up = 12;
const int relay_down = 13;
void target_position_changed();
void relay_write(int relay, bool on) {
gpio_write(relay, on ? 1 : 0);
}
void led_write(bool on) {
gpio_write(led_gpio, on ? 0 : 1);
}
void relays_write(int state) {
gpio_write(relay_up, state == POSITION_STATE_OPENING);
gpio_write(relay_down, state == POSITION_STATE_CLOSING);
}
void reset_configuration_task() {
for (int i=0; i<3; i++) {
led_write(true);
vTaskDelay(100 / portTICK_PERIOD_MS);
led_write(false);
vTaskDelay(100 / portTICK_PERIOD_MS);
}
printf("Resetting Wifi Config\n");
wifi_config_reset();
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("Resetting HomeKit Config\n");
homekit_server_reset();
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("Restarting\n");
sdk_system_restart();
vTaskDelete(NULL);
}
void reset_configuration() {
printf("Resetting Sonoff configuration\n");
xTaskCreate(reset_configuration_task, "Reset configuration", 256, NULL, 2, NULL);
}
void gpio_init() {
gpio_enable(led_gpio, GPIO_OUTPUT);
led_write(false);
gpio_enable(button_up, GPIO_INPUT);
gpio_enable(button_down, GPIO_INPUT);
gpio_enable(relay0_gpio, GPIO_OUTPUT);
gpio_enable(relay1_gpio, GPIO_OUTPUT);
relay_write(relay0_gpio, false);
relay_write(relay1_gpio, false);
}
void button_up_callback(uint8_t gpio_num, button_event_t event) {
if (position_state.value.int_value != POSITION_STATE_STOPPED) {
target_position.value.int_value = current_position.value.int_value;
target_position_changed();
}else{
switch (event) {
case button_event_single_press:
target_position.value.int_value = POSITION_OPEN;
target_position_changed();
break;
case button_event_long_press:
break;
default:
printf("Unknown button event: %d\n", event);
}
}
}
void button_down_callback(uint8_t gpio_num, button_event_t event) {
if (position_state.value.int_value != POSITION_STATE_STOPPED) {
target_position.value.int_value = current_position.value.int_value;
target_position_changed();
}else{
switch (event) {
case button_event_single_press:
target_position.value.int_value = POSITION_CLOSED;
target_position_changed();
break;
case button_event_long_press:
break;
default:
printf("Unknown button event: %d\n", event);
}
}
}
void update_state() {
while (true) {
printf("update_state\n");
relays_write(position_state.value.int_value);
uint8_t position = current_position.value.int_value;
int8_t direction = current_position.value.int_value < target_position.value.int_value ? 1 : -1;
int16_t newPosition = position + direction;
printf("position %u, target %u\n", newPosition, target_position.value.int_value);
current_position.value.int_value = newPosition;
homekit_characteristic_notify(¤t_position, current_position.value);
if (newPosition == target_position.value.int_value) {
printf("reached destination %u\n", newPosition);
position_state.value.int_value = POSITION_STATE_STOPPED;
relays_write(position_state.value.int_value);
homekit_characteristic_notify(&position_state, position_state.value);
vTaskSuspend(updateStateTask);
}
vTaskDelay(pdMS_TO_TICKS(SECONDS_FROM_CLOSED_TO_OPEN * 10));
}
}
void update_state_init() {
xTaskCreate(update_state, "UpdateState", 256, NULL, tskIDLE_PRIORITY, &updateStateTask);
vTaskSuspend(updateStateTask);
}
void window_covering_identify(homekit_value_t _value) {
printf("Curtain identify\n");
}
void on_update_target_position(homekit_characteristic_t *ch, homekit_value_t value, void *context);
homekit_characteristic_t current_position = {
HOMEKIT_DECLARE_CHARACTERISTIC_CURRENT_POSITION(POSITION_CLOSED)
};
homekit_characteristic_t target_position = {
HOMEKIT_DECLARE_CHARACTERISTIC_TARGET_POSITION(POSITION_CLOSED, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(on_update_target_position))
};
homekit_characteristic_t position_state = {
HOMEKIT_DECLARE_CHARACTERISTIC_POSITION_STATE(POSITION_STATE_STOPPED)
};
homekit_accessory_t *accessories[] = {
HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_window_covering, .services=(homekit_service_t*[]) {
HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
HOMEKIT_CHARACTERISTIC(NAME, "Window blind"),
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "None"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "201905261408"),
HOMEKIT_CHARACTERISTIC(MODEL, "Blinds"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.7"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, window_covering_identify),
NULL
}),
HOMEKIT_SERVICE(WINDOW_COVERING, .primary=true, .characteristics=(homekit_characteristic_t*[]) {
HOMEKIT_CHARACTERISTIC(NAME, "Window blind"),
¤t_position,
&target_position,
&position_state,
NULL
}),
NULL
}),
NULL
};
void on_update_target_position(homekit_characteristic_t *ch, homekit_value_t value, void *context) {
target_position_changed();
}
void target_position_changed(){
printf("Update target position to: %u\n", target_position.value.int_value);
if (target_position.value.int_value == current_position.value.int_value) {
printf("Current position equal to target. Stopping.\n");
position_state.value.int_value = POSITION_STATE_STOPPED;
relays_write(position_state.value.int_value);
homekit_characteristic_notify(&position_state, position_state.value);
vTaskSuspend(updateStateTask);
} else {
position_state.value.int_value = target_position.value.int_value > current_position.value.int_value
? POSITION_STATE_OPENING
: POSITION_STATE_CLOSING;
homekit_characteristic_notify(&position_state, position_state.value);
vTaskResume(updateStateTask);
}
}
homekit_server_config_t config = {
.accessories = accessories,
.password = "345-58-410",
.setupId="0LK7",
};
void on_wifi_ready() {
homekit_server_init(&config);
}
void user_init(void) {
uart_set_baud(0, 115200);
gpio_init();
wifi_config_init("blinds", NULL, on_wifi_ready);
update_state_init();
if (button_create(button_up, 0, 1000, button_up_callback)) {
printf("Failed to initialize button up\n");
}
if (button_create(button_down, 0, 1000, button_down_callback)) {
printf("Failed to initialize button down\n");
}
}
Hi Maxim,
I have a problem with my blinds setup, I used the sonoff_dual_blinds example to build upon. So after compiling everything is working correctly.
After adding my blinds to HomeKit the motor (see scheme below) turns left and right when I open and close the blinds. ( from 0 to 100 in 15 seconds / 100 to 0 in 15 seconds).
I can't figure out why the Up button does not work? and the 'Button' button should it not stop the up and down movement when pressed?
Maybe I have looked at it for too long and can't see the solution anymore? :weary:
Scheme
Code