From 1b4290e8f6d0e1e0b4a118c3fc140f3da4dbe95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Wed, 18 Oct 2017 21:38:30 +0200 Subject: [PATCH 1/3] Move IR code to its own module --- code/espurna/config/arduino.h | 1 + code/espurna/config/general.h | 115 +++++++++++++++++++- code/espurna/config/hardware.h | 90 ++-------------- code/espurna/ir.ino | 104 ++++++++++++++++++ code/espurna/light.ino | 34 ++++-- code/espurna/light_ir.ino | 189 ++++++--------------------------- 6 files changed, 284 insertions(+), 249 deletions(-) create mode 100644 code/espurna/ir.ino diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index 677a1713..0e2c2c86 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -66,6 +66,7 @@ //#define HOMEASSISTANT_SUPPORT 0 //#define I2C_SUPPORT 1 //#define INFLUXDB_SUPPORT 0 +//#define IR_SUPPORT 1 //#define MDNS_SUPPORT 0 //#define NOFUSS_SUPPORT 1 //#define NTP_SUPPORT 0 diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index dcca6654..d9bd1469 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -495,6 +495,7 @@ PROGMEM const char* const custom_reset_string[] = { #define LIGHT_MAX_PWM 4095 // Maximum PWM value #define LIGHT_MAX_VALUE 255 // Maximum light value #define LIGHT_MAX_BRIGHTNESS 255 // Maximun brightness value +#define LIGHT_STEP 32 // Step size #define LIGHT_USE_COLOR 1 // Use 3 first channels as RGB #define LIGHT_USE_WHITE 0 // Use white channel whenever RGB have the same value #define LIGHT_USE_GAMMA 0 // Use gamma correction for color channels @@ -691,10 +692,122 @@ PROGMEM const char* const custom_reset_string[] = { // Both ALEXA_SUPPORT and alexaEnabled should be 1 for Alexa support to work. #define ALEXA_ENABLED 1 - // ----------------------------------------------------------------------------- // RFBRIDGE // ----------------------------------------------------------------------------- #define RF_SEND_TIMES 4 // How many times to send the message #define RF_SEND_DELAY 250 // Interval between sendings in ms + +// ----------------------------------------------------------------------------- +// IR +// ----------------------------------------------------------------------------- + +#ifndef IR_SUPPORT +#define IR_SUPPORT 0 // Do not build with IR support by default +#endif + +#ifndef IR_PIN +#define IR_PIN 4 // IR LED +#endif + +// 24 Buttons Set of the IR Remote +#ifndef IR_BUTTON_SET +#define IR_BUTTON_SET 1 +#endif + +// IR Button modes +#define IR_BUTTON_MODE_NONE 0 +#define IR_BUTTON_MODE_RGB 1 +#define IR_BUTTON_MODE_HSV 2 +#define IR_BUTTON_MODE_BRIGHTER 3 +#define IR_BUTTON_MODE_STATE 4 +#define IR_BUTTON_MODE_EFFECT 5 + +#define LIGHT_EFFECT_SOLID 0 +#define LIGHT_EFFECT_FLASH 1 +#define LIGHT_EFFECT_STROBE 2 +#define LIGHT_EFFECT_FADE 3 +#define LIGHT_EFFECT_SMOOTH 4 + +//Remote Buttons SET 1 (for the original Remote shipped with the controller) +#if IR_BUTTON_SET == 1 + + #define IR_BUTTON_COUNT 24 + + const unsigned long IR_BUTTON[IR_BUTTON_COUNT][3] PROGMEM = { + + { 0xFF906F, IR_BUTTON_MODE_BRIGHTER, 1 }, + { 0xFFB847, IR_BUTTON_MODE_BRIGHTER, 0 }, + { 0xFFF807, IR_BUTTON_MODE_STATE, 0 }, + { 0xFFB04F, IR_BUTTON_MODE_STATE, 1 }, + + { 0xFF9867, IR_BUTTON_MODE_RGB, 0xFF0000 }, + { 0xFFD827, IR_BUTTON_MODE_RGB, 0x00FF00 }, + { 0xFF8877, IR_BUTTON_MODE_RGB, 0x0000FF }, + { 0xFFA857, IR_BUTTON_MODE_RGB, 0xFFFFFF }, + + { 0xFFE817, IR_BUTTON_MODE_RGB, 0xD13A01 }, + { 0xFF48B7, IR_BUTTON_MODE_RGB, 0x00E644 }, + { 0xFF6897, IR_BUTTON_MODE_RGB, 0x0040A7 }, + { 0xFFB24D, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_FLASH }, + + { 0xFF02FD, IR_BUTTON_MODE_RGB, 0xE96F2A }, + { 0xFF32CD, IR_BUTTON_MODE_RGB, 0x00BEBF }, + { 0xFF20DF, IR_BUTTON_MODE_RGB, 0x56406F }, + { 0xFF00FF, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_STROBE }, + + { 0xFF50AF, IR_BUTTON_MODE_RGB, 0xEE9819 }, + { 0xFF7887, IR_BUTTON_MODE_RGB, 0x00799A }, + { 0xFF708F, IR_BUTTON_MODE_RGB, 0x944E80 }, + { 0xFF58A7, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_FADE }, + + { 0xFF38C7, IR_BUTTON_MODE_RGB, 0xFFFF00 }, + { 0xFF28D7, IR_BUTTON_MODE_RGB, 0x0060A1 }, + { 0xFFF00F, IR_BUTTON_MODE_RGB, 0xEF45AD }, + { 0xFF30CF, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_SMOOTH } + + }; + +#endif + +//Remote Buttons SET 2 (another identical IR Remote shipped with another controller) +#if IR_BUTTON_SET == 2 + + #define IR_BUTTON_COUNT 24 + + const unsigned long IR_BUTTON[IR_BUTTON_COUNT][3] PROGMEM = { + + { 0xFF00FF, IR_BUTTON_MODE_BRIGHTER, 1 }, + { 0xFF807F, IR_BUTTON_MODE_BRIGHTER, 0 }, + { 0xFF40BF, IR_BUTTON_MODE_STATE, 0 }, + { 0xFFC03F, IR_BUTTON_MODE_STATE, 1 }, + + { 0xFF20DF, IR_BUTTON_MODE_RGB, 0xFF0000 }, + { 0xFFA05F, IR_BUTTON_MODE_RGB, 0x00FF00 }, + { 0xFF609F, IR_BUTTON_MODE_RGB, 0x0000FF }, + { 0xFFE01F, IR_BUTTON_MODE_RGB, 0xFFFFFF }, + + { 0xFF10EF, IR_BUTTON_MODE_RGB, 0xD13A01 }, + { 0xFF906F, IR_BUTTON_MODE_RGB, 0x00E644 }, + { 0xFF50AF, IR_BUTTON_MODE_RGB, 0x0040A7 }, + { 0xFFD02F, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_FLASH }, + + { 0xFF30CF, IR_BUTTON_MODE_RGB, 0xE96F2A }, + { 0xFFB04F, IR_BUTTON_MODE_RGB, 0x00BEBF }, + { 0xFF708F, IR_BUTTON_MODE_RGB, 0x56406F }, + { 0xFFF00F, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_STROBE }, + + { 0xFF08F7, IR_BUTTON_MODE_RGB, 0xEE9819 }, + { 0xFF8877, IR_BUTTON_MODE_RGB, 0x00799A }, + { 0xFF48B7, IR_BUTTON_MODE_RGB, 0x944E80 }, + { 0xFFC837, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_FADE }, + + { 0xFF28D7, IR_BUTTON_MODE_RGB, 0xFFFF00 }, + { 0xFFA857, IR_BUTTON_MODE_RGB, 0x0060A1 }, + { 0xFF6897, IR_BUTTON_MODE_RGB, 0xEF45AD }, + { 0xFFE817, IR_BUTTON_MODE_EFFECT, LIGHT_EFFECT_SMOOTH } + + }; + +#endif diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 24924997..0a692dcc 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -63,12 +63,10 @@ #define LED1_PIN 2 #define LED1_PIN_INVERSE 1 - // Buttons - // No buttons on the D1 MINI alone, but defining it without adding a button doen't create problems - #define BUTTON1_PIN 0 // Connect a pushbutton between D3 and GND, - // it's the same as using a Wemos one button shield - #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH - #define BUTTON1_RELAY 1 + // IR + #define IR_SUPPORT 1 + #define IR_PIN 4 + #define IR_BUTTON_SET 1 // ----------------------------------------------------------------------------- // ESPurna @@ -713,8 +711,11 @@ #define DEVICE "LED_CONTROLLER_20" #define RELAY_PROVIDER RELAY_PROVIDER_LIGHT #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER + #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER #define DUMMY_RELAY_COUNT 1 + //#define LIGHT_PROVIDER_EXPERIMENTAL_RGB_ONLY_HSV_IR + // LEDs #define LED1_PIN 2 #define LED1_PIN_INVERSE 1 @@ -730,79 +731,10 @@ #define LIGHT_CH3_INVERSE 0 #define LIGHT_CH4_INVERSE 0 - #define LIGHT_IR_PIN 4 // IR LED - #define LIGHT_PROVIDER_EXPERIMENTAL_RGB_ONLY_HSV_IR 0 - - // 24 Buttons Set of the IR Remote - #ifndef IR_BUTTONS_SET - #define IR_BUTTONS_SET 1 - #endif - - //Remote Buttons SET 1 (for the original Remote shipped with the controller) - #if IR_BUTTONS_SET == 1 - #define IR_BUTTON_0 0xFF906F // Brightness + - #define IR_BUTTON_1 0xFFB847 // Brightness - - #define IR_BUTTON_2 0xFFF807 // OFF - #define IR_BUTTON_3 0xFFB04F // ON - - #define IR_BUTTON_4 0xFF9867 // RED - #define IR_BUTTON_5 0xFFD827 // GREEN - #define IR_BUTTON_6 0xFF8877 // BLUE - #define IR_BUTTON_7 0xFFA857 // WHITE - - #define IR_BUTTON_8 0xFFE817 // "Red" 1 - #define IR_BUTTON_9 0xFF48B7 // "Green" 1 - #define IR_BUTTON_10 0xFF6897 // "Blue" 1 - #define IR_BUTTON_11 0xFFB24D // FLASH Mode - - #define IR_BUTTON_12 0xFF02FD // "Red" 2 - #define IR_BUTTON_13 0xFF32CD // "Green" 2 - #define IR_BUTTON_14 0xFF20DF // "Blue" 2 - #define IR_BUTTON_15 0xFF00FF // STROBE Mode - - #define IR_BUTTON_16 0xFF50AF // "Red" 3 - #define IR_BUTTON_17 0xFF7887 // "Green" 3 - #define IR_BUTTON_18 0xFF708F // "Blue" 3 - #define IR_BUTTON_19 0xFF58A7 // FADE Mode - - #define IR_BUTTON_20 0xFF38C7 // "Red" 4 - #define IR_BUTTON_21 0xFF28D7 // "Green" 4 - #define IR_BUTTON_22 0xFFF00F // "Blue" 4 - #define IR_BUTTON_23 0xFF30CF // SMOOTH Mode - #endif - - //Remote Buttons SET 2 (another identical IR Remote shipped with another controller) - #if IR_BUTTONS_SET == 2 - #define IR_BUTTON_0 0xFF00FF // Brightness + - #define IR_BUTTON_1 0xFF807F // Brightness - - #define IR_BUTTON_2 0xFF40BF // OFF - #define IR_BUTTON_3 0xFFC03F // ON - - #define IR_BUTTON_4 0xFF20DF // RED - #define IR_BUTTON_5 0xFFA05F // GREEN - #define IR_BUTTON_6 0xFF609F // BLUE - #define IR_BUTTON_7 0xFFE01F // WHITE - - #define IR_BUTTON_8 0xFF10EF // "Red" 1 - #define IR_BUTTON_9 0xFF906F // "Green" 1 - #define IR_BUTTON_10 0xFF50AF // "Blue" 1 - #define IR_BUTTON_11 0xFFD02F // FLASH Mode - - #define IR_BUTTON_12 0xFF30CF // "Red" 2 - #define IR_BUTTON_13 0xFFB04F // "Green" 2 - #define IR_BUTTON_14 0xFF708F // "Blue" 2 - #define IR_BUTTON_15 0xFFF00F // STROBE Mode - - #define IR_BUTTON_16 0xFF08F7 // "Red" 3 - #define IR_BUTTON_17 0xFF8877 // "Green" 3 - #define IR_BUTTON_18 0xFF48B7 // "Blue" 3 - #define IR_BUTTON_19 0xFFC837 // FADE Mode - - #define IR_BUTTON_20 0xFF28D7 // "Red" 4 - #define IR_BUTTON_21 0xFFA857 // "Green" 4 - #define IR_BUTTON_22 0xFF6897 // "Blue" 4 - #define IR_BUTTON_23 0xFFE817 // SMOOTH Mode - #endif + // IR + #define IR_SUPPORT 1 + #define IR_PIN 4 + #define IR_BUTTON_SET 1 // ----------------------------------------------------------------------------- // HUACANXING H801 & H802 diff --git a/code/espurna/ir.ino b/code/espurna/ir.ino new file mode 100644 index 00000000..1b842a7a --- /dev/null +++ b/code/espurna/ir.ino @@ -0,0 +1,104 @@ +/* + +IR MODULE + +Copyright (C) 2016-2017 by Xose Pérez +Copyright (C) 2017 by François Déchery + +*/ + +#if IR_SUPPORT + +#include +#include + +IRrecv * _ir_recv; +decode_results _ir_results; + +// ----------------------------------------------------------------------------- +// PRIVATE +// ----------------------------------------------------------------------------- + +void _irProcessCode(unsigned long code) { + + static unsigned long last_code; + boolean found = false; + + // Repeat last valid code + DEBUG_MSG_P(PSTR("[IR] Received 0x%08X\n"), code); + if (code == 0xFFFFFFFF) { + DEBUG_MSG_P(PSTR("[IR] Processing 0x%08X\n"), code); + code = last_code; + } + + for (unsigned char i = 0; i < IR_BUTTON_COUNT ; i++) { + + unsigned long button_code = pgm_read_dword(&IR_BUTTON[i][0]); + if (code == button_code) { + + unsigned long button_mode = pgm_read_dword(&IR_BUTTON[i][1]); + unsigned long button_value = pgm_read_dword(&IR_BUTTON[i][2]); + + #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE + + if (button_mode == IR_BUTTON_MODE_BRIGHTER) { + lightBrightnessStep(button_value ? 1 : -1); + delay(150); //debounce + } + + if (button_mode == IR_BUTTON_MODE_RGB) { + lightColor(button_value); + } + + /* + if (button_mode == IR_BUTTON_MODE_HSV) { + lightColor(button_value); + } + */ + + #endif + + /* + #if LIGHT_PROVIDER == LIGHT_PROVIDER_FASTLED + if (button_mode == IR_BUTTON_MODE_EFFECT) { + _buttonAnimMode(button_value); + } + #endif + */ + + lightUpdate(true, true); + + found = true; + last_code = code; + break; + + } + + } + + if (!found) { + last_code = 0; + DEBUG_MSG_P(PSTR("[IR] Ignoring code\n")); + } + +} + + +// ----------------------------------------------------------------------------- +// PUBLIC API +// ----------------------------------------------------------------------------- + +void irSetup() { + _ir_recv = new IRrecv(IR_PIN); + _ir_recv->enableIRIn(); +} + +void irLoop() { + if (_ir_recv->decode(&_ir_results)) { + unsigned long code = _ir_results.value; + _irProcessCode(code); + _ir_recv->resume(); // Receive the next value + } +} + +#endif // IR_SUPPORT diff --git a/code/espurna/light.ino b/code/espurna/light.ino index 693827ff..2d815b86 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -53,6 +53,21 @@ const unsigned short gamma_table[LIGHT_MAX_VALUE+1] = { // UTILS // ----------------------------------------------------------------------------- +void _fromLong(unsigned long value, bool brightness) { + + if (brightness) { + _channels[0].value = (value >> 24) & 0xFF; + _channels[1].value = (value >> 16) & 0xFF; + _channels[2].value = (value >> 8) & 0xFF; + _brightness = (value & 0xFF) * LIGHT_MAX_BRIGHTNESS / 255; + } else { + _channels[0].value = (value >> 16) & 0xFF; + _channels[1].value = (value >> 8) & 0xFF; + _channels[2].value = (value) & 0xFF; + } + +} + void _fromRGB(const char * rgb) { char * p = (char *) rgb; @@ -67,16 +82,7 @@ void _fromRGB(const char * rgb) { unsigned long value = strtoul(p, NULL, 16); // RGBA values are interpreted like RGB + brightness - if (strlen(p) > 7) { - _channels[0].value = (value >> 24) & 0xFF; - _channels[1].value = (value >> 16) & 0xFF; - _channels[2].value = (value >> 8) & 0xFF; - _brightness = (value & 0xFF) * LIGHT_MAX_BRIGHTNESS / 255; - } else { - _channels[0].value = (value >> 16) & 0xFF; - _channels[1].value = (value >> 8) & 0xFF; - _channels[2].value = (value) & 0xFF; - } + _fromLong(value, strlen(p) > 7); } @@ -440,6 +446,10 @@ void lightColor(const char * color) { _fromRGB(color); } +void lightColor(unsigned long color) { + _fromLong(color, false); +} + String lightColor() { char rgb[8]; _toRGB(rgb, 8, false); @@ -467,6 +477,10 @@ void lightBrightness(unsigned int b) { _brightness = constrain(b, 0, LIGHT_MAX_BRIGHTNESS); } +void lightBrightnessStep(int steps) { + lightBrightness(_brightness + steps * LIGHT_STEP); +} + // ----------------------------------------------------------------------------- // SETUP // ----------------------------------------------------------------------------- diff --git a/code/espurna/light_ir.ino b/code/espurna/light_ir.ino index 2d013756..4da10f7a 100644 --- a/code/espurna/light_ir.ino +++ b/code/espurna/light_ir.ino @@ -3,7 +3,7 @@ LIGHT (EXPERIMENTAL) IR Copyright (C) 2016-2017 by Xose Pérez -Copyright (C) 2017 by François Déchery +Copyright (C) 2017 by François Déchery ------------------------------------------------------------------------------------------ Features : @@ -24,8 +24,6 @@ Not currently Implemented : #ifdef LIGHT_PROVIDER_EXPERIMENTAL_RGB_ONLY_HSV_IR -#include -#include #include // #### Defined ########################################################################## @@ -37,64 +35,9 @@ Not currently Implemented : #define ANIM3_SPEED 100 // fade speed #define ANIM4_SPEED 700 // smooth speed #define ANIM5_SPEED 200 // party speed - -#define BUTTONS_COUNT 24 #define LED_DURATION 70 // Status led ON duration // #### Variables ######################################################################## -unsigned long r_but_codes[]={ // IR remote buttons codes - IR_BUTTON_0 , // Brightness + - IR_BUTTON_1 , // Brightness - - IR_BUTTON_2 , // OFF - IR_BUTTON_3 , // ON - IR_BUTTON_4 , // Red - IR_BUTTON_5 , // Green - IR_BUTTON_6 , // Blue - IR_BUTTON_7 , // White - IR_BUTTON_8 , // R1 - IR_BUTTON_9 , // G1 - IR_BUTTON_10 , // B1 - IR_BUTTON_11 , // Flash - IR_BUTTON_12 , // R2 - IR_BUTTON_13 , // G2 - IR_BUTTON_14 , // B2 - IR_BUTTON_15 , // Strobe - IR_BUTTON_16 , // R3 - IR_BUTTON_17 , // G3 - IR_BUTTON_18 , // B3 - IR_BUTTON_19 , // Fade - IR_BUTTON_20 , // R4 - IR_BUTTON_21 , // G4 - IR_BUTTON_22 , // B4 - IR_BUTTON_23 // Smooth -}; - -unsigned long r_but_colors[]={ // IR remote buttons colors - 0, // Brightness + - 0, // Brightness - - 0, // OFF - 0, // ON - 0xFF0000, // Red - 0x00FF00, // Green - 0x0000FF, // Blue - 0xFFFFFF, // White - 0xD13A01, // R1 - 0x00E644, // G1 - 0x0040A7, // B1 - 0, // Flash - 0xE96F2A, // R2 - 0x00BEBF, // G2 - 0x56406F, // B2 - 0, // Strobe - 0xEE9819, // R3 - 0x00799A, // G3 - 0x944E80, // B3 - 0, // Fade - 0xFFFF00, // R4 - 0x0060A1, // G4 - 0xEF45AD, // B4 - 0 // Smooth -}; // variables declarations ############################################################### CHSV _cur_color = CHSV(0,255,255); @@ -108,9 +51,6 @@ unsigned long _anim_last_update = millis(); unsigned long _last_ir_button = 0; unsigned long _last_status_led_time = 0; -IRrecv _ir_recv(LIGHT_IR_PIN); //IRrecv _ir_recv(IR_PIN, IR_LED_PIN); dont work. Why ? -decode_results _ir_results; - // ####################################################################################### // #### PRIVATE ########################################################################## @@ -129,75 +69,6 @@ void _flashStatusLed(){ _last_status_led_time=millis(); } -// --------------------------------------------------------------------------------------- -void _loopProcessIR() { - if (_ir_recv.decode(&_ir_results)) { - //dumpIR(&_ir_results); - //DEBUG_MSG_P(PSTR(".\n")); - unsigned long code = _ir_results.value; - DEBUG_MSG_P(PSTR("[IR] received : 0x%X "), code ); - if( code == 0xFFFFFFFF){ - code = _last_ir_button; - DEBUG_MSG_P(PSTR("(Repeat : %X) "), code ); - } - DEBUG_MSG_P(PSTR("=> ") ); - _processIrButtons(code); - _ir_recv.resume(); // Receive the next value - } -} - -// --------------------------------------------------------------------------------------- -void _processIrButtons(unsigned long code) { - //DEBUG_MSG_P(PSTR("IR code : %X\n"), code ); - boolean done=false; - for (int i = 0; i < BUTTONS_COUNT ; i = i + 1) { - if( code == r_but_codes[i] ){ - //DEBUG_MSG_P(PSTR(" : %X -> "), r_but_colors[i] ); - - _last_ir_button = 0; //no repat else if specified - - if(i == 0){ - _buttonBrightness(true); - _last_ir_button = code; - delay(150); //debounce - } - else if(i == 1){ - _buttonBrightness(false); - _last_ir_button = code; - delay(150); //debounce - } - else if(i == 2){ - _buttonPower(false); - } - else if(i == 3){ - _buttonPower(true); - } - else if(i == 11){ - _buttonAnimMode(1); - } - else if(i == 15){ - _buttonAnimMode(2); - } - else if(i == 19){ - _buttonAnimMode(3); - } - else if(i == 23){ - _buttonAnimMode(4); - } - else{ - _buttonColorRVB(r_but_colors[i],0); - } - done=true; - lightUpdate(true, true); - } - } - if(!done){ - _last_ir_button = 0; - //DEBUG_PRINTHEX(code); - DEBUG_MSG_P(PSTR("ignored!\n")); - } -} - // --------------------------------------------------------------------------------------- void _buttonPower(boolean on){ _flashStatusLed(); @@ -289,7 +160,7 @@ CHSV _dimHSV(CHSV color, int offset){ offset=offset*10; int bright=color.v + offset; if(offset ==0){ - return color; + return color; } else if(bright < 1){ bright=1; // no off @@ -316,7 +187,7 @@ void _setBrightness(byte val){ if(val==0){ _cur_status=0; } - _buttonColorHSV(_cur_color,0); + _buttonColorHSV(_cur_color,0); } // --------------------------------------------------------------------------------------- @@ -330,7 +201,7 @@ void _setAnimSpeed(unsigned long speed){ void _setLedsRGB(CRGB rgb){ analogWrite(LIGHT_CH1_PIN, rgb.r); analogWrite(LIGHT_CH2_PIN, rgb.g); - analogWrite(LIGHT_CH3_PIN, rgb.b); + analogWrite(LIGHT_CH3_PIN, rgb.b); if(_cur_anim_mode == 0){ DEBUG_MSG_P(PSTR("RGB=%3u,%3u,%3u\n"), rgb.r, rgb.g, rgb.b); } @@ -528,9 +399,9 @@ void _anim5(boolean init){ _cur_anim_color.v= 255; } unsigned long now= millis(); - if(_cur_anim_step == 1 && now > (_anim_last_update + _cur_anim_speed) ){ + if(_cur_anim_step == 1 && now > (_anim_last_update + _cur_anim_speed) ){ DEBUG_MSG_P(PSTR("[ANIM_%d] Update : "), _cur_anim_mode); - _cur_anim_color.h = random(0,255); + _cur_anim_color.h = random(0,255); _setLedsHSV(_cur_anim_color); _cur_anim_step = 0; _anim_last_update = now; @@ -796,14 +667,14 @@ void lightSetup() { DEBUG_MSG_P(PSTR("[LIGHT] LIGHT_PROVIDER = %d (With IR)\n"), LIGHT_PROVIDER); - pinMode(LIGHT_CH1_PIN, OUTPUT); + pinMode(LIGHT_CH1_PIN, OUTPUT); pinMode(LIGHT_CH2_PIN, OUTPUT); pinMode(LIGHT_CH3_PIN, OUTPUT); _ir_recv.enableIRIn(); // Start the receiver //confirmRgb(); - + _cur_color = _romLoadColor(); _lightColorRestore(); @@ -849,12 +720,12 @@ void lightUpdate(bool save, bool forward) { //root["color_hsv"] = lightColor(); //root["brightness"] = _cur_color.v; - // RGB channels + // RGB channels //JsonArray& channels = root.createNestedArray("channels"); //for (unsigned char id=0; id < lightChannels(); id++) { // channels.add(lightChannel(id)); //} - + // Relay JsonArray& relay = root.createNestedArray("relayStatus"); relay.add(_cur_status); @@ -927,7 +798,7 @@ unsigned int lightChannel(unsigned char id) { return current_rvb.b; } else{ - DEBUG_MSG_P(PSTR(" [ERROR] GET lightChannel : %s\n"), id); + DEBUG_MSG_P(PSTR(" [ERROR] GET lightChannel : %s\n"), id); return 0; } } @@ -935,27 +806,27 @@ unsigned int lightChannel(unsigned char id) { // --------------------------------------------------------------------------------------- // Set Channel's Value void lightChannel(unsigned char id, unsigned int value) { - DEBUG_MSG_P(PSTR("[WEB|API] Set Color Channel ")); + DEBUG_MSG_P(PSTR("[WEB|API] Set Color Channel ")); value= constrain(value, 0, 255); CRGB current_rvb = CHSV(_cur_color); if(id == 0 ){ - DEBUG_MSG_P(PSTR("RED to : %d => "), value); + DEBUG_MSG_P(PSTR("RED to : %d => "), value); current_rvb.r=value; _buttonColorRVB(current_rvb,0); } else if(id == 1 ){ - DEBUG_MSG_P(PSTR("GREEN to : %d => "), value); + DEBUG_MSG_P(PSTR("GREEN to : %d => "), value); current_rvb.g=value; _buttonColorRVB(current_rvb,0); } else if(id == 2 ){ - DEBUG_MSG_P(PSTR("BLUE to : %d => "), value); + DEBUG_MSG_P(PSTR("BLUE to : %d => "), value); current_rvb.b=value; _buttonColorRVB(current_rvb,0); } else{ - DEBUG_MSG_P(PSTR(" [ERROR] SET lightChannel %s To %d \n"), id, value); + DEBUG_MSG_P(PSTR(" [ERROR] SET lightChannel %s To %d \n"), id, value); } } @@ -969,10 +840,10 @@ unsigned int lightBrightness() { // Set Brightness void lightBrightness(unsigned int b) { b=constrain(b, 0, 255); - DEBUG_MSG_P(PSTR("[WEB|API] Set Brightness to : %d\n"), b); + DEBUG_MSG_P(PSTR("[WEB|API] Set Brightness to : %d\n"), b); _cur_color.v=b; _setLedsHSV(_cur_color); - + //set status if(b > 0){ _cur_status=1; @@ -1011,34 +882,34 @@ void lightColor(const char * color) { void _SetLightColorRGB(const char * color) { //used only from settings - DEBUG_MSG_P(PSTR("[WEB|API] Set (#RGB) Color to : ")); + DEBUG_MSG_P(PSTR("[WEB|API] Set (#RGB) Color to : ")); if( _charColorIsValid(color) ){ - DEBUG_MSG_P(PSTR("%s \n"), color); + DEBUG_MSG_P(PSTR("%s \n"), color); _buttonColorRVB(_charToRgb(color), 0); } else{ - DEBUG_MSG_P(PSTR(" Canceled ('%s' is invalid) !\n"), color); + DEBUG_MSG_P(PSTR(" Canceled ('%s' is invalid) !\n"), color); } } void _SetLightColorHSV(const char * color) { - DEBUG_MSG_P(PSTR("[WEB|API] Set (#HSV) Color to : ")); + DEBUG_MSG_P(PSTR("[WEB|API] Set (#HSV) Color to : ")); if( _charColorIsValid(color) ){ - DEBUG_MSG_P(PSTR("%s \n"), color); + DEBUG_MSG_P(PSTR("%s \n"), color); _buttonColorHSV(_charToHsv(color), 0); } else{ - DEBUG_MSG_P(PSTR(" Canceled ('%s' is invalid) !\n"), color); + DEBUG_MSG_P(PSTR(" Canceled ('%s' is invalid) !\n"), color); } } void setLightColor (const char * h, const char * s, const char * v){ - DEBUG_MSG_P(PSTR("[WEB|API] Set Color from (%s,%s,%s) "), h, s, v); + DEBUG_MSG_P(PSTR("[WEB|API] Set Color from (%s,%s,%s) "), h, s, v); CHSV color; color.h=strtoul(h, NULL, 10); color.s=strtoul(s, NULL, 10); color.v=strtoul(v, NULL, 10); - DEBUG_MSG_P(PSTR("to (%d,%d,%d) "), color.h, color.s, color.v); + DEBUG_MSG_P(PSTR("to (%d,%d,%d) "), color.h, color.s, color.v); _buttonColorRVB(color, 0); } @@ -1062,7 +933,7 @@ bool lightState() { // --------------------------------------------------------------------------------------- // Set State void lightState(bool state){ - DEBUG_MSG_P(PSTR("[WEB|API] Set Relay to : %u => "), state); + DEBUG_MSG_P(PSTR("[WEB|API] Set Relay to : %u => "), state); //if(state != _cur_status){ _buttonPower(state); //} @@ -1074,7 +945,7 @@ String lightAnimMode(){ return String(_cur_anim_mode); } void lightAnimMode(const char * val){ - DEBUG_MSG_P(PSTR("[WEB|API] Set AnimMode to %s\n"), val); + DEBUG_MSG_P(PSTR("[WEB|API] Set AnimMode to %s\n"), val); _setAnimMode(strtoul(val, NULL, 10)); } // --------------------------------------------------------------------------------------- @@ -1082,7 +953,7 @@ String lightAnimSpeed(){ return String(_cur_anim_speed); } void lightAnimSpeed(const char * val){ - DEBUG_MSG_P(PSTR("[WEB|API] Set AnimSpeed to %s \n"), val); + DEBUG_MSG_P(PSTR("[WEB|API] Set AnimSpeed to %s \n"), val); _setAnimSpeed(strtoul(val, NULL, 10)); } @@ -1138,7 +1009,7 @@ void _lightMQTTCallback(unsigned int type, const char * topic, const char * payl _setAnimSpeed(atoi(payload)); lightUpdate(true, mqttForward()); } - + // Brightness if (t.equals(MQTT_TOPIC_BRIGHTNESS)) { _setBrightness (constrain(atoi(payload), 0, LIGHT_MAX_BRIGHTNESS)); From 6e3031cdee4b3176a8f7e7cdbf7938d0fc6f3fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Wed, 8 Nov 2017 08:05:10 +0100 Subject: [PATCH 2/3] Use own DHT implementation --- code/espurna/dht.ino | 150 +++++++++++++++++++++++++++++++++++++------ code/platformio.ini | 2 - 2 files changed, 129 insertions(+), 23 deletions(-) diff --git a/code/espurna/dht.ino b/code/espurna/dht.ino index 8655b20c..4aaa9325 100644 --- a/code/espurna/dht.ino +++ b/code/espurna/dht.ino @@ -8,20 +8,139 @@ Copyright (C) 2016-2017 by Xose Pérez #if DHT_SUPPORT -#include -#include - -DHT dht(DHT_PIN, DHT_TYPE, DHT_TIMING); - double _dhtTemperature = 0; unsigned int _dhtHumidity = 0; +// ----------------------------------------------------------------------------- +// HAL +// https://github.com/gosouth/DHT22/blob/master/main/DHT22.c +// ----------------------------------------------------------------------------- + +#define DHT_MAX_DATA 5 +#define DHT_MAX_ERRORS 5 +#define DHT_MIN_INTERVAL 2000 +#define DHT_OK 0 +#define DHT_CHECKSUM_ERROR -1 +#define DHT_TIMEOUT_ERROR -2 + +#define DHT11 11 +#define DHT22 22 +#define DHT21 21 +#define AM2301 21 + +unsigned long _getSignalLevel(unsigned char gpio, int usTimeOut, bool state) { + unsigned long uSec = 1; + while (digitalRead(gpio) == state) { + if (++uSec > usTimeOut) return 0; + delayMicroseconds(1); + } + return uSec; +} + +int readDHT(unsigned char gpio, unsigned char type) { + + static unsigned long last_ok = 0; + if (millis() - last_ok < DHT_MIN_INTERVAL) return DHT_OK; + + unsigned long low = 0; + unsigned long high = 0; + + static unsigned char errors = 0; + uint8_t dhtData[DHT_MAX_DATA] = {0}; + uint8_t byteInx = 0; + uint8_t bitInx = 7; + + // Send start signal to DHT sensor + if (++errors > DHT_MAX_ERRORS) { + errors = 0; + digitalWrite(gpio, HIGH); + delay(250); + } + pinMode(gpio, OUTPUT); + digitalWrite(gpio, LOW); + delay(20); + noInterrupts(); + digitalWrite(gpio, HIGH); + delayMicroseconds(40); + pinMode(gpio, INPUT_PULLUP); + delayMicroseconds(10); + + // DHT will keep the line low for 80 us and then high for 80us + low = _getSignalLevel(gpio, 85, LOW); + if (low==0) return DHT_TIMEOUT_ERROR; + high = _getSignalLevel(gpio, 85, HIGH); + if (high==0) return DHT_TIMEOUT_ERROR; + + // No errors, read the 40 data bits + for( int k = 0; k < 40; k++ ) { + + // Starts new data transmission with >50us low signal + low = _getSignalLevel(gpio, 56, LOW); + if (low==0) return DHT_TIMEOUT_ERROR; + + // Check to see if after >70us rx data is a 0 or a 1 + high = _getSignalLevel(gpio, 75, HIGH); + if (high==0) return DHT_TIMEOUT_ERROR; + + // add the current read to the output data + // since all dhtData array where set to 0 at the start, + // only look for "1" (>28us us) + if (high > low) dhtData[byteInx] |= (1 << bitInx); + + // index to next byte + if (bitInx == 0) { + bitInx = 7; + ++byteInx; + } else { + --bitInx; + } + + } + + interrupts(); + + // Verify checksum + if (dhtData[4] != ((dhtData[0] + dhtData[1] + dhtData[2] + dhtData[3]) & 0xFF)) { + return DHT_CHECKSUM_ERROR; + } + + // Get humidity from Data[0] and Data[1] + if (type == DHT11) { + _dhtHumidity = dhtData[0]; + } else { + _dhtHumidity = dhtData[0] * 256 + dhtData[1]; + _dhtHumidity /= 10; + } + + // Get temp from Data[2] and Data[3] + if (type == DHT11) { + _dhtTemperature = dhtData[2]; + } else { + _dhtTemperature = (dhtData[2] & 0x7F) * 256 + dhtData[3]; + _dhtTemperature /= 10; + if (dhtData[2] & 0x80) _dhtTemperature *= -1; + } + + last_ok = millis(); + errors = 0; + return DHT_OK; + +} + +int readDHT() { + return readDHT(DHT_PIN, DHT_TYPE); +} + // ----------------------------------------------------------------------------- // Values // ----------------------------------------------------------------------------- +double getDHTTemperature(bool celsius) { + return celsius ? _dhtTemperature : _dhtTemperature * 1.8 + 32; +} + double getDHTTemperature() { - return _dhtTemperature; + return getDHTTemperature(true); } unsigned int getDHTHumidity() { @@ -30,8 +149,6 @@ unsigned int getDHTHumidity() { void dhtSetup() { - dht.begin(); - #if WEB_SUPPORT apiRegister(DHT_TEMPERATURE_TOPIC, DHT_TEMPERATURE_TOPIC, [](char * buffer, size_t len) { dtostrf(_dhtTemperature, 1-len, 1, buffer); @@ -50,21 +167,12 @@ void dhtLoop() { if ((millis() - last_update > DHT_UPDATE_INTERVAL) || (last_update == 0)) { last_update = millis(); - unsigned char tmpUnits = getSetting("tmpUnits", TMP_UNITS).toInt(); - // Read sensor data - double h = dht.readHumidity(); - double t = dht.readTemperature(tmpUnits == TMP_FAHRENHEIT); - - // Check if readings are valid - if (isnan(h) || isnan(t)) { - - DEBUG_MSG_P(PSTR("[DHT] Error reading sensor\n")); - - } else { + if (readDHT(DHT_PIN, DHT_TYPE) == DHT_OK) { - _dhtTemperature = t; - _dhtHumidity = h; + unsigned char tmpUnits = getSetting("tmpUnits", TMP_UNITS).toInt(); + double t = getDHTTemperature(tmpUnits == TMP_CELSIUS); + unsigned int h = getDHTHumidity(); char temperature[6]; char humidity[6]; diff --git a/code/platformio.ini b/code/platformio.ini index d743f1de..40f68586 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -13,8 +13,6 @@ build_flags_1m = ${common.build_flags} -Wl,-Tesp8266.flash.1m0.ld #https://github.com/me-no-dev/ESPAsyncTCP#9b0cc37 // 2.3.0 compatible #https://github.com/me-no-dev/ESPAsyncTCP#3795e16 // 2.4.0-rc2 compatible lib_deps = - DHT sensor library - Adafruit Unified Sensor https://github.com/xoseperez/Time ArduinoJson https://github.com/me-no-dev/ESPAsyncTCP#9b0cc37 From 2f91d90814eab030a3c55e287479d97107fa91aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Wed, 8 Nov 2017 08:34:56 +0100 Subject: [PATCH 3/3] Clean up IR code --- code/espurna/config/hardware.h | 6 +++++- code/espurna/espurna.ino | 6 ++++++ code/espurna/ir.ino | 27 +++++++++++++++------------ code/espurna/web.ino | 2 +- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 509415cd..5c9d03c4 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -699,6 +699,11 @@ #define LIGHT_CH3_INVERSE 0 #define LIGHT_CH4_INVERSE 0 + // IR + #define IR_SUPPORT 1 + #define IR_PIN 4 + #define IR_BUTTON_SET 1 + #elif defined(MAGICHOME_LED_CONTROLLER_20) // Info @@ -706,7 +711,6 @@ #define DEVICE "LED_CONTROLLER_20" #define RELAY_PROVIDER RELAY_PROVIDER_LIGHT #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER - #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER #define DUMMY_RELAY_COUNT 1 //#define LIGHT_PROVIDER_EXPERIMENTAL_RGB_ONLY_HSV_IR diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index a6cf877d..7b62fa97 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -294,6 +294,9 @@ void setup() { #if RF_SUPPORT rfSetup(); #endif + #if IR_SUPPORT + irSetup(); + #endif #if DOMOTICZ_SUPPORT domoticzSetup(); #endif @@ -356,5 +359,8 @@ void loop() { #if RF_SUPPORT rfLoop(); #endif + #if IR_SUPPORT + irLoop(); + #endif } diff --git a/code/espurna/ir.ino b/code/espurna/ir.ino index 1b842a7a..2a1e59b0 100644 --- a/code/espurna/ir.ino +++ b/code/espurna/ir.ino @@ -25,9 +25,9 @@ void _irProcessCode(unsigned long code) { boolean found = false; // Repeat last valid code - DEBUG_MSG_P(PSTR("[IR] Received 0x%08X\n"), code); + DEBUG_MSG_P(PSTR("[IR] Received 0x%06X\n"), code); if (code == 0xFFFFFFFF) { - DEBUG_MSG_P(PSTR("[IR] Processing 0x%08X\n"), code); + DEBUG_MSG_P(PSTR("[IR] Processing 0x%06X\n"), code); code = last_code; } @@ -39,6 +39,10 @@ void _irProcessCode(unsigned long code) { unsigned long button_mode = pgm_read_dword(&IR_BUTTON[i][1]); unsigned long button_value = pgm_read_dword(&IR_BUTTON[i][2]); + if (button_mode == IR_BUTTON_MODE_STATE) { + relayStatus(0, button_value); + } + #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE if (button_mode == IR_BUTTON_MODE_BRIGHTER) { @@ -50,23 +54,23 @@ void _irProcessCode(unsigned long code) { lightColor(button_value); } + /* + #if LIGHT_PROVIDER == LIGHT_PROVIDER_FASTLED + if (button_mode == IR_BUTTON_MODE_EFFECT) { + _buttonAnimMode(button_value); + } + #endif + */ + /* if (button_mode == IR_BUTTON_MODE_HSV) { lightColor(button_value); } */ - #endif + lightUpdate(true, true); - /* - #if LIGHT_PROVIDER == LIGHT_PROVIDER_FASTLED - if (button_mode == IR_BUTTON_MODE_EFFECT) { - _buttonAnimMode(button_value); - } #endif - */ - - lightUpdate(true, true); found = true; last_code = code; @@ -77,7 +81,6 @@ void _irProcessCode(unsigned long code) { } if (!found) { - last_code = 0; DEBUG_MSG_P(PSTR("[IR] Ignoring code\n")); } diff --git a/code/espurna/web.ino b/code/espurna/web.ino index 2a5289e8..7f9923cc 100644 --- a/code/espurna/web.ino +++ b/code/espurna/web.ino @@ -215,7 +215,7 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) { if (lightHasColor()) { if (action.equals("color") && root.containsKey("data")) { - lightColor(root["data"]); + lightColor((const char *) root["data"]); lightUpdate(true, true); }