Add Sonoff B1 Support. AiLight is experimental

This commit is contained in:
arendst 2017-08-15 22:09:52 +02:00
parent 5fdc5e890a
commit 99c9b1671c
6 changed files with 128 additions and 131 deletions

View File

@ -1,7 +1,9 @@
/* 5.5.2f /* 5.5.2g
* Fix Sonoff Pow intermittent exception 0 * Fix Sonoff Pow intermittent exception 0
* Change Sonoff Pow sending Domoticz telemetry data only * Change Sonoff Pow sending Domoticz telemetry data only
* Add Ai-Thinker RGBW led (AiLight) and Sonoff B1 support (experimental) * Add Sonoff B1 support
* Add Ai-Thinker RGBW led (AiLight) (experimental)
* Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k1 code space)
* *
* 5.5.2 20170808 * 5.5.2 20170808
* Extent max number of WS2812 pixels from 256 to 512 (#667) * Extent max number of WS2812 pixels from 256 to 512 (#667)

View File

@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)" - Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/ ====================================================*/
#define VERSION 0x05050206 // 5.5.2f #define VERSION 0x05050207 // 5.5.2g
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
enum week_t {Last, First, Second, Third, Fourth}; enum week_t {Last, First, Second, Third, Fourth};
@ -172,6 +172,7 @@ enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCf
#include <ESP8266httpUpdate.h> // Ota #include <ESP8266httpUpdate.h> // Ota
#include <StreamString.h> // Webserver, Updater #include <StreamString.h> // Webserver, Updater
#include <ArduinoJson.h> // WemoHue, IRremote, Domoticz #include <ArduinoJson.h> // WemoHue, IRremote, Domoticz
#include <NeoPixelBus.h> // Ws2812, Sonoff Led hue support
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
#include <ESP8266WebServer.h> // WifiManager, Webserver #include <ESP8266WebServer.h> // WifiManager, Webserver
#include <DNSServer.h> // WifiManager #include <DNSServer.h> // WifiManager

View File

@ -117,9 +117,9 @@ enum fpins_t {
GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow) GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow)
GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow)
GPIO_ADC0, // ADC GPIO_ADC0, // ADC
GPIO_DI, // my92x1 PWM input
GPIO_DCKI, // my92x1 CLK input
GPIO_USER, // User configurable GPIO_USER, // User configurable
GPIO_DI, // my9231 PWM input
GPIO_DCKI, // my9231 CLK input
GPIO_MAX }; GPIO_MAX };
/********************************************************************************************/ /********************************************************************************************/

View File

