Neopixel .show() method causing SOS

Dear all,

I have a strange issue since today and I can’t figure out what’s going on. The code below worked now for some while. I just had some issues with the UDP / WiFi stability and did some modifications. In particular I played around with SYSTEM_THREAD(ENABLED) to see if that solves the topic because in the forum someone has stated that this might solve it. But I have redone all changes and now my photon always crashes with the SOS (Hard fault) when the strip.show() method is beeing called. When I comment this out. the photon keeps running. So I was able to isolate this issue, but now I have no idea anymore.
The photon has firmware 0.6.0.

Any help is really appreciated!

Heres the code:

SYSTEM_MODE(MANUAL);
//STARTUP(WiFi.selectAntenna(ANT_INTERNAL)); // selects the CHIP antenna
//STARTUP(WiFi.selectAntenna(ANT_EXTERNAL)); // selects the u.FL antenna
STARTUP(WiFi.selectAntenna(ANT_AUTO)); // continually switches at high speed between antennas

// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

// This #include statement was automatically added by the Particle IDE.
#include "my_helpers.h"

// This #include statement was automatically added by the Particle IDE.
#include <PietteTech_DHT.h>

//#################################################################
//      GLOBAL DEFINITIONS
//#################################################################

// Define the LED strip parameters
#define PIXEL_COUNT 70      // Number of Pixels (1 Pixel = 10 cm)
#define PIXEL_PIN D0        // Pin of the data connection to the strip
#define PIXEL_TYPE TM1829   // Strip controller type

// Define the Temperature Sensor parameters
#define DHTPIN   D2         // Digital pin for communications
#define DHTTYPE  DHT22      // Sensor type DHT11/21/22/AM2301/AM2302

// Define the UDP parameters
const int UDP_TX_PACKET_MAX_SIZE=1024;          //UDP package size
const unsigned int localPort = 8888;            //UDP Port used for two way communication
const unsigned int localPortLED = 8001;         //UDP Port used to ping back the LED color
const unsigned int localPortMeasures = 8002;    //UDP Port used to ping back the Temperature
const unsigned int OH_Port = 25002;             //UDP Port to send the data to
const IPAddress OpenHabIP(192,168,178,134);     //IP Adress of the openhab server. This is needed when the connection is initated by the photon and not by OH

const unsigned long beat_rate = 10000;      // hearbeat rate to do something every some seconds

// Switch debugging on(1)/off(0)
const int debug = 1;

//#################################################################
//      Needed Objects
//#################################################################

// An UDP instance to let us send and receive packets over UDP
UDP Udp;

// create some helping fuctions
my_helpers h = my_helpers(debug);

// construct the strip object
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

//buffer to hold incoming packet
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; 

// Temperature Sensor instantiate
PietteTech_DHT DHT(DHTPIN, DHTTYPE);

//#################################################################
//      The Variables we need
//#################################################################

// timer to do something every x seconds
unsigned long time_stamp = 0;

// the port of the remote device sending the command
int remoteport= 0;

// the IP address of the remote device sending the command
IPAddress remoteIP(0,0,0,0);

// the measured DHT Humidity
String Humidity = "";

// the measured DHT Temperature
String Temperature = "";

// the RGB Value for the LED Strip
int RGBValues[3];

// the number of pixels we want to change individually
int pixels;

// the array to store the ID of the pixel and the color
int Pixel[4];

// the data pack to send back to the sender
char callbackData[0];

int DHTerrorcode;

// The temperature & humidity data which gets send back 
String measured_values ="";

// The MAC Address of the access point
byte bssid[6];

// size of the received UDP Package
//int packetSize;

//count the loops for debuging
unsigned long loopcount = 0;

//String datagram ="";

//#################################################################
//      Setup
//#################################################################
void setup() {

// Print your device IP Address via serial for debuging
if (debug == 1){Serial.begin(9600);}
if (debug == 1){delay (8000);}

// connect to the hood
WiFi.on();

// connect to my network
WiFi.setCredentials("mywlan", "topsecrect");
WiFi.connect();
while(!WiFi.ready());

if (debug == 1){Serial.print("My IP: ");}
if (debug == 1){Serial.println(WiFi.localIP());}

// start the UDP
Udp.begin(localPort);

//Setup the strip & initialize all pixels to 'off'
strip.begin();
strip.show(); 

Particle.syncTime(); // Sync time with cloud
Time.zone(1); // From UTC to CET
if (debug == 1){Serial.print("Current time: ");}
if (debug == 1){Serial.println(Time.timeStr());} // Wed May 21 01:08:47 2014

} // end setup

