MQTT & Neopixel Conflict?

I have the simple example from the MQTT library running, but when I attempt to add Neopixel support into the callback function, I get an error, specifically when I call strip.show();

Code:

#include "neopixel/neopixel.h"
#include "MQTT/MQTT.h"
#define PIXEL_PIN D2
#define PIXEL_COUNT 1
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
void callback(char* topic, byte* payload, unsigned int length);
byte server[] = {000,000,000,00};

MQTT client(server, 1883, callback);
// recieve message
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    if (message.equals("2"))    
       // RGB.color(255, 0, 0);
        rainbow(1);
        strip.show();
    else if (message.equals("1"))    
        RGB.color(0, 255, 0);
    else if (message.equals("BLUE"))    
        RGB.color(0, 0, 255);
    else    
        RGB.color(255, 255, 255);
    delay(1000);
}

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("outTopic","hello world");
        client.subscribe("rooms/10");
    }
}

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

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Error Output:

mqtttest.cpp: In function 'void callback(char*, byte*, unsigned int)':
mqtttest.cpp:25:15: warning: converting to non-pointer type 'char' from NULL [-Wconversion-null]
 byte server[] = {184,169,164,30};
               ^
mqtttest.cpp:31:5: error: 'else' without a previous 'if'
     memcpy(p, payload, length);
     ^

make[1]: *** [../build/target/user/platform-6mqtttest.o] Error 1
make: *** [user] Error 2

That looks like one of the preprocessor hickups.
Try adding the braces { } even around single line conditional branches.

But I’d rather set a flag inside any callback to be handled via loop() (just for the sake of “decoupling”)

3 Likes

Excellent solution on both parts, I thank you. :+1:

#include "neopixel/neopixel.h"
#include "MQTT/MQTT.h"
#define PIXEL_PIN D2
#define PIXEL_COUNT 1
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

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,
 * MQTT client("www.sample.com", 1883, callback);
 **/
byte server[] = {000,000,000,00};
String data;
MQTT client(server, 1883, callback);
// recieve message
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    data = message;
    delay(1000);
}


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("outTopic","hello world");
        client.subscribe("rooms/10");
    }
}

void loop() {
    if (client.isConnected())
        client.loop();
        if (data.equals("2"))
       {
        RGB.color(255, 0, 0);
        rainbow(1);
        strip.show();
       }
    else if (data.equals("1"))    
        {
            RGB.color(0, 255, 0);
            rainbow(1);
            strip.show();
        }
    else if (data.equals("BLUE"))    
        {
            RGB.color(0, 0, 255);
            rainbow(1);
            strip.show();            
        }
            
    else    
        {
            RGB.color(255, 255, 255);
            rainbow(1);
            strip.show();            
    
        }
        
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
2 Likes

This is the problem. In C/C++ you can have exactly one statement after an if() but for more than one statement you must use curly braces if () { stmt1; stmt2; } else … So the compiler interprets this as the strip.show(); command being outside the if statement.

    if (message.equals("2")) 
      {   
       // RGB.color(255, 0, 0);
        rainbow(1);
        strip.show();
      }
    else if (message.equals("1"))    
        RGB.color(0, 255, 0);    // one statement ok
    else if (message.equals("BLUE"))    
        RGB.color(0, 0, 255);   // one statement ok
    else    
        RGB.color(255, 255, 255);  // one statement ok

3 Likes

lol… hence why I use braces for even a single line statement… you just know Murphy is gonna get you later down the track when you change that one line statement to a two line statement and you didn’t add the braces! :wink:

4 Likes