@ -80,7 +80,6 @@ void sl_my92x1_command(uint8_t chips, uint8_t command)
{ {
uint8_t command_data; uint8_t command_data;
// ets_intr_lock();
os_delay_us(12); // TStop > 12us. os_delay_us(12); // TStop > 12us.
// Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12
// pulse's rising edge convert to command mode. // pulse's rising edge convert to command mode.
@ -104,19 +103,17 @@ void sl_my92x1_command(uint8_t chips, uint8_t command)
// at 16 pulse's falling edge convert to duty mode. // at 16 pulse's falling edge convert to duty mode.
sl_di_pulse(16); sl_di_pulse(16);
os_delay_us(12); // TStop > 12us. os_delay_us(12); // TStop > 12us.
// ets_intr_unlock();
} }
void sl_my9231_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) void sl_my9231_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c)
{ {
uint16_t duty_current = 0; uint8_t duty_current = 0;
uint16_t duty[6] = { duty_r, duty_g, duty_b, duty_w, duty_c, 0 }; // Definition for RGBWC channels uint8_t duty[6] = { duty_w, duty_c, 0, duty_g, duty_r, duty_b }; // Definition for RGBWC channels
// ets_intr_lock();
os_delay_us(12); // TStop > 12us. os_delay_us(12); // TStop > 12us.
for (uint8_t channel = 0; channel < 6; channel++) { // RGBWC0 6CH for (uint8_t channel = 0; channel < 6; channel++) { // WC0GRB 6CH
duty_current = duty[channel]; // RGBWC Channel duty_current = duty[channel];
for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data
digitalWrite(sl_pdcki, LOW); digitalWrite(sl_pdcki, LOW);
digitalWrite(sl_pdi, (duty_current & 0x80)); digitalWrite(sl_pdi, (duty_current & 0x80));
@ -131,16 +128,14 @@ void sl_my9231_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t
os_delay_us(12); // TStart > 12us. Ready for send DI pulse. os_delay_us(12); // TStart > 12us. Ready for send DI pulse.
sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data.
os_delay_us(12); // TStop > 12us. os_delay_us(12); // TStop > 12us.
// ets_intr_unlock();
} }
void sl_my9291_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w) void sl_my9291_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w)
{ {
uint16_t duty_current = 0; uint8_t duty_current = 0;
uint16_t duty[4] = { duty_r, duty_g, duty_b, duty_w }; // Definition for RGBW channels uint8_t duty[4] = { duty_r, duty_g, duty_b, duty_w }; // Definition for RGBW channels
// ets_intr_lock();
os_delay_us(12); // TStop > 12us. os_delay_us(12); // TStop > 12us.
for (uint8_t channel = 0; channel < 4; channel++) { // RGBW 4CH for (uint8_t channel = 0; channel < 4; channel++) { // RGBW 4CH
duty_current = duty[channel]; // RGBW Channel duty_current = duty[channel]; // RGBW Channel
@ -158,7 +153,6 @@ void sl_my9291_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t
os_delay_us(12); // TStart > 12us. Ready for send DI pulse. os_delay_us(12); // TStart > 12us. Ready for send DI pulse.
sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data.
os_delay_us(12); // TStop > 12us. os_delay_us(12); // TStop > 12us.
// ets_intr_unlock();
} }
/********************************************************************************************/ /********************************************************************************************/
@ -198,7 +192,7 @@ void sl_init(void)
sl_my92x1_command(1, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM sl_my92x1_command(1, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM
} else if (5 == sfl_flg) { } else if (5 == sfl_flg) {
// Clear all duty register // Clear all duty register
sl_dcki_pulse(48); // 2 * 24 bits sl_dcki_pulse(64); // 2 * 32 bits
sl_my92x1_command(2, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM sl_my92x1_command(2, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM
} }
} }
@ -371,75 +365,16 @@ void sl_animate()
void sl_rgb2hsb(float *hue, float *sat, float *bri) void sl_rgb2hsb(float *hue, float *sat, float *bri)
{ {
RgbColor dcolor;
sl_setDim(sysCfg.led_dimmer[0]); sl_setDim(sysCfg.led_dimmer[0]);
dcolor.R = sl_dcolor[0];
float r = (float)(sl_dcolor[0] / 255.0f); dcolor.G = sl_dcolor[1];
float g = (float)(sl_dcolor[1] / 255.0f); dcolor.B = sl_dcolor[2];
float b = (float)(sl_dcolor[2] / 255.0f); HsbColor hsb = HsbColor(dcolor);
*hue = hsb.H;
float max = fmax(fmax(r, g), b); *sat = hsb.S;
float min = fmin(fmin(r, g), b); *bri = hsb.B;
*bri = (max + min) / 2.0f;
if (max == min) {
*hue = *sat = 0.0f;
} else {
float d = max - min;
*sat = (*bri > 0.5f) ? d / (2.0f - max - min) : d / (max + min);
if (r > g && r > b) {
*hue = (g - b) / d + (g < b ? 6.0f : 0.0f);
}
else if (g > b) {
*hue = (b - r) / d + 2.0f;
}
else {
*hue = (r - g) / d + 4.0f;
}
*hue /= 6.0f;
}
}
float sl_hue2rgb(float p, float q, float t)
{
if (t < 0.0f) {
t += 1.0f;
}
if (t > 1.0f) {
t -= 1.0f;
}
if (t < 1.0f / 6.0f) {
return p + (q - p) * 6.0f * t;
}
if (t < 1.0f / 2.0f) {
return q;
}
if (t < 2.0f / 3.0f) {
return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
}
return p;
}
void sl_hsb2rgb(float hue, float sat, float bri)
{
float r;
float g;
float b;
if (sat == 0.0f) {
r = g = b = bri;
} else {
float q = bri < 0.5f ? bri * (1.0f + sat) : bri + sat - bri * sat;
float p = 2.0f * bri - q;
r = sl_hue2rgb(p, q, hue + 1.0f / 3.0f);
g = sl_hue2rgb(p, q, hue);
b = sl_hue2rgb(p, q, hue - 1.0f / 3.0f);
}
sl_dcolor[0] = (uint8_t)(r * 255 + 0.5f);
sl_dcolor[1] = (uint8_t)(g * 255 + 0.5f);
sl_dcolor[2] = (uint8_t)(b * 255 + 0.5f);
sl_setColor();
} }
/********************************************************************************************/ /********************************************************************************************/
@ -458,7 +393,8 @@ void sl_replaceHSB(String *response)
} else { } else {
response->replace("{h}", "0"); response->replace("{h}", "0");
response->replace("{s}", "0"); response->replace("{s}", "0");
response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); // response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0])));
response->replace("{b}", String((uint8_t)(0.01f * (float)sysCfg.led_dimmer[0])));
} }
} }
@ -469,34 +405,69 @@ void sl_getHSB(float *hue, float *sat, float *bri)
} else { } else {
*hue = 0; *hue = 0;
*sat = 0; *sat = 0;
*bri = (2.54f * (float)sysCfg.led_dimmer[0]); // *bri = (2.54f * (float)sysCfg.led_dimmer[0]);
*bri = (0.01f * (float)sysCfg.led_dimmer[0]);
} }
} }
void sl_setHSB(float hue, float sat, float bri) void sl_setHSB(float hue, float sat, float bri, float ct)
{ {
char svalue[MESSZ]; char svalue[MESSZ];
HsbColor hsb;
float my_ct;
/* /*
char log[LOGSZ]; char log[LOGSZ];
char stemp1[10]; char stemp1[10];
char stemp2[10]; char stemp2[10];
char stemp3[10]; char stemp3[10];
char stemp4[10];
dtostrf(hue, 1, 3, stemp1); dtostrf(hue, 1, 3, stemp1);
dtostrf(sat, 1, 3, stemp2); dtostrf(sat, 1, 3, stemp2);
dtostrf(bri, 1, 3, stemp3); dtostrf(bri, 1, 3, stemp3);
snprintf_P(log, sizeof(log), PSTR("LED: Hue %s, Sat %s, Bri %s"), stemp1, stemp2, stemp3); dtostrf(ct, 1, 3, stemp4);
snprintf_P(log, sizeof(log), PSTR("HUE: Set Hue %s, Sat %s, Bri %s, Ct %s"), stemp1, stemp2, stemp3, stemp4);
addLog(LOG_LEVEL_DEBUG, log); addLog(LOG_LEVEL_DEBUG, log);
*/ */
if (sfl_flg > 2) { if (sfl_flg > 2) {
sl_hsb2rgb(hue, sat, bri); hsb.H = hue;
hsb.S = sat;
hsb.B = bri;
RgbColor tmp = RgbColor(hsb);
sl_dcolor[0] = tmp.R;
sl_dcolor[1] = tmp.G;
sl_dcolor[2] = tmp.B;
sl_setColor();
sl_prepPower(svalue, sizeof(svalue)); sl_prepPower(svalue, sizeof(svalue));
mqtt_publish_topic_P(5, "COLOR", svalue); mqtt_publish_topic_P(5, "COLOR", svalue);
} else { } else {
uint8_t tmp = (uint8_t)(bri * 100); uint8_t tmp = (uint8_t)(bri * 100);
sysCfg.led_dimmer[0] = tmp; sysCfg.led_dimmer[0] = tmp;
if (2 == sfl_flg) {
if (ct > 0) {
my_ct = ct - 0.306;
if (my_ct > 0.694) { // >500 (Warm)
my_ct = 0.694;
}
float fcold = 367 * (0.694 - my_ct); // 0 - 255
float fwarm = 367 * my_ct; // 0 - 255
float fmax = (fwarm > fcold) ? fwarm : fcold;
float fbri = 100 / (fmax / 2.55); // Scale to 255
if (bri < 1) {
bri = bri + 0.01; // Adjust for sl_setColor
}
sl_dcolor[0] = (uint8_t)(fcold * fbri * bri); // Cold
sl_dcolor[1] = (uint8_t)(fwarm * fbri * bri); // Warm
sl_setColor();
}
sl_prepPower(svalue, sizeof(svalue));
mqtt_publish_topic_P(5, "COLOR", svalue);
} else {
sl_prepPower(svalue, sizeof(svalue)); sl_prepPower(svalue, sizeof(svalue));
mqtt_publish_topic_P(5, "DIMMER", svalue); mqtt_publish_topic_P(5, "DIMMER", svalue);
} }
}
} }
/*********************************************************************************************\ /*********************************************************************************************\

View File

@ -533,6 +533,7 @@ void hue_lights(String *path)
float bri = 0; float bri = 0;
float hue = 0; float hue = 0;
float sat = 0; float sat = 0;
float ct = 0;
bool resp = false; bool resp = false;
bool on = false; bool on = false;
bool change = false; bool change = false;
@ -636,9 +637,21 @@ void hue_lights(String *path)
response.replace("{res}", String(tmp)); response.replace("{res}", String(tmp));
change = true; change = true;
} }
if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm)
tmp = hue_json["ct"];
ct = (float)tmp / 500.0f;
if (resp) {
response += ",";
}
response += FPSTR(HUE_LIGHT_RESPONSE_JSON);
response.replace("{id}", String(device));
response.replace("{cmd}", "ct");
response.replace("{res}", String(tmp));
change = true;
}
if (change) { if (change) {
if (sfl_flg) { if (sfl_flg) {
sl_setHSB(hue, sat, bri); sl_setHSB(hue, sat, bri, ct);
#ifdef USE_WS2812 #ifdef USE_WS2812
} }
else if (pin[GPIO_WS2812] < 99) { else if (pin[GPIO_WS2812] < 99) {
@ -655,6 +668,9 @@ void hue_lights(String *path)
else { else {
response = FPSTR(HUE_ERROR_JSON); response = FPSTR(HUE_ERROR_JSON);
} }
addLog(LOG_LEVEL_DEBUG_MORE, response.c_str());
webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); webServer->send(200, FPSTR(HDR_CTYPE_JSON), response);
} }
else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID
@ -678,6 +694,9 @@ void hue_lights(String *path)
void hue_groups(String *path) void hue_groups(String *path)
{ {
/*
* http://sonoff/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"})
*/
String response = "{}"; String response = "{}";
if (path->endsWith("/0")) { if (path->endsWith("/0")) {

View File

@ -22,7 +22,7 @@
* WS2812 Leds using NeopixelBus library * WS2812 Leds using NeopixelBus library
\*********************************************************************************************/ \*********************************************************************************************/
#include <NeoPixelBus.h> //#include <NeoPixelBus.h> // Global defined as also used by Sonoff Led
#ifdef USE_WS2812_DMA #ifdef USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1) #if (USE_WS2812_CTYPE == 1)
@ -145,37 +145,6 @@ void ws2812_setColor(uint16_t led, char* colstr)
} }
} }
void ws2812_replaceHSB(String *response)
{
ws2812_setDim(sysCfg.ws_dimmer);
HsbColor hsb = HsbColor(dcolor);
response->replace("{h}", String((uint16_t)(65535.0f * hsb.H)));
response->replace("{s}", String((uint8_t)(254.0f * hsb.S)));
response->replace("{b}", String((uint8_t)(254.0f * hsb.B)));
}
void ws2812_getHSB(float *hue, float *sat, float *bri)
{
ws2812_setDim(sysCfg.ws_dimmer);
HsbColor hsb = HsbColor(dcolor);
*hue = hsb.H;
*sat = hsb.S;
*bri = hsb.B;
}
void ws2812_setHSB(float hue, float sat, float bri)
{
char rgb[7];
HsbColor hsb;
hsb.H = hue;
hsb.S = sat;
hsb.B = bri;
RgbColor tmp = RgbColor(hsb);
sprintf(rgb,"%02X%02X%02X", tmp.R, tmp.G, tmp.B);
ws2812_setColor(0,rgb);
}
void ws2812_getColor(uint16_t led, char* svalue, uint16_t ssvalue) void ws2812_getColor(uint16_t led, char* svalue, uint16_t ssvalue)
{ {
RgbColor mcolor; RgbColor mcolor;
@ -504,6 +473,41 @@ void ws2812_init(uint8_t powerbit)
ws2812_pixels(); ws2812_pixels();
} }
/*********************************************************************************************\
* Hue support
\*********************************************************************************************/
void ws2812_replaceHSB(String *response)
{
ws2812_setDim(sysCfg.ws_dimmer);
HsbColor hsb = HsbColor(dcolor);
response->replace("{h}", String((uint16_t)(65535.0f * hsb.H)));
response->replace("{s}", String((uint8_t)(254.0f * hsb.S)));
response->replace("{b}", String((uint8_t)(254.0f * hsb.B)));
}
void ws2812_getHSB(float *hue, float *sat, float *bri)
{
ws2812_setDim(sysCfg.ws_dimmer);
HsbColor hsb = HsbColor(dcolor);
*hue = hsb.H;
*sat = hsb.S;
*bri = hsb.B;
}
void ws2812_setHSB(float hue, float sat, float bri)
{
char rgb[7];
HsbColor hsb;
hsb.H = hue;
hsb.S = sat;
hsb.B = bri;
RgbColor tmp = RgbColor(hsb);
sprintf(rgb,"%02X%02X%02X", tmp.R, tmp.G, tmp.B);
ws2812_setColor(0,rgb);
}
/*********************************************************************************************\ /*********************************************************************************************\
* Commands * Commands
\*********************************************************************************************/ \*********************************************************************************************/