//#################################################################
//      LOOP
//#################################################################
void loop() {

int packetSize = Udp.parsePacket();
memset(&packetBuffer[0], 0, sizeof(packetBuffer));

if(packetSize)
    {
        
    if (debug == 1){Serial.print("Received packet of size ");}
    if (debug == 1){Serial.println(packetSize);}
    if (debug == 1){Serial.print("From ");}
    
    remoteIP = Udp.remoteIP();
    remoteport = Udp.remotePort();

    // Print the remote IP & port
    if (debug == 1)
    {for (int i =0; i < 4; i++){
    Serial.print(remoteIP[i], DEC);
    if (i < 3){Serial.print(".");}}}
    if (debug == 1){Serial.print(", port ");}
    if (debug == 1){Serial.println(remoteport);}

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
        if (debug == 1){Serial.println("Contents UDP datagram:");}
        if (debug == 1){Serial.println(packetBuffer);}
        
    //store the datagram
    String datagram = String(packetBuffer);

// DO CHANGES TO THE LED STRIP
// ff = function number e.g. 01, 02 ...
// rrr, ggg, bbb RGB values 0 - 255
// ppp = pixel number 000 - 999

switch (datagram.substring(0,2).toInt())
{
    
//#####################################################################################################################
case 0: // 0 = Off: Switch off the strip
    colorAll(strip.Color(0, 0, 0), 0);
break; // end if ("Off")


//#####################################################################################################################
case 1: // 1 = ColorWipe: change the strip pixel by pixel. data package: ffrrrgggbbb
    h.RGBFromString(RGBValues, datagram.substring(2));
        if (debug == 1){Serial.println("ColorWipe");}
        if (debug == 1){Serial.println("Data: ");}
        if (debug == 1){Serial.println(datagram.substring(2));}
        if (debug == 1){Serial.println("RGB Values: ");}
        if (debug == 1){Serial.println(RGBValues[0]);}
        if (debug == 1){Serial.println(RGBValues[1]);}
        if (debug == 1){Serial.println(RGBValues[2]);}
        
    colorWipe(strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]), 300);
    //echo back the UDP message
    h.UDP_callback(localPortLED, packetBuffer, remoteIP, OH_Port);

break; // end else if ("ColorWipe")


//#####################################################################################################################
case 2: // 2=ColorAll: change the strip at once. data package: ffrrrgggbbb
    
    h.RGBFromString(RGBValues, datagram.substring(2));  
        if (debug == 1){Serial.println("ColorAll");}
        if (debug == 1){Serial.println("Data: ");}
        if (debug == 1){Serial.println(datagram.substring(2));}
        if (debug == 1){Serial.println("RGB Values: ");}
        if (debug == 1){Serial.println(RGBValues[0]);}
        if (debug == 1){Serial.println(RGBValues[1]);}
        if (debug == 1){Serial.println(RGBValues[2]);}        

    colorAll(strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]), 0);

    //echo back the UDP message
    h.UDP_callback(localPortLED, packetBuffer, remoteIP, OH_Port);
    
break; // end else if (command == "ColorAll")


//#####################################################################################################################
case 9: // 9 = Pixel: control one ore more pixel individually data package: ffppprrrgggbbbppprrrgggbbb...

    // determine the number of pixels we have to change. one pixel control package has always 12 characters in the data package (ppprrrgggbbb).
    // so the number of pixels is the length of the data package / 12
    pixels = (datagram.length()-2) / 12;
    
    if (debug == 1){Serial.println("Pixel");}
    if (debug == 1){Serial.println("Data: ");}
    if (debug == 1){Serial.println(datagram.substring(2));}
    
    // fill the pixel array from the data package
        for (int i=0; i < pixels; i++)
        {
            h.pixeldata (Pixel, datagram.substring((i+2) * 12, ((i+2) * 12) + 12)); // cut the data package into the pixel control packages
            strip.setPixelColor(Pixel[0], strip.Color(Pixel[1], Pixel[2], Pixel[3]));
                if (debug == 1){Serial.println("Pixel Data: ");}
                if (debug == 1){Serial.println(Pixel[0]);}
                if (debug == 1){Serial.println(Pixel[1]);}
                if (debug == 1){Serial.println(Pixel[2]);}  
                if (debug == 1){Serial.println(Pixel[3]);}  
        }
        
    strip.show();
    //echo back the UDP message
    h.UDP_callback(localPortLED, packetBuffer, remoteIP, OH_Port);   
    
