Code does not light all neopixels

Hi All,

I'm putting together a code to extract colour data from a webpage and light up 4 LEDs to reflect the colours.

The current data is [green,blue], which should show 2 green LEDs and 2 blue. Alternatively it could be 3 colours (e.g. [green,blue,red]) which would need to show 2 of the first colour and 1 of the other two.

At the moment only the first 2 LEDs are lighting up.

Can anyone help with this issue? I've got an idea of where the issue is in the code, but not the solution.

Worth noting as well that I have tested the neopixels with a test code, and all 4 neopixels work fine.

Thanks


#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <Adafruit_NeoPixel.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <WiFiClient.h>
#include <SPI.h>

// Change to suit your number of pixels and output pin on the ESP8266
#define PIN D3
#define NUMPIXELS 4

// Change to add in your WiFi SSID, Password & NODE_RED Server IP
const char* NODE_RED_HOST_IP = "http://XXXXXXXXXXXXXXXXX";
const char* ssid = "XXXXXXXXXXXXX";
const char* password = "XXXXXXXXXXX";

// Adafruit NeoPixel initilisation string
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

// Define some standard colours for easier reference later
const uint32_t redPixel = pixels.Color(255, 0, 0);
const uint32_t greenPixel = pixels.Color(0, 255, 0);
const uint32_t bluePixel = pixels.Color(0, 0, 255);
const uint32_t whitePixel = pixels.Color(255, 255, 255);
const uint32_t unlitPixel = pixels.Color(0, 0, 0);
const uint32_t dimWhitePixel = pixels.Color(255, 255, 255);

HTTPClient http;
WiFiClient client;

void setup() {
  // Boot up ESP8266, setup serial comms and try to connect to wifi
  Serial.begin(115200);
  Serial.println("Booting Up");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection to WiFi Failed! Retrying...");
    delay(5000);
  }

  // Set LED colour to dim white when booted and connected to your wifi with a valid IP, print the IP to serial
  Serial.print("IP Address:");
  Serial.println(WiFi.localIP());
  pixels.begin();
  pixels.setPixelColor(0, dimWhitePixel);
  pixels.show();
}

