@maghac Great project.
I've made something similar, Arduino Pro Mini 5v, 5m LED strip (non-addressable), nrf24L01+ and MOSTFETs
I know it took me awhile to find code examples, so I figured I would share my code incase it helps anyone else.
I use Domoticz as a controller. This code talks to:
- Switch - to control turning my color cycle fade effect on
- Dimmer - to control the speed of the color cycle fade effect
- RGB switch - to control having only a single color turned on and the brightness of the string.
Much of my code is standard stuff, using FastLED analogue, but I'm particularly proud of the brightness part, since I bashed my head against the keyboard several times trying to figure it out
//## INCLUDES ##
#define MY_DEBUG
#define MY_RADIO_NRF24
#define MY_NODE_ID 20
#include <MySensors.h>
#include <SPI.h>
#include <FastLED.h>
#define cID_RGB_SELECTOR 0
#define cID_CYCLE_EFFECT 1
#define cID_CYCLE_EFFECT_SPEED 2
#define PIN_RED 5
#define PIN_GREEN 6
#define PIN_BLUE 3
//## 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<char*>(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;
}
Hopefully this proves useful to someone :)