From 6f6bade822b30139887c265b3b58d038451d4965 Mon Sep 17 00:00:00 2001 From: Simon Milvert Date: Sat, 29 Dec 2018 13:16:51 +0100 Subject: [PATCH] Added a simple RGB sensor --- rgb_sensor/platformio.ini | 14 ++ rgb_sensor/src/rgb.ino | 287 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 rgb_sensor/platformio.ini create mode 100644 rgb_sensor/src/rgb.ino diff --git a/rgb_sensor/platformio.ini b/rgb_sensor/platformio.ini new file mode 100644 index 0000000..07d429e --- /dev/null +++ b/rgb_sensor/platformio.ini @@ -0,0 +1,14 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html +; [ +[env:pro16MHzatmega328] +platform = atmelavr +framework = arduino +board = pro16MHzatmega328 diff --git a/rgb_sensor/src/rgb.ino b/rgb_sensor/src/rgb.ino new file mode 100644 index 0000000..2a967d2 --- /dev/null +++ b/rgb_sensor/src/rgb.ino @@ -0,0 +1,287 @@ +//## INCLUDES ## +#define MY_DEBUG +#define MY_RADIO_NRF24 +#define MY_NODE_ID 31 + +#include +#include +#include + +#define cID_RGB_SELECTOR 0 +#define cID_CYCLE_EFFECT 1 +#define cID_CYCLE_EFFECT_SPEED 2 + +#define PIN_RED 3 +#define PIN_GREEN 5 +#define PIN_BLUE 6 + +//## VARIABLES ## +// MySensors +#define MySensors_SketchName "RGB LED Strip" +#define MySensors_SketchVersion "v0.3" +MyMessage MySensors_MSG_Last_Color(cID_RGB_SELECTOR,V_VAR1); +MyMessage MySensors_MSG_RGB_Selector(cID_RGB_SELECTOR, V_LIGHT); +MyMessage MySeonsors_MSG_CYCLE_EFFECT(cID_CYCLE_EFFECT, V_LIGHT); +MyMessage MySensors_MSG_CYCLE_EFFECT_SPEED(cID_CYCLE_EFFECT_SPEED, V_DIMMER); +bool MySensors_RequestACK = false; +// Single color +int Solid_RGB_Active=0; +char Solid_RGB_Color[] = "000000"; +uint16_t Solid_RGB_Brightness = 0xFF; +// Cycle effect +int Cycle_Effect_Active=0; +unsigned long Cycle_Effect_pMillis = 0; +long Cycle_Effect_Speed = 20; +static uint8_t Cycle_Effect_Current_Hue; +// Supporting +bool Status_Change = false; +bool Print_Debug = false; + +// ## Primary flow control +void setup() { + Serial.begin(115200); + while (!Serial) ; + Serial.print("compiled: ");Serial.print(__DATE__);Serial.println(__TIME__); + + pinMode(PIN_RED, OUTPUT); + pinMode(PIN_GREEN, OUTPUT); + pinMode(PIN_BLUE, OUTPUT); + + Event_ColorTestBars(); + + request(cID_RGB_SELECTOR, V_VAR1); + request(cID_RGB_SELECTOR, V_LIGHT); + request(cID_CYCLE_EFFECT, V_LIGHT); + request(cID_CYCLE_EFFECT_SPEED, V_DIMMER); +} +void loop() { + if (Cycle_Effect_Active == 1){ + unsigned long currentMillis = millis(); + Event_RunCycleEffect(currentMillis); + } else if (Status_Change){ + Status_Change = false; +#ifdef MY_DEBUG + if (Print_Debug) {Serial.println("STATUS CHANGE");} +#endif + if (Solid_RGB_Active == 0){ + Event_SetLEDColors( CRGB::Black ); + }else if (Solid_RGB_Active == 1){ + CHSV colorHSV = rgb2hsv_approximate(str2CRGB(Solid_RGB_Color)); + Event_SetLEDColors(CHSV(colorHSV.h, colorHSV.s, Solid_RGB_Brightness)); + } + } +} +// ## MySensors Methods +void presentation() { + sendSketchInfo(MySensors_SketchName, MySensors_SketchVersion); + + present(cID_RGB_SELECTOR, S_RGB_LIGHT, "RGB Color Selector", MySensors_RequestACK); + present(cID_CYCLE_EFFECT, S_LIGHT, "RGB Cycle Effect", MySensors_RequestACK); + present(cID_CYCLE_EFFECT_SPEED, S_DIMMER, "RGB Cycle Effect Speed", MySensors_RequestACK); +} +void receive(const MyMessage &message){ +#ifdef MY_DEBUG + if (message.isAck()){ + Serial.println("Got ack from gateway"); + } +#endif + if (message.type == V_LIGHT){ +#ifdef MY_DEBUG + if (Print_Debug) {Serial.println("message v_light");} +#endif + int current_Light_State = message.getString()[0] == '1';// Incoming on/off command sent from controller ("1" or "0") + if (message.sensor==cID_CYCLE_EFFECT){// is Cycle Message + if (current_Light_State==1){//turn cycle on + Event_LightCycle(true, true, false); + Event_SolidColor(false, false, true); + } else {//turn cycle off + Event_LightCycle(false, true, false); + Event_SolidColor(false, false, true); + } + } else if (message.sensor==cID_RGB_SELECTOR){// is RGB Message + if (current_Light_State==1){//turn RGB on + Event_SolidColor(true, true, false); + Event_LightCycle(false, false, true); + } else {//turn RGB off + Event_SolidColor(false, true, false); + Event_LightCycle(false, false, true); + } + } else { +#ifdef MY_DEBUG + Serial.print("UNKNOWN Light - Message:"); + Serial.print(message.getString()); + Serial.print(" - Sensor:"); + Serial.println(message.sensor); +#endif + } + } else if (message.type == V_RGB){ +#ifdef MY_DEBUG + if (Print_Debug) {Serial.println("message v_rgb");} +#endif + String szMessage=message.getString(); + strcpy(Solid_RGB_Color, getValue(szMessage,'&',0).c_str()); + Solid_RGB_Active = 1; + }else if (message.type == V_DIMMER) {// if DIMMER type, adjust brightness +#ifdef MY_DEBUG + if (Print_Debug) {Serial.println("message v_dimmer");} +#endif + if (message.sensor==cID_RGB_SELECTOR){// is single Message + if (Solid_RGB_Active==1){//turn RGB on + Event_SolidColor(true, true, false); + Event_LightCycle(false, false, true); + } else {//turn RGB off + Event_SolidColor(false, true, false); + Event_LightCycle(false, false, true); + } + Solid_RGB_Brightness = map(message.getLong(), 0, 100, 0, 255); + CRGB colorRGB = str2CRGB(Solid_RGB_Color); + CHSV colorHSV = rgb2hsv_approximate(colorRGB); + colorHSV = CHSV(colorHSV.h, colorHSV.s, Solid_RGB_Brightness); + Event_SetLEDColors(colorHSV); +#ifdef MY_DEBUG + if (Print_Debug) { + Serial.print("colorHSV.h:"); + Serial.println(colorHSV.h); + Serial.print("colorHSV.s:"); + Serial.println(colorHSV.s); + Serial.print("colorHSV.v:"); + Serial.println(colorHSV.v); + } +#endif + Event_SendLastColor(); + } else if (message.sensor==cID_CYCLE_EFFECT_SPEED){// is Speed dimmer Message + Cycle_Effect_Speed = map(message.getLong(), 0, 100, 1, 202); +#ifdef MY_DEBUG + if (Print_Debug) { + Serial.print("Cycle_Effect_Speed: "); + Serial.println(Cycle_Effect_Speed); + } +#endif + } + }else if (message.type == V_STATUS) { // if on/off type, toggle brightness +#ifdef MY_DEBUG + if (Print_Debug) {Serial.println("message v_status");} +#endif + Solid_RGB_Active = message.getInt(); + Cycle_Effect_Active = 0; + if (Solid_RGB_Active == 0){ + if (Print_Debug) {Serial.println("Strip OFF");} + Event_SetLEDColors( CRGB::Black ); + }else{ + if (Print_Debug) {Serial.println("Strip ON");} + Event_SetLEDColors(strtol(Solid_RGB_Color, NULL, 16)); + } + //Event_SendLastColor(); + }else if (message.type==V_VAR1) { // color status + String szMessage=message.getString(); +#ifdef MY_DEBUG + if (Print_Debug) { + Serial.println("message v_var1"); + Serial.println(szMessage); + } +#endif + strcpy(Solid_RGB_Color, getValue(szMessage,'&',0).c_str()); + Solid_RGB_Active = 1; + Cycle_Effect_Active = 0; + } + Status_Change = true; +} +// ## Events +void Event_LightCycle(bool t, bool s, bool u) { + Cycle_Effect_Active = (t) ? 1 : 0; + if (u){ + send(MySeonsors_MSG_CYCLE_EFFECT.set(Cycle_Effect_Active),MySensors_RequestACK); + } +} +void Event_SolidColor(bool t, bool s, bool u) { + Solid_RGB_Active = (t) ? 1 : 0; + if (u){ + send(MySensors_MSG_RGB_Selector.set(Solid_RGB_Active),MySensors_RequestACK); + } +} +void Event_SetLEDColors( const CRGB& rgb){ + analogWrite(PIN_RED, rgb.r ); + analogWrite(PIN_GREEN, rgb.g ); + analogWrite(PIN_BLUE, rgb.b ); +} +void Event_SendLastColor(){ + String current_status=Solid_RGB_Color+String("&")+String(Solid_RGB_Brightness)+String("&")+String(Solid_RGB_Active); + send(MySensors_MSG_Last_Color.set(current_status.c_str()),MySensors_RequestACK); +} +void Event_RunCycleEffect(unsigned long theMills){ + if (theMills - Cycle_Effect_pMillis >= Cycle_Effect_Speed){ + Cycle_Effect_pMillis = theMills; + Cycle_Effect_Current_Hue = Cycle_Effect_Current_Hue + 1; + Event_SetLEDColors( CHSV( Cycle_Effect_Current_Hue, 255, 255) ); + } +} +void Event_ColorTestBars(){// Event_ColorTestBars: flashes Red, then Green, then Blue, then Black. Helpful for diagnosing if you've mis-wired which is which. + Event_SetLEDColors( CRGB::Red ); delay(500); + Event_SetLEDColors( CRGB::Green ); delay(500); + Event_SetLEDColors( CRGB::Blue ); delay(500); + Event_SetLEDColors( CRGB::Black ); delay(500); +} +// ## Helper Functions +String getValue(String data, char separator, int index){ + int found = 0; + int strIndex[] = {0, -1}; + int maxIndex = data.length()-1; + for(int i=0; i<=maxIndex && found<=index; i++){ + if(data.charAt(i)==separator || i==maxIndex){ + found++; + strIndex[0] = strIndex[1]+1; + strIndex[1] = (i == maxIndex) ? i+1 : i; + } + } + return found>index ? data.substring(strIndex[0], strIndex[1]) : ""; +} + +int x2i(char *s) { + int x = 0; + for(;;) { + char c = *s; + if (c >= '0' && c <= '9') { + x *= 16; + x += c - '0'; + }else if (c >= 'A' && c <= 'F') { + x *= 16; + x += (c - 'A') + 10; + }else { + break; + } + s++; + } + return x; +} +char* str2char(String command){ + if(command.length()!=0){ + char *p = const_cast(command.c_str()); + return p; + } +} +CRGB str2CRGB(String s){ + String r = str2char(s.substring(0,2)); + String g = str2char(s.substring(2,4)); + String b = str2char(s.substring(4,6)); + uint8_t red = x2i(r.c_str()); + uint8_t green = x2i(g.c_str()); + uint8_t blue = x2i(b.c_str()); +#ifdef MY_DEBUG + if (Print_Debug) { + Serial.print("r:"); + Serial.println(r); + Serial.print("g:"); + Serial.println(g); + Serial.print("b:"); + Serial.println(b); + Serial.print("red:"); + Serial.println(red); + Serial.print("green:"); + Serial.println(green); + Serial.print("blue:"); + Serial.println(blue); + } +#endif + CRGB colorRGB = CRGB(red, green, blue); + return colorRGB; +}