Skip to content

Commit

Permalink
Sonoff Basic PWM example (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbsqp authored and maximkulkin committed Mar 5, 2018
1 parent 9e32115 commit aca8f83
Show file tree
Hide file tree
Showing 10 changed files with 863 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -1 +1,5 @@
/wifi.h
/examples/*/wifi.h
/examples/*/build
/examples/*/firmware
.DS_Store
21 changes: 21 additions & 0 deletions examples/sonoff_basic_pwm/Makefile
@@ -0,0 +1,21 @@
PROGRAM = sonoff_basic_dimmer

EXTRA_COMPONENTS = \
extras/http-parser \
extras/dhcpserver \
$(abspath ../../components/wifi_config) \
$(abspath ../../components/wolfssl) \
$(abspath ../../components/cJSON) \
$(abspath ../../components/homekit)

FLASH_SIZE ?= 8
FLASH_MODE ?= dout
FLASH_SPEED ?= 40
HOMEKIT_SPI_FLASH_BASE_ADDR ?= 0x7A000

EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS

include $(SDK_PATH)/common.mk

monitor:
$(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT)
109 changes: 109 additions & 0 deletions examples/sonoff_basic_pwm/button.c
@@ -0,0 +1,109 @@
#include <string.h>
#include <esplibs/libmain.h>
#include "button.h"

typedef struct _button {
uint8_t gpio_num;
button_callback_fn callback;

uint16_t debounce_time;
uint16_t long_press_time;

bool pressed_value;

uint32_t last_press_time;
uint32_t last_event_time;

struct _button *next;
} button_t;


button_t *buttons = NULL;


static button_t *button_find_by_gpio(const uint8_t gpio_num) {
button_t *button = buttons;
while (button && button->gpio_num != gpio_num)
button = button->next;

return button;
}


void button_intr_callback(uint8_t gpio) {
button_t *button = button_find_by_gpio(gpio);
if (!button)
return;

uint32_t now = xTaskGetTickCountFromISR();
if ((now - button->last_event_time)*portTICK_PERIOD_MS < button->debounce_time) {
// debounce time, ignore events
return;
}
button->last_event_time = now;
if (gpio_read(button->gpio_num) == button->pressed_value) {
// Record when the button is pressed down.
button->last_press_time = now;
} else {
// The button is released. Handle the use cases.
if ((now - button->last_press_time) * portTICK_PERIOD_MS > button->long_press_time) {
button->callback(button->gpio_num, button_event_long_press);
} else {
button->callback(button->gpio_num, button_event_single_press);
}
}
}

int button_create(const uint8_t gpio_num, bool pressed_value, uint16_t long_press_time, button_callback_fn callback) {
button_t *button = button_find_by_gpio(gpio_num);
if (button)
return -1;

button = malloc(sizeof(button_t));
memset(button, 0, sizeof(*button));
button->gpio_num = gpio_num;
button->callback = callback;
button->pressed_value = pressed_value;

// times in milliseconds
button->debounce_time = 50;
button->long_press_time = long_press_time;

uint32_t now = xTaskGetTickCountFromISR();
button->last_event_time = now;
button->last_press_time = now;

button->next = buttons;
buttons = button;

gpio_set_pullup(button->gpio_num, true, true);
gpio_set_interrupt(button->gpio_num, GPIO_INTTYPE_EDGE_ANY, button_intr_callback);

return 0;
}


void button_delete(const uint8_t gpio_num) {
if (!buttons)
return;

button_t *button = NULL;
if (buttons->gpio_num == gpio_num) {
button = buttons;
buttons = buttons->next;
} else {
button_t *b = buttons;
while (b->next) {
if (b->next->gpio_num == gpio_num) {
button = b->next;
b->next = b->next->next;
break;
}
}
}

if (button) {
gpio_set_interrupt(gpio_num, GPIO_INTTYPE_EDGE_ANY, NULL);
}
}

26 changes: 26 additions & 0 deletions examples/sonoff_basic_pwm/button.h
@@ -0,0 +1,26 @@
#pragma once

typedef enum {
button_event_single_press,
button_event_long_press,
} button_event_t;

typedef void (*button_callback_fn)(uint8_t gpio_num, button_event_t event);

/**
Starts monitoring the given GPIO pin for the pressed value. Events are recieved through the callback.
@param gpio_num The GPIO pin that should be monitored
@param pressed_value The expected value when the button is pressed. For buttons connected to ground this is 0/false, for other buttons this might be 1/true.
@param long_press_time The duration that should be recognized as a long press, in miliseconds.
@param callback The callback that is called when an "button" event occurs.
@return A negative integer if this method fails.
*/
int button_create(uint8_t gpio_num, bool pressed_value, uint16_t long_press_time, button_callback_fn callback);

/**
Removes the given GPIO pin from monitoring.
@param gpio_num The GPIO pin that should be removed from monitoring
*/
void button_delete(uint8_t gpio_num);
7 changes: 7 additions & 0 deletions examples/sonoff_basic_pwm/info.txt
@@ -0,0 +1,7 @@
Modification of sonoff_basic_toggle example with PWM dimming as implemented in eps-open-rtos/examples/pwm_test.c

IMPORTANT: This is a proof of concept demonstration and should NOT be modified to attempt to control AC directly via PWM to the relay or by swapping out the relay for TRIAC!

Indirect approach needed to dim AC i.e. via separate daughter board with a TRIAC and zero-crossing detection circuit. Zero crossing detection facilitates synchronise of the PWM with the AC to stop flickering. Google "ac dimming" for more information.


0 comments on commit aca8f83

Please sign in to comment.