Neopixel controller via MQTT --> Need animated code

Hi,

Don’t know if this is the correct location. I have an question since I am no programmer. I would like to use MQTT to set Neopixel LED strips. I have code that sets a simple color on the ledstrip. What I really want is set an animation depending on the MQTT message received. I will paste the code I have, which works. But if someone can help me out getting real strip animations in. I need there need to be some loop going on and that this may cause issues when “listening” for the next MQTT message. The thing is … I have no clue


// This #include statement was automatically added by the Particle ID
#include "MQTT.h"
#include "neopixel.h"

void callback(char* topic, byte* payload, unsigned int length);

/**
 * if want to use IP address,
 * byte server[] = { XXX,XXX,XXX,XXX };
 * MQTT client(server, 1883, callback);
 * want to use domain name,
 * exp) iot.eclipse.org is Eclipse Open MQTT Broker: https://iot.eclipse.org/getting-started
 * MQTT client("iot.eclipse.org", 1883, callback);
 **/
byte server[] = { 192,168,1,5 };
MQTT client(server, 1883, callback);

#define PIXEL_PIN D2
#define PIXEL_COUNT 144
#define PIXEL_TYPE WS2812B



Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);



int i;



// recieve message
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
//First animation if RED is send via MQTT. The actual function is between the 2 {} brackets
    if (!strcmp(p, "PURPLE")) {
//The actual animation starts here
        for(i=0; i < PIXEL_COUNT; i++) {
        strip.setPixelColor(i, 180, 3, 180);
        strip.show();
        
    }

//The animation ends here
    }


    else if (!strcmp(p, "ORANGE")){
        for(i=0; i < PIXEL_COUNT; i++) {
        strip.setPixelColor(i, 200, 50, 5);
        strip.show();
        }
    
    }   
    
    else if (!strcmp(p, "OFF")){
        for(i=0; i < PIXEL_COUNT; i++) {
        strip.setPixelColor(i, 0, 0, 0);
        strip.show();
        }
    
    }   
        
      
    else
        {
        for(i=0; i < PIXEL_COUNT; i++) {
        strip.setPixelColor(i, 0, 0, 0);
        strip.show();
        }
    
    }   
}


void setup() {
    RGB.control(true);
    strip.begin();
    strip.show(); // Initialize all pixels to 'off
    // connect to the server
    client.connect("sparkclient");

    // publish/subscribe
    if (client.isConnected()) {
        client.publish("photon/message","hello world");
        client.subscribe("photon/color");
    }
}

void loop() {
    
    
    if (client.isConnected())
      client.loop();
        
        
        
}






One thing to not here: You should not put strip.show() into the for() loop. This would always push the entire pixel buffer down the strip slowing down your function.
You rather want to set all pixels in the loop without actually pusing that data out and then only call strip.show() once.

BTW, this is also not needed

You can use if (!strncmp(payload, "YOURCOLOUR", length)) directly.

For your animation, you would set a flag inside your MQTT callback and after that let loop() do the animation without an "trapping" loop but one step at a time with each iteration of loop() (or rather on a timed basis).

something like

const int aniDelay = 100; // milliseconds between each animation frame
int       animation = 0;  // which kind of animation to play
...
void callback(char* topic, byte* payload, unsigned int length) {
  if (!strncmp(payload, "Animation 1", length)) 
      animation = 1;
  else if (!strncmp(payload, "PURPLE", length)) {
      for(i=0; i < PIXEL_COUNT; i++) 
          strip.setPixelColor(i, 180, 3, 180);
      strip.show();
  }
  else if (...
}

...
void loop() {
    if (client.isConnected())
      client.loop();

    if (animation) 
    {
      if (runAnimation(animation) == 0) // when animation is finished
        animation = 0;                  // reset the animation flag
    }
}

int runAnimation(int scene) {
  static uint32_t msStep = 0;
  static uint32_t aniStep = 0;
  if (millis() - msStep < aniDelay) return; // if next animation step is not due yet leave
  msStep = millis(); 
 
  switch(scene) {
    case 1: // animation scene 1
        // set all pixels according to aniStep;
        break;

    default:
        msStep = 0;
        aniStep = 0;
        break;
  }
  strip.show();

  return ++aniStep; // report back which step of the animation will be next
}

I… have no clue what you are talking about :wink:

What if I would like to add one of these animations here.

How would that look like?

That page uses FastLED library - not neopixel which has many animations already built in but they also show how the individual custom animations are programmed.
I’ve given you above a framework that allows for the animations to run without interfering too much with your MQTT loop.
The actual animations are something you should actually fill in. We can provide guidance but don’t usually do the job for you (unless as contract work :wink: ).

ok… since I have no clue,what about that contract work :wink:

I copy/pasted some code an glued it together but thats not cutting it … :wink:

Which of the shown animations do you want implemented the most?
Some of these are quite involved some others are a walk in the park.

The ones I would like are :

  • Cylon
  • Regenboog Cycle
  • Theatre Chase
  • Multi Color Stuiterende Ballen

Be able to turn the strip OFF and be able to set a color (colorpicker)

:wink:

Would anyone be able to build this for me.