break; // end else if ("Pixel")


//#####################################################################################################################
case 8: // 8 = Temp: return temperature and humidity
    
    sendTemp(remoteIP);

break; // end else if ("Temp")
} // end switch
//#####################################################################################################################

} // end if(packetSize)



// Do something every some seconds
    if (time_stamp < millis()){
        
        // This was recommended by the forum. Sometimes the UDP just stops receiving packages
        Udp.stop();
        delay(1);
        Udp.begin(localPort);
        
        // Show some WiFi data for debugging     
        if (debug == 1){Serial.print("My IP: ");}
        if (debug == 1){Serial.println(WiFi.localIP());}
        if (debug == 1){Serial.println("Connected to Accesspoint: ");}
        if (debug == 1){WiFi.BSSID(bssid);}
        if (debug == 1){Serial.printlnf("%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); }
        if (debug == 1){Serial.println("signal strength from -127 (weak) to -1dB (strong):"); }
        if (debug == 1){Serial.println(WiFi.RSSI());}        

        sendTemp(OpenHabIP);
        loopcount++;
        time_stamp = millis() + beat_rate;
    } //end loop timer


} //end loop function

//#################################################################
//      Some Functions 
//#################################################################


// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint8_t wait) {
  uint16_t i;
  
  for(i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
  }
  strip.show();
  delay(wait);
}

// Fill the dots one after the other with a color, wait (ms) after each one
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}


// Send temperature and humidity via a small JSON to a specific IP
void sendTemp (IPAddress sendtoIP)
{
        DHTerrorcode = DHT.acquireAndWait();
        
        if (debug == 1){switch (DHTerrorcode) {
            case DHTLIB_OK:
                Serial.println("OK");
                break;
            case DHTLIB_ERROR_CHECKSUM:
                Serial.println("Error\n\r\tChecksum error");
                break;
            case DHTLIB_ERROR_ISR_TIMEOUT:
                Serial.println("Error\n\r\tISR time out error");
                break;
            case DHTLIB_ERROR_RESPONSE_TIMEOUT:
                Serial.println("Error\n\r\tResponse time out error");
                break;
            case DHTLIB_ERROR_DATA_TIMEOUT:
                Serial.println("Error\n\r\tData time out error");
                break;
            case DHTLIB_ERROR_ACQUIRING:
                Serial.println("Error\n\r\tAcquiring");
                break;
            case DHTLIB_ERROR_DELTA:
                Serial.println("Error\n\r\tDelta time to small");
                break;
            case DHTLIB_ERROR_NOTSTARTED:
                Serial.println("Error\n\r\tNot started");
                break;
            default:
                Serial.println("Unknown error");
                break;
            }} // end debug switch
        

        //Get the Humidity
        Humidity = String(DHT.getHumidity(), 2);
        if (debug == 1){Serial.print("Humidity (%): ");}
        if (debug == 1){Serial.println(Humidity);}
       //Get the Temperature
        Temperature = String(DHT.getCelsius(), 2);
        if (debug == 1){Serial.print("Temperature (oC): ");}
        if (debug == 1){Serial.println(Temperature);}

        // Create a JSON Feedback e.g.: {"T1":25.21,"H1":40.43}
        measured_values = "{\"Time\":\"" + Time.timeStr() + "\",\"T1\":" + Temperature + ",\"H1\":" + Humidity + ",\"Loops\":" + loopcount + "}";

        memset(&callbackData, 0, measured_values.length());
        measured_values.toCharArray(callbackData, measured_values.length()+1);
        
        if (debug == 1){Serial.print("Values to send: ");}       
        if (debug == 1){Serial.println(callbackData);}
        
        if (debug == 1){Serial.print("Sending to IP: ");}
        if (debug == 1){Serial.println(sendtoIP);}
        if (debug == 1){Serial.print("Port: ");}
        if (debug == 1){Serial.println(OH_Port);}
        if (debug == 1){Serial.print("From Port: ");}
        if (debug == 1){Serial.println(localPortMeasures);}
        h.UDP_callback(localPortMeasures, callbackData, sendtoIP, OH_Port);
    
}

even show() in setup() causes an SOS condition?

comment out all of your loop() function contents and try that…

it is hard to read through your code with all of that serial debug…

this:

if (debug == 1){Serial.println("ColorWipe");}
        if (debug == 1){Serial.println("Data: ");}
        if (debug == 1){Serial.println(datagram.substring(2));}
        if (debug == 1){Serial.println("RGB Values: ");}
        if (debug == 1){Serial.println(RGBValues[0]);}
        if (debug == 1){Serial.println(RGBValues[1]);}
        if (debug == 1){Serial.println(RGBValues[2]);}

can be condensed to a single line:

if(debug ==1) Serial.printlnf("Colorwipe\nData: %s\nRGB Values: R%03d, G%03d, B%03d", datagram.substring(2)), RGBValues[0], RGBValues[1], RGBValues[2]); 

kind-of-thing.

1 Like

Hi James,

thanks a lot for your fast reply.
I have built in your suggestion on the debugging already. I am not such a professional, so I am glad for every input.
I was spending now some hours longer on my initial topic and it is very strange.
As stated before when I take out the show() it works. In the setup() function it works in every constellation.

So I thought it might has something to do with my “memory management”.

it the send_temp function I have the following statement:

    memset(&callbackData, 0, measured_values.length());
    measured_values.toCharArray(callbackData, measured_values.length()+1);

When I remove this the photon keeps working without any issues. But why does this influence .show() ?
Honestly, I am pretty unskilled in handling memset and I am not sure what I need to do to pass the data to Udp.write() in the correct manner.

the method which is called looks like this:

void my_helpers::UDP_callback (int sending_port, char data[], IPAddress remoteIP, int remoteport )
{

    UDPsender.stop();
    UDPsender.begin(sending_port);
    UDPsender.beginPacket(remoteIP, remoteport);
    UDPsender.write(data);
    UDPsender.endPacket();
    UDPsender.stop();
}

Do I even need memset?

it seems you are overwriting one of the buffers and stepping on some other variables.

sorry I cannot be more helpful, but your code is so darned over-commented and filled with superfluous Serial activity, it hurts my eyes to look at it!

:smirk:

1 Like
char callbackData[0];
...
memset(&callbackData, 0, measured_values.length());
measured_values.toCharArray(callbackData, measured_values.length()+1);

You are not reserving any space for callbackData but you are clearing more than zero bytes - that’s already wrong, but you should also not use the addressOf operator (&) on the array variable itself, since that’s already a pointer.

You need to give your array a proper size

char callbackData[128];

And you need to clear like this

memset(callbackData, 0, sizeof(callbackData));
// or
memset(&callbackData[0], 0, sizeof(callbackData));
2 Likes

Hi @ScruffR,

thanks! I think that was the root cause. Actually I don’t know why I use the & operator. I simply transferred this from a UDP example program. Similar like I use in the beginning of the loop().
@BulldogLowell, I understand that you get eye cancer by looking at my coding :slight_smile: It wasn’t meant to go public. And with every issue and test some more debugging statements remained…

For completness here is the cleaned up code:

SYSTEM_MODE(MANUAL);
STARTUP(WiFi.selectAntenna(ANT_AUTO)); 
#include <PietteTech_DHT.h>
#include <neopixel.h>
#include "my_helpers.h"

// Define the LED strip parameters
#define PIXEL_COUNT 40
#define PIXEL_PIN D0
#define PIXEL_TYPE TM1829 

// Define the Temperature Sensor parameters
#define DHTPIN   D2
#define DHTTYPE  DHT22 

// Define the UDP parameters
const int UDP_TX_PACKET_MAX_SIZE=256;          //UDP package size
const unsigned int localPort = 8888;            //UDP Port used for two way communication
const unsigned int localPortLED = 8001;         //UDP Port used to ping back the LED color
const unsigned int localPortMeasures = 8002;    //UDP Port used to ping back the Temperature
const unsigned int OH_Port = 25002;             //UDP Port to send the data to
const IPAddress OpenHabIP(192,168,178,134);     //IP Adress of the openhab server. This is needed when the connection is initated by the photon and not by OH
const unsigned long beat_rate = 10000; 
const int debug = 1;

UDP Udp;
my_helpers h = my_helpers(debug);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

//buffer to hold incoming packet
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; 

PietteTech_DHT DHT(DHTPIN, DHTTYPE);

unsigned long time_stamp = 0;
int remoteport= 0;
IPAddress remoteIP(0,0,0,0);

// the RGB Value for the LED Strip
int RGBValues[3];
// the number of pixels we want to change individually
int pixels;
// the array to store the ID of the pixel and the color
int Pixel[4];

