Hi Synco,
Here is my complete sketch. As noted, it uses multiple libraries so may be a little more involved than what you’re looking for. I separated sections with forward slashes - ///////////
This runs two LED strips, has a capacitive touch sensor as a button, analog light sensor, and talks over ethernet to an MQTT server. This is running on a Freetronics EtherTen module which is crammed for additional code space.
The EtherTen if you aren’t familiar is basically an Uno + Ethernet shield all in one. I am powering the system from the Freetronics Midspan injector to run power and ethernet all in one cable.
Here is a quick video of the system:
#include <FastLED.h>
/// ethernet setup
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 99);
IPAddress server(192, 168, 1, 1);
EthernetClient ethClient;
PubSubClient client(ethClient);
#define DATA_PIN A0
#define DATA_PIN_2 A1
#define NUM_LEDS 10
#define NUM_LEDS_2 9
#define BRIGHTNESS 128
#define LED_TYPE TM1803
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define InputPin 7 // switch for turning lights on/off
bool run = false;
//fastled
#define FRAMES_PER_SECOND 120
// MQTT
unsigned long lastReadTime; //the last time we read the light pin (high-speed read)
unsigned long lastReportedReadTime; //the last time light level was pushed to MQTT (low speed read+publish)
int prevReadValue; //last read value of the light pin
#define readTimer 100 // interval to read the light pin (high speed read) //was int
#define readTimerMQTT 300000 //interval to read for MQTT publishes (low speed read) // was unsigned long
#define lightPin A4 //analog pin of photocell
void setup() {
lastReadTime=millis(); // last read for regular readings
lastReportedReadTime=millis()-readTimerMQTT; //last time a read was published to MQTT
prevReadValue=analogRead(lightPin); //initial reading of photocell
delay( 3000 ); // power-up safety delay (FastLED)
FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_2,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness( BRIGHTNESS );
pinMode(lightPin, INPUT); //light sensor
pinMode(InputPin, INPUT);
//currentPalette = RainbowColors_p;
//currentBlending = LINEARBLEND;
//ethernet
client.setServer(server, 1883);
client.setCallback(callback);
Ethernet.begin(mac, ip);
// Allow the hardware to sort itself out
delay(1500);
}
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
void loop()
{
// ethernet
if (!client.connected()) {
reconnect();
}
client.loop();
readAnalog();
checkInputs();
if (run) {
FastLED.setBrightness(BRIGHTNESS);
runFastLED(); // run simulation frame
FastLED.show();
//FastLED.delay(1000 / UPDATES_PER_SECOND);
}
else{ //turn off the lights
FastLED.show(0);
}
}
//////// Code to scan for a physical button press, take action, and report to MQTT
void checkInputs()
{
if(digitalRead(InputPin) == HIGH){
delay(10); //debounce
if(digitalRead(InputPin) == HIGH) {
client.publish("home/kitchen/button1","ON");
run = !run; //invert
if(run) client.publish("home/kitchen/stringLights/status", "ON");
else if(run== false) client.publish("home/kitchen/stringLights/status", "OFF");
delay(500);
}
}
}
///////// FastLED related code:
void runFastLED(){
// Call the current pattern function once, updating the 'leds' array
gPatterns[gCurrentPatternNumber]();
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
// add one to the current pattern number, and wrap around at the end
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void rainbow()
{
// FastLED's built-in rainbow generator
fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
void rainbowWithGlitter()
{
// built-in FastLED rainbow, plus some random sparkly glitter
rainbow();
addGlitter(80);
}
void addGlitter( fract8 chanceOfGlitter)
{
if( random8() < chanceOfGlitter) {
leds[ random16(NUM_LEDS) ] += CRGB::White;
}
}
void confetti()
{
// random colored speckles that blink in and fade smoothly
fadeToBlackBy( leds, NUM_LEDS, 10);
int pos = random16(NUM_LEDS);
leds[pos] += CHSV( gHue + random8(64), 200, 255);
}
void sinelon()
{
// a colored dot sweeping back and forth, with fading trails
fadeToBlackBy( leds, NUM_LEDS, 20);
int pos = beatsin16(13,0,NUM_LEDS);
leds[pos] += CHSV( gHue, 255, 192);
}
void bpm()
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for( int i = 0; i < NUM_LEDS; i++) { //9948
leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
}
}
void juggle() {
// eight colored dots, weaving in and out of sync with each other
fadeToBlackBy( leds, NUM_LEDS, 20);
byte dothue = 0;
for( int i = 0; i < 8; i++) {
leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
///////// Code to respond to callbacks (messages) from the MQTT Topics that we're listening to
void callback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0'; //set terminator for payload length (or part of old messages could show up)
//Command will be either "ON" or "OFF"
String s = String((char*)payload); //convert payload to string
if(strcmp(topic, "home/kitchen/stringLights/command")==0){
//Note - don't publish a new command before reading in the current one - the library uses the same buffer for send & rec. This will confuse it.
// https://community.openhab.org/t/rgb-led-strip-control-using-arduino-and-mqtt/4366
// https://community.openhab.org/t/oh2-how-to-convert-colorpicker-to-rgb-values/16305/5
if(s == "OFF") {
run = false;
client.publish("home/kitchen/stringLights/status", "OFF");
}
else if(s == "ON") {
//if(strcmp( (char *) payload, "ON") == 0) {
run = true;
client.publish("home/kitchen/stringLights/status", "ON");
}
} //end of the command callback
else if(strcmp(topic, "home/kitchen/stringLights/color")==0){
if(s == "OFF") {
run = false;
client.publish("home/kitchen/stringLights/status", "OFF");
}
else if(s == "ON") {
//if(strcmp( (char *) payload, "ON") == 0) {
run = true;
client.publish("home/kitchen/stringLights/status", "ON");
}
// else if(strcmp(s.substring(0,5), "color")==0){
// set the color
// }
} //end of the color callback
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
// Attempt to connect
if (client.connect("KitchenLightController", "username", "password", "home/kitchen/LWT", 1, 1, "Offline")) {
client.publish("home/kitchen/LWT","Online");
client.subscribe("home/kitchen");
client.subscribe("home/kitchen/stringLights/command");
client.subscribe("home/kitchen/stringLights/color");
client.subscribe("home/kitchen/stringLights/brightness");
/* removed to resolve crashing
//post IP address to MQTT
String IPCurrent="";
char str[4];
for(int n=0; n<4; n++){
itoa((int)Ethernet.localIP()[n], str, 10);
IPCurrent +=str;
if(n<3) IPCurrent +=".";
}
IPCurrent.toCharArray(str, 20);
client.publish("home/kitchen/ControllerIPAddress", str);
*/
}
else {
delay(5000);
}
}
}
///// Code to read analog (ambient light) sensor; take action; and report to MQTT
void readAnalog(){
if(millis() >= lastReadTime+readTimer) //see if we need to read the light pin
{
int lightReadValue=1024-(analogRead(lightPin));
char lightChar[10] = "";
dtostrf(lightReadValue, 3,0, lightChar);
//publish large changes
if(abs(lightReadValue - prevReadValue) > 5){
client.publish("home/kitchen/lightLevel", lightChar);
lastReportedReadTime=millis();
}
//or just publish every five minutes
else if(millis() >= lastReportedReadTime+readTimerMQTT){
client.publish("home/kitchen/lightLevel", lightChar);
lastReportedReadTime=millis();
}
if(lightReadValue <= 65 && prevReadValue > 65){
//currentPalette = CloudColors_p;
FastLED.show();
delay(5000);
run=false; //disable FastLED library
}
lastReadTime=millis();
prevReadValue=lightReadValue; //remember previous read
}
}