void loop() {
  // Connect to the NODE_RED server and pull a result, show red LED if this fails

  const int httpPort = 1880;
  // Connect to the NODE_RED bins webpage, change to suit your IP and Bins webpage address
  if (! http.begin(client, "http://XXXXXXXXXXXXXXXXXXXX")) {
    Serial.println("Connection Failed To " + String(NODE_RED_HOST_IP));
    // If we cant connect, show 1 pixel red to indicate an error
    pixels.setPixelColor(0, redPixel);
  } else {
    // If we can connect to NODE_RED, start a pull of data from NODE_RED server
    Serial.print("Doing Get: ");
    int httpCode = http.GET();

    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    // Check we're getting a HTTP Code 200
    if (httpCode = HTTP_CODE_OK) {
      String parseMe = http.getString();
      //Create a memory buffer to store the JSON data
      StaticJsonBuffer<300> JSONBuffer;
      JsonArray& parsed = JSONBuffer.parseArray(parseMe);

      // If we can connect to NODE_RED, but dont understand the returned data, set 1 pixel to red and output to serial
      if (!parsed.success()) {
        Serial.println("Parsing JSON Failed");
        pixels.setPixelColor(0, redPixel);
        pixels.show();
        delay(5000);
        return;
      }

      int arraySize = parsed.size();
      int pixelIndex = 0;

      static uint32_t lastColour = unlitPixel;
      for (int i = 0; i < arraySize; i++) {
        char jsonChar[10];
        parsed[i].printTo((char*)jsonChar, parsed.measureLength() + 1);

        // Parse retreived data and check for for matching colours. If webpage says Green, show Green LED, if Red, show Red, etc
        if (strcmp(jsonChar, "green") == 0 ) {
          pixels.setPixelColor(pixelIndex, greenPixel);
          lastColour = greenPixel;
          Serial.println("Set To Green");
        }
        if (strcmp(jsonChar, "red") == 0 ) {
          pixels.setPixelColor(pixelIndex, redPixel);
          lastColour = redPixel;
          Serial.println("Set To Red");
        }
        if (strcmp(jsonChar, "blue") == 0 ) {
          pixels.setPixelColor(pixelIndex, bluePixel);
          lastColour = bluePixel;
          Serial.println("Set To Blue");
        }
        if (strcmp(jsonChar, "white") == 0 ) {
          pixels.setPixelColor(pixelIndex, whitePixel);
          lastColour = whitePixel;
          Serial.println("Set To White");
        }
        pixelIndex++;
      }
      // If only one bin value is found, repeat colour so whole bin lights up
      if (arraySize == 1) {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(pixelIndex, lastColour);
        }
      }

    }
   
    Serial.println();
    Serial.println("Closing Connection");
    http.end();
    pixels.show();
   
    delay(30000);

If you put some Serial.print statements right wherever you

 pixels.setPixelColor(blah blah blah 

to print the pixel number and the color being set you will get some clues.

a7

Doing Get: [HTTP] GET... code: 200
Set To Green
Set To Blue

Closing Connection
Doing Get: [HTTP] GET... code: 200
Set To Green
Set To Blue

Closing Connection

Thats what I get from the Serial Monitor

Youve missed my point.

When you print

Set To Green

print out the pixel number you are setting also.

Everywhere you setPixelColor, print the number and the color.

a7

Gotcha.

        if (strcmp(jsonChar, "green") == 0 ) {
          pixels.setPixelColor(pixelIndex, greenPixel);
          lastColour = greenPixel;
          Serial.println("Set To Green");
          Serial.println(pixelIndex, greenPixel);
        }
        if (strcmp(jsonChar, "red") == 0 ) {
          pixels.setPixelColor(pixelIndex, redPixel);
          lastColour = redPixel;
          Serial.println("Set To Red");
          Serial.println(pixelIndex, redPixel);
        }
        if (strcmp(jsonChar, "blue") == 0 ) {
          pixels.setPixelColor(pixelIndex, bluePixel);
          lastColour = bluePixel;
          Serial.println("Set To Blue");
          Serial.println(pixelIndex, bluePixel);
        }
        if (strcmp(jsonChar, "white") == 0 ) {
          pixels.setPixelColor(pixelIndex, whitePixel);
          lastColour = whitePixel;
          Serial.println("Set To White");
          Serial.println(pixelIndex, whitePixel);
        }
        pixelIndex++;
      }
      // If only one bin value is found, repeat colour so whole bin lights up
      if (arraySize == 1) {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(pixelIndex, lastColour);
          Serial.println(pixelIndex, lastColour);

I've updated it to include the above Serial.Println statements. Assuming thats what you mean, I get this:

Doing Get: [HTTP] GET... code: 200
Set To Green
0
Set To Blue
1

Closing Connection

Cheers

Mike

OK, so the above never gets triggered, as do not your other colors.

Should it? Can you guess what's next? :expressionless:

After you get but before you act on a message print it so you get an idea of what you are reacting to

        parsed[i].printTo((char*)jsonChar, parsed.measureLength() + 1);

// right here. what's in that jsonChar thingy or what was in the parsed[] array???

        // Parse retreived data and check for for matching colours. If webpage says Green, show Green LED, if Red, show Red, etc
        if (strcmp(jsonChar, "green") == 0 ) {

It is primitive, but print statements are your first and easiest self-help tool. Otherwise you are flying blind, and making possibly unwarranted assumptions about what is in you variables and how your program is flowing.

a7

So it shouldn't be triggering all of them at the moment. I've simplified what it's reading so that it's just one colour, blue. In this instance it should be lighting up all 4 LEDs, however it just lights up two. I'm thinking it only thinks there are two LEDs.

Cheers for your help explaining this btw, stuff like this is gold for a newbie like me. Much appreciated.

Mike

You are setting the same pixel each time through this loop. Maybe you wanted to use i rather than pixelIndex since that value is actually changing :slight_smile:

NP this is what passes for life here.

This

  int pixelIndex = 0;

is a local variable, every time loop is called it's a new world set to zero. That is probably what you want.

This

      pixelIndex++; 

sorta is counting the arraySize number of <whatever has the colors messages or packets?>

  int arraySize = parsed.size();

So print arraySize - betting it is two, so pixelIndex doesn't go above 2.

Also this

      if (arraySize == 1) {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(pixelIndex, lastColour);
        }
      }

would make perfect more sense if you incremented pixelIndex within the loop - otherwise you just hammering away at the same pixel index that was already set above.

HTH and keep printing stuff you wonder about or controls the flow!

a7