From 99c9b1671c2b2625e23ba63592b34445ebb5bb78 Mon Sep 17 00:00:00 2001 From: arendst Date: Tue, 15 Aug 2017 22:09:52 +0200 Subject: [PATCH] Add Sonoff B1 Support. AiLight is experimental --- sonoff/_releasenotes.ino | 6 +- sonoff/sonoff.ino | 3 +- sonoff/sonoff_template.h | 4 +- sonoff/xdrv_snfled.ino | 155 ++++++++++++++++----------------------- sonoff/xdrv_wemohue.ino | 23 +++++- sonoff/xdrv_ws2812.ino | 68 +++++++++-------- 6 files changed, 128 insertions(+), 131 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index ac7a5ceb2..cc9d81c0b 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,7 +1,9 @@ -/* 5.5.2f +/* 5.5.2g * Fix Sonoff Pow intermittent exception 0 * 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 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5b559f964..97a0c15bc 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - 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 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 // Ota #include // Webserver, Updater #include // WemoHue, IRremote, Domoticz +#include // Ws2812, Sonoff Led hue support #ifdef USE_WEBSERVER #include // WifiManager, Webserver #include // WifiManager diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bd7e2cadc..333ed89e9 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -117,9 +117,9 @@ enum fpins_t { GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow) GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) GPIO_ADC0, // ADC + GPIO_DI, // my92x1 PWM input + GPIO_DCKI, // my92x1 CLK input GPIO_USER, // User configurable - GPIO_DI, // my9231 PWM input - GPIO_DCKI, // my9231 CLK input GPIO_MAX }; /********************************************************************************************/ diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index 8161a077b..525c245f4 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -80,7 +80,6 @@ void sl_my92x1_command(uint8_t chips, uint8_t command) { uint8_t command_data; -// ets_intr_lock(); os_delay_us(12); // TStop > 12us. // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // 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. sl_di_pulse(16); 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. - for (uint8_t channel = 0; channel < 6; channel++) { // RGBWC0 6CH - duty_current = duty[channel]; // RGBWC Channel + for (uint8_t channel = 0; channel < 6; channel++) { // WC0GRB 6CH + duty_current = duty[channel]; for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data digitalWrite(sl_pdcki, LOW); 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. sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. 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. for (uint8_t channel = 0; channel < 4; channel++) { // RGBW 4CH 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. sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. 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 } else if (5 == sfl_flg) { // 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 } } @@ -211,7 +205,7 @@ void sl_init(void) void sl_setDim(uint8_t myDimmer) { float temp; - + if ((1 == sfl_flg) && (100 == myDimmer)) { myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 } @@ -371,76 +365,17 @@ void sl_animate() void sl_rgb2hsb(float *hue, float *sat, float *bri) { - sl_setDim(sysCfg.led_dimmer[0]); + RgbColor dcolor; - float r = (float)(sl_dcolor[0] / 255.0f); - float g = (float)(sl_dcolor[1] / 255.0f); - float b = (float)(sl_dcolor[2] / 255.0f); - - float max = fmax(fmax(r, g), b); - float min = fmin(fmin(r, g), 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(); -} + sl_setDim(sysCfg.led_dimmer[0]); + dcolor.R = sl_dcolor[0]; + dcolor.G = sl_dcolor[1]; + dcolor.B = sl_dcolor[2]; + HsbColor hsb = HsbColor(dcolor); + *hue = hsb.H; + *sat = hsb.S; + *bri = hsb.B; +} /********************************************************************************************/ @@ -458,7 +393,8 @@ void sl_replaceHSB(String *response) } else { response->replace("{h}", "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,33 +405,68 @@ void sl_getHSB(float *hue, float *sat, float *bri) } else { *hue = 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]; + HsbColor hsb; + float my_ct; + /* char log[LOGSZ]; char stemp1[10]; char stemp2[10]; char stemp3[10]; + char stemp4[10]; dtostrf(hue, 1, 3, stemp1); dtostrf(sat, 1, 3, stemp2); 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); */ + 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)); mqtt_publish_topic_P(5, "COLOR", svalue); } else { uint8_t tmp = (uint8_t)(bri * 100); sysCfg.led_dimmer[0] = tmp; - sl_prepPower(svalue, sizeof(svalue)); - mqtt_publish_topic_P(5, "DIMMER", svalue); + 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)); + mqtt_publish_topic_P(5, "DIMMER", svalue); + } } } diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 08bcba878..3d0aa30fc 100644 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -533,6 +533,7 @@ void hue_lights(String *path) float bri = 0; float hue = 0; float sat = 0; + float ct = 0; bool resp = false; bool on = false; bool change = false; @@ -636,9 +637,21 @@ void hue_lights(String *path) response.replace("{res}", String(tmp)); 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 (sfl_flg) { - sl_setHSB(hue, sat, bri); + sl_setHSB(hue, sat, bri, ct); #ifdef USE_WS2812 } else if (pin[GPIO_WS2812] < 99) { @@ -655,6 +668,9 @@ void hue_lights(String *path) else { response = FPSTR(HUE_ERROR_JSON); } + +addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); + webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID @@ -678,6 +694,9 @@ void hue_lights(String *path) void hue_groups(String *path) { +/* + * http://sonoff/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"}) + */ String response = "{}"; if (path->endsWith("/0")) { @@ -721,7 +740,7 @@ void handle_hue_api(String *path) else if (path->endsWith("/")) hue_auth(path); // New HUE App setup else if (path->endsWith("/config")) hue_config(path); else if (path->indexOf("/lights") >= 0) hue_lights(path); - else if (path->indexOf("/groups") >= 0) hue_groups(path); + else if (path->indexOf("/groups") >= 0) hue_groups(path); else if (path->endsWith("/schedules")) hue_todo(path); else if (path->endsWith("/sensors")) hue_todo(path); else if (path->endsWith("/scenes")) hue_todo(path); diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino index 93a6e5fe4..92fe3e349 100644 --- a/sonoff/xdrv_ws2812.ino +++ b/sonoff/xdrv_ws2812.ino @@ -22,7 +22,7 @@ * WS2812 Leds using NeopixelBus library \*********************************************************************************************/ -#include +//#include // Global defined as also used by Sonoff Led #ifdef USE_WS2812_DMA #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) { RgbColor mcolor; @@ -504,6 +473,41 @@ void ws2812_init(uint8_t powerbit) 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 \*********************************************************************************************/