// the data pack to send back to the sender
char callbackData[UDP_TX_PACKET_MAX_SIZE];

String Humidity = "";
String Temperature = "";
int DHTerrorcode;

// The temperature & humidity data which gets send back 
String measured_values ="";

byte bssid[6];

int packetSize;

//count the loops for debuging
unsigned long loopcount = 0;

String datagram ="";

void setup() {


    // connect to the hood
    WiFi.on();
    
    // connect to my network
    WiFi.setCredentials("wifi", "secret");
    WiFi.connect();
    while(!WiFi.ready());
    
    // start the UDP
    Udp.begin(localPort);
    
    //Setup the strip & initialize all pixels to 'off'
    strip.begin();
    strip.show(); 
    
    Particle.syncTime(); // Sync time with cloud
    Time.zone(1); // From UTC to CET


} // end setup



void loop() {

packetSize = Udp.parsePacket();
memset(&packetBuffer[0], 0, sizeof(packetBuffer));

if(packetSize)
    {
        
    remoteIP = Udp.remoteIP();
    remoteport = Udp.remotePort();

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    datagram = String(packetBuffer);


switch (datagram.substring(0,2).toInt())
{
case 0: // 0 = Off: Switch off the strip
        colorAll(strip.Color(0, 0, 0), 0);
    break; // end if ("Off")
    
case 1: // 1 = ColorWipe: change the strip pixel by pixel. data package: ffrrrgggbbb
        h.RGBFromString(RGBValues, datagram.substring(2));
        colorWipe(strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]), 300);
        //echo back the UDP message
        h.UDP_callback(localPortLED, packetBuffer, remoteIP, OH_Port);
    break; // end else if ("ColorWipe")
    
case 2: // 2=ColorAll: change the strip at once. data package: ffrrrgggbbb
        
        h.RGBFromString(RGBValues, datagram.substring(2));
        colorAll(strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]), 0);
        //echo back the UDP message
        h.UDP_callback(localPortLED, packetBuffer, remoteIP, OH_Port);
    break; // end else if (command == "ColorAll")
    
case 9: // 9 = Pixel: control one ore more pixel individually data package: ffppprrrgggbbbppprrrgggbbb...

        pixels = (datagram.length()-2) / 12;
        
        // fill the pixel array from the data package
            for (int i=0; i < pixels; i++)
            {
                h.pixeldata (Pixel, datagram.substring((i+2) * 12, ((i+2) * 12) + 12)); // cut the data package into the pixel control packages
                strip.setPixelColor(Pixel[0], strip.Color(Pixel[1], Pixel[2], Pixel[3]));
            }
        strip.show();
        //echo back the UDP message
        h.UDP_callback(localPortLED, packetBuffer, remoteIP, OH_Port);   
    break; // end else if ("Pixel")
    
case 8: // 8 = Temp: return temperature and humidity
        sendTemp(remoteIP);
    break; // end else if ("Temp")
    } // end switch
} // end if(packetSize)


// Do something every some seconds
    if (time_stamp < millis()){
        // This was recommended by the forum. Sometimes the UDP just stops receiving packages
        Udp.stop();
        delay(1);
        Udp.begin(localPort);
   
        sendTemp(OpenHabIP);
        loopcount++;
        time_stamp = millis() + beat_rate;
    } //end loop timer
} //end loop function

//#################################################################
//      Function Section
//#################################################################


// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint8_t wait) {
  uint16_t i;
  
  for(i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
  }
  strip.show();
  delay(wait);
}

// Fill the dots one after the other with a color, wait (ms) after each one
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}


// Send temperature and humidity via a small JSON to a specific IP
void sendTemp (IPAddress sendtoIP)
{
    
        DHTerrorcode = DHT.acquireAndWait();

        Humidity = String(DHT.getHumidity(), 2);
        Temperature = String(DHT.getCelsius(), 2);

        // Create a JSON Feedback e.g.: {"T1":25.21,"H1":40.43}
        measured_values = "{\"Time\":\"" + Time.timeStr() + "\",\"T1\":" + Temperature + ",\"H1\":" + Humidity + ",\"Loops\":" + loopcount + "}\0";

        memset(&callbackData[0], 0, measured_values.length());
        measured_values.toCharArray(callbackData, measured_values.length()+1);

        h.UDP_callback(localPortMeasures, callbackData, sendtoIP, OH_Port); 
    
}

It seems to work now. Hopefully…
But thanks a lot for now to both of you!!!

3 Likes