ESP Crashing on udp.recieve

First off, ever since I upgraded to 1.8.8 I couldn’t get stack tracer to appear under tools. So I had to use a bunch of serial.prints to narrow down the crash. It appears to be in udp.recieve.

The purpose of this is to establish a wireless link between two MCUs in a way that makes one a Master, the other the slave. The slave simply acts as an intermediatory between pins and the master. I want the master sketch to act on all pins from both units. They are NodeMCU 12Es.

Pertinent Function:

  Serial.println("UPDREceive");
  int packetSize = Udp.parsePacket();
  char incomingPacketChar[255];
  if (packetSize) {
    // receive incoming UDP packets
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());

    int len = Udp.read(incomingPacketChar, 255);
    if (len > 0)
    {
      incomingPacketChar[len] = 0;
    }
    incomingPacket = incomingPacketChar;
    Serial.print(incomingPacket);
  }
  else {
    strcpy(incomingPacket, "-1");
  }

}

Entire Sketch:

// *** Node 7B


#include <LiquidCrystal_I2C.h>
#include <stdio.h>
#include <stdarg.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP Udp;
//*****************************************************************************************************************************************************************
// -1: InputPullup, 0: Not installed, 1: Input Positive, 2: OUTPUT
int installed[20] = {  0,   -1,     -1,    -1,     -1,    0,    -1,    2,     0,     2,     1,     2,      0,    0,       0,      0,      0,     0,     0,     0 };
char* pinNames[20] = { "D0", "D1", "D2",  "D3",   "D4",   "D5", "D6",   "D7",   "D8", "D9", "D10", "A0", "D0", "D0",    "D0"     "D0",  "D0",  "D0",  "D0",  "D0"  };
char* ssNames[20] = { "x"   "gl7", "LG8", "x",    "x",    "LR8", "AL7", "PW7", "LB8", "RSA", "x",   "x",  "pr7", "mc7", "bo7",   "dr7", "PX7", "pb7", "HO8", "c8r" };

int                     gl7 = D1,                    LR8 = D5,      PW7 = D7;
int                           LG8 = D2,                     AL7 = D6,          LB8 = D8;

int                        pr7 = D0,          dr7 = D0, PX7 = D0,  HO8 = D0;
int                            mc7 = D0,  bo7 = D0,         pb7 = D0, c8r = D0;

int GPIONo[12] = {     16,    5,    4,     0,       2,     14,    12,    13,   0,     3,      0 };
// *****************************************************************************************************************************************************************


// ******

unsigned int localUdpPort = 8888;  // local port to listen on
char receivedChars[255];  // buffer for incoming serial
char* incomingPacket; // for incoming UDP
boolean newData;
int numChars = 255;

float pirActivity;
int arrMax = 9, beeps, beepLen, beepRepeat, beepRepeatS, dirc, doorOpens, doorOpenTime, doorState, entering, iPing, i, iG, iBeep, hookedUp, loops, loops2, pr8Hits, parsed, pexUnlock, powerBoostInc, target;
int redState[3], redRun[3], redIntervalOn[3], redIntervalOff[3];
int sent, beepInterval;

long unsigned sentReset, alarmMS, noKeysMS, doorMS, eventTime, inParseDisbleMS, hertz, pexPush, beepMS, redCycle[3], pirMS, c8rTimer, runOn, runTotal, lastMillis, ESPReset;
String eventName, beepEvent;
String eventSound;

int now[20] = { 0 } ; //Set prior to parse

long number; //stores internodal comm code

long unsigned last[20] = { 0 }; //Millis of last trigger (state change)
long flashStop[3];

const int beepArrSize = 40; // Carefully set this, can cause corruption!

const int deBounceMS = 30; // Debounce delay
const int delayMS = 10; //Loop Delay
const int loopsMax = 5; //Secondary Loop Divider
const long unsigned noKeysDelay = 120000L; // Delay to unlock second time
const int delayDoorOpen = 20100; // Please Close Door Delay
const int c8rTimerMax = 180123; // Time to run powerBoost
// ***********************************************************

//********************************PASSWORD***********
const char* ssid = "JMR";
const char* password = "crystal2965";

void setup() {
  Serial.begin(115200);
  Serial.println("Node 7B");
  wifiSetup();
  pinModes();
}
void pinModes() {
  Serial.println("pinModes");
  for (i = 0; i < arrMax; i++) {
    // Array init loop

    // Set pin-modes based on installed flags
    if (installed[i] == -1) {
      pinMode(nameToGPIO(pinNames[i]), INPUT_PULLUP);
    }
    if (installed[i] == 0) {
      pinMode(nameToGPIO(pinNames[i]), INPUT_PULLUP);
    }
    if (installed[i] == 1) {
      pinMode(nameToGPIO(pinNames[i]), INPUT);
    }
    if (installed[i] == 2) {
      pinMode(nameToGPIO(pinNames[i]), OUTPUT);
    }
  }
}
int nameToGPIO(char* pinName) {
  for (int i = 0; i < 19; i++) {
    if (strcmp(pinName, pinNames[i]) == 0) {
      int nameToGPIO = GPIONo[i];
      Serial.print(pinName); Serial.print(">"); Serial.println(nameToGPIO);
    }
  }
  return -1;
}
void requestHandle() {
  //if there is a request
  //digitalRead it, and send it back.
  Serial.println("ReqHandle");
  char request[5];
  memcpy(request, &incomingPacket[0], 4);
  request[4] = '/0';
  Serial.println(request);
  if (strcmp(request, "Req:") == 0) {
    Serial.print("ReqHandle:REQ ");
    char pinName[4];
    memcpy(pinName, &incomingPacket[5], 3);
    pinName[3] = '/0';
    Serial.println(pinName);
    int dRead = digitalRead2(pinName);
    Udp.beginPacket("192.168.1.138", 8888);
    Udp.write(dRead);
    Udp.endPacket();
  }
  if (strcmp(request, "Wri:") == 0) {
    Serial.print("ReqHandle:Wri ");
    //Wri: dr7 1
    char pinName[4];
    memcpy(pinName, &incomingPacket[5], 3);
    pinName[3] = '/0';
    Serial.print(pinName);
    int value = incomingPacket[10];
    digitalWrite2(nameToGPIO(pinName), value);
  }
}
void loop() {
  //Get pin OUTPUT commands
  Serial.println("loop");
  pinRead();
 udpReceive();
  if (incomingPacket) {
    requestHandle();
  }
  delay(10);
}
void pinRead() {
  Serial.print("pinread");
  for (int i = 0; i < 19; i++) {
    Serial.print(i);
    now[i] = digitalRead2(ssNames[i]);
    //Serial.println(ssNames[i]);
  }
}
void wifiSetup() {
  Serial.println("wifiSetup");
  Serial.printf("Connecting to %s ", ssid);

  IPAddress ip(192, 168, 1, 138);
  IPAddress gw(192, 168, 1, 254);
  IPAddress dns(192, 168, 1, 254);
  IPAddress sn(255, 255, 255, 0);
  WiFi.config(ip, gw, sn, dns);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.println(".");
  }
  Serial.println(" connected");

  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}
int digitalRead2(char* pinNo) {
  char* udpRead;
  char* pinNoA;
  Serial.println("DR");
  Serial.print(pinNo);
  Serial.print("/"); Serial.println(nameToGPIO(pinNo));
  if (nameToGPIO(pinNo) == 0) {
    //If pin name is on other board, request it.
    Serial.println("DR D0");
    char* code = strcpy(code, "Req: ");
    code = strcat(code, pinNo);
    Serial.println("DR UDP Send");
    Udp.beginPacket("192.168.1.137", 8888);
    Udp.write(code);
    Udp.endPacket();
    Serial.println("DR UDP Recv");

    long udpMS = millis();
    while (udpRead == "") {
      udpReceive();
      strcpy(udpRead, incomingPacket);
      if (millis() - udpMS > 500) {
        return -1;
      }
    }
    return atoi(udpRead);
  }
  else {
    Serial.println("DR Else");
    return digitalRead(nameToGPIO(pinNo));
  }
}
void digitalWrite2(int pinNo, int value) {
  if (pinNo == D0) {
    String code = "Wri: " + String(pinNo) + " " + String(value);
    char* charCode;
    code.toCharArray(charCode, 10);
    Udp.beginPacket("192.168.1.137", 8888);
    Udp.write(charCode);
    Udp.endPacket();
  }
  else {
    digitalWrite(pinNo, value);
  }
}



void sp(long code) { //Serial Print - for sending status information
  Serial.println(code);

  Udp.beginPacket("192.168.1.139", 8888);
  Udp.write(code);
  Udp.endPacket();
}
void udpReceive() {
  Serial.println("UPDREceive");
  int packetSize = Udp.parsePacket();
  char incomingPacketChar[255];
  if (packetSize) {
    // receive incoming UDP packets
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());

    int len = Udp.read(incomingPacketChar, 255);
    if (len > 0)
    {
      incomingPacketChar[len] = 0;
    }
    incomingPacket = incomingPacketChar;
    Serial.print(incomingPacket);
  }
  else {
    strcpy(incomingPacket, "-1");
  }

}

No idea if it's the cause of the problem but one thing I notice is that nameToGPIO() always returns -1. Next you try to write to the pin with that number. Further GPIONo does not have 20 elements. I stopped checking code after that.

Also, it's confusing to use the same name for a function and a variable; in nameToGPIO, rename the variable to e.g. pinNum.

Lastly you might want to consider to use a struct to combine installed, pinNames and ssNames and possibly GPIONo (I've added it in the below)

struct PIN
{
  int gpioNo;
  int installed;
  char *pinName;
  char *ssName;
};

PIN pins[]
{
  {16, 0, "D0", "x"},
  {5, -1, "D1", "G17"},

   ...
   ...
};

You need to read up on structs if you're not familiar with them.

Another error:

request[4] = '/0';

...
...

pinName[3] = '/0';

Should be '\0'.

And things like this are probably the cause of your problem

    char* charCode;
    code.toCharArray(charCode, 10);

charCode is a pointer to nowhere; toCharArray() requires a buffer that it can fill, not some undefined location in memory where it can overwrite whatever is stored there.

Not sure if space for a terminating nul-character is required. The memset() is added to make sure that the array is filled with 0 ('\0', nul-character)

    char charCode[11];.
    memset(charCode, 0, sizeof(charCode));
    code.toCharArray(charCode, 10);

When I change char* code to char code[11] I get error on this line:

code = strcat(code, pinNo);

Incompatible types of assignment of char* to char[11].

Hence why I used the char* code in the first place. I'll admit I'm not proficient on pointers, nor structs.

It crashes here, every time: code = strcpy(code, "Req: ");

Oh darn, strcpy doesn't use an l-value

mattlogue: When I change char* code to char code[11] I get error on this line:

code = strcat(code, pinNo);

Incompatible types of assignment of char* to char[11].

Hence why I used the char* code in the first place. I'll admit I'm not proficient on pointers, nor structs.

The error message told you far more than that. The strcat() function copies some data to an array AND returns (unnecessarily, usually) a pointer to the location it wrote the data to. It returns a value so that you can call strcat() in the argument list of a call to strcat(). Should YOU do that? Never!

So, pay attention to which use of the variable code in that statement is causing the problem, and fix, or eliminate, the problem. The simplest solution, in your case, is to ignore the fact that strcat() returns a value (that you do not need).

   strcat(code, pinNo);

By the way, pinNo IMPLIES that the value is a number, and strcat() doesn't deal with numbers, so pinNo is a stupid name for the variable containing the string to be copied.

I took off the l-values on strcat and strcpy and it worked for a bit.

Well, pinNo is a dumb name. I meant to use pinName. Of course there are both and I made it confusing for myself. Right now it is crashing again on Udp.read(IncomingPacket,255);. I have it narrowed down to there with Serial prints falling off just above. Is it really this function that crashes it, discretely? No, I’m sure I f’d up somewhere else, causing a segmentation fault or corrupting memory. My coding is far from impeccable, so I am hounded by ESP exceptions.

And worse, the exceptional exception decoder fails to show in IDE 1.8.8. It disapeered when I updated.

Here is the sketch. I had to lob off most of the declarations for a new post:

// *** Node 7B

int debug = 1;
void setup() {
  Serial.begin(115200);
  Serial.println("Node 7B");
  wifiSetup();
  pinModes();
}
void loop() {
  //Get pin OUTPUT commands
  Serial.println("loop");
  pinRead();
  udpReceive();
  if (incomingPacket) {
    requestHandle();
  }
  delay(10);
}
void pinModes() {
  Serial.println("pinModes");
  for (i = 0; i < arrMax; i++) {
    // Array init loop

    // Set pin-modes based on installed flags
    if (installed[i] == -1) {
      pinMode(nameToGPIO(pinNames[i]), INPUT_PULLUP);
    }
    if (installed[i] == 0) {
      pinMode(nameToGPIO(pinNames[i]), INPUT_PULLUP);
    }
    if (installed[i] == 1) {
      pinMode(nameToGPIO(pinNames[i]), INPUT);
    }
    if (installed[i] == 2) {
      pinMode(nameToGPIO(pinNames[i]), OUTPUT);
    }
  }
}
int nameToGPIO(char* pinName) {
  //Scans thru pinNames for match, returns congruent GPIOno
  Serial.print("NTG");
  if (pinName) {
  for (int i = 0; i < 17; i++) {
    Serial.print(pinName); Serial.print("-vs-"); Serial.println(ssNames[i]);
    if (strcmp(pinName, ssNames[i]) == 0) {
      if (strcmp(pinName, "x") == 0) return -1;
      ix = i;
      Serial.print(pinName);
      Serial.print(">");
      Serial.println(GPIONo[i]);
      return GPIONo[i];
    }
  }
  }
  return -1;
}
void requestHandle() {
  //if there is a request
  //digitalRead it, and send it back.
  Serial.println("ReqHandle");
  char request[5];
  memcpy(request, &incomingPacket[0], 4);
  request[4] = '/0';
  Serial.println(request);
  if (strcmp(request, "Req:") == 0) {
    Serial.print("ReqHandle:REQ ");
    char pinName[4];
    memcpy(pinName, &incomingPacket[5], 3);
    pinName[3] = '\0';
    Serial.println(pinName);
    int dRead = digitalRead2(pinName);
    Serial.print("digitalRead2 of ^ is:"); Serial.println(dRead);
    Udp.beginPacket("192.168.1.137", 8888);
    Udp.write(dRead);
    Udp.endPacket();
  }
  if (strcmp(request, "Wri:") == 0) {
    Serial.print("ReqHandle:Wri ");
    //Wri: dr7 1
    char pinName[4];
    memcpy(pinName, &incomingPacket[5], 3);
    pinName[3] = '\0';
    Serial.print(pinName);
    int value = incomingPacket[10];
    Serial.print(nameToGPIO(pinName));
    digitalWrite2(ssNames[ix], value);
  }
}

void pinRead() {
  Serial.print("pinread");
  for (int i = 0; i < 17; i++) {
    Serial.print("Pinread: ");
    Serial.print(i);
    if (abs(installed[i]) == 1)  {
      now[i] = digitalRead2(ssNames[i]);
    }
    int adRead = 0;
    if (installed[i] == 3) {
      int aRead = analogRead(17);
      if (aRead > 600) {
        adRead = 1;
        digitalRead2(ssNames[i]);
      }
    } //installed=3, analog pin
  }
}
void wifiSetup() {
  Serial.println("wifiSetup");
  Serial.printf("Connecting to %s ", ssid);

  IPAddress ip(192, 168, 1, 138);
  IPAddress gw(192, 168, 1, 254);
  IPAddress dns(192, 168, 1, 254);
  IPAddress sn(255, 255, 255, 0);
  WiFi.config(ip, gw, sn, dns);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.println(".");
  }
  Serial.println(" connected");

  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}
int digitalRead2(char pinNo[3]) {
  char udpRead[12];
  char code2[12];
  pinNo[3] = '\0';

  Serial.print(pinNo);
  Serial.print("/"); Serial.println(nameToGPIO(pinNo));
  int inameToGPIO;
  inameToGPIO = nameToGPIO(pinNo);
  Serial.print("DR iname");
  if ((installed[ix] == 0) && (ssNames[ix] != "x")) {
    Serial.print("DR iname0");
    //If pin name is on other board, request it.
    Serial.print("DR memeset");
    memset(code2, 0, sizeof(code2));
    Serial.print("DR Req");
    strcpy(code2, "Req: ");
    Serial.print("DR cat pinNo");
    strcat(code2, pinNo);
    Serial.print("DR beginpacket");
    Udp.beginPacket("192.168.1.137", 8888);
    Serial.print("DR UDP write");
    Udp.write(code2);
    Serial.print("DR endpacket");
    Udp.endPacket();
    Serial.print("DR udpMS") ;
    long udpMS = millis();
    Serial.print("DR while") ;
    incomingPacket = '\0';
    Serial.print("["); Serial.print(incomingPacket); Serial.print("]");
    while (!incomingPacket) {
      Serial.print("DR udprecv") ;
      udpReceive();
      Serial.print("DR delay") ;
      delay(2);
      Serial.print("DR if MS") ;
      if (millis() - udpMS > 100) { //Not currently working.
        Serial.println("UDP Request Timeout");
        return now[ix]; //IF no reply in 100ms, use last reading (now[])
        Serial.print("DR }") ;
      }
      Serial.print("DR After timeout");
    }
    Serial.printf("UDP Packet Returned: %s", incomingPacket);
    return atoi(incomingPacket);
  }
  else {
    Serial.print("DR else ret 0") ;
    if (inameToGPIO == -1) return 0;
    return digitalRead(inameToGPIO);
  }
}
void digitalWrite2(char pinNo[3], int value) {
 int GPIOpin = nameToGPIO(pinNo);
  if ((installed[ix] == 0) && (ssNames[ix] != "x")) {
    String code = "Wri: " + String(pinNo) + " " + String(value);
    char* charCode;
    code.toCharArray(charCode, 10);
    Udp.beginPacket("192.168.1.137", 8888);
    Udp.write(charCode);
    Udp.endPacket();
  }
  else {
    digitalWrite(GPIOpin, value);
  }
}
void sp(long code) { //Serial Print - for sending status information
  if (debug) Serial.println(code);

  Udp.beginPacket("192.168.1.139", 8888);
  Udp.write(code);
  Udp.endPacket();
}
void sps(char str[255]) {
  if (debug) Serial.println(str);
}
void udpReceive() {
  Serial.println("UPDRecv");
  int packetSize = Udp.parsePacket();
  sp(packetSize);
  if (packetSize) {
    sps("if packet size");
    Udp.read(incomingPacket, 255);
    sps("upd read");
   int len = strlen(incomingPacket);
    sps("strlen");
    if (len > 0)
    {
      incomingPacket[len] = 0;
    }
    Serial.printf("UPDReceived: %s", incomingPacket);
  }
  else {
    incomingPacket = 0;
  }
}

Here are the declarations. Thanks for your help!

// *** Node 7B


#include <LiquidCrystal_I2C.h>
#include <stdio.h>
#include <stdarg.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP Udp;
//*****************************************************************************************************************************************************************
// -1: InputPullup, 0: Not installed, 1: Input Positive, 2: OUTPUT
int installed[20] = {  0,   -1,     2,    -1,     -1,    2,    2,         2,      0,      2,    2,     0,    0,     0,       0,      0,      0,    };
char* pinNames[17] = { "D0", "D1", "D2",  "D3",   "D4",   "D5",  "D6",     "D7",  "D8", "D9", "D10", "D0",  "D0",   "D0",    "D0"     "D0",  "D0"  };
char* ssNames[20] = { "x",   "c8r", "LG8", "mc7",  "rd8",  "x", "LB8",    "RSA",   "x", "AL7", "PW7", "gl7", "LR8", "bo7",   "dr7", "pb7", "PX7"  };
int GPIONo[20] = {     16,    5,    4,     0,       2,     14,    12,        13,  15,   3,      1,    17,     0,     0,    0,     0,     0,     0,     0 };

int                     c8r = D1,      mc7 = D3,           AL7 = D9,      RSA = D7,         PW7 = D10;
int                           LG8 = D2,         rd8 = D4,            LB8 = D6;         

int                        pr7 = D0,          dr7 = D0, PX7 = D0,  HO8 = D0;
int                             bo7 = D0,         pb7 = D0;

// *****************************************************************************************************************************************************************


// ******

unsigned int localUdpPort = 8888;  // local port to listen on
char receivedChars[255];  // buffer for incoming serial
char* incomingPacket; // for incoming UDP
boolean newData;
int numChars = 255;
int ix;

float pirActivity;
int arrMax = 9, beeps, beepLen, beepRepeat, beepRepeatS, dirc, doorOpens, doorOpenTime, doorState, entering, iPing, i, iG, iBeep, hookedUp, loops, loops2, pr8Hits, parsed, pexUnlock, powerBoostInc, target;
int redState[3], redRun[3], redIntervalOn[3], redIntervalOff[3];
int sent, beepInterval;

long unsigned sentReset, alarmMS, noKeysMS, doorMS, eventTime, inParseDisbleMS, hertz, pexPush, beepMS, redCycle[3], pirMS, c8rTimer, runOn, runTotal, lastMillis, ESPReset;
String eventName, beepEvent;
String eventSound;

int now[20] = { 0 } ; //Set prior to parse

long number; //stores internodal comm code

long unsigned last[20] = { 0 }; //Millis of last trigger (state change)
long flashStop[3];

const int beepArrSize = 40; // Carefully set this, can cause corruption!

const int deBounceMS = 30; // Debounce delay
const int delayMS = 10; //Loop Delay
const int loopsMax = 5; //Secondary Loop Divider
const long unsigned noKeysDelay = 120000L; // Delay to unlock second time
const int delayDoorOpen = 20100; // Please Close Door Delay
const int c8rTimerMax = 180123; // Time to run powerBoost
// ***********************************************************

//********************************PASSWORD***********

You should not expect us to sew your snippets back together in the proper order. Use the Reply button, NOT the Quick reply field, and select the Additional Options link (yes, I know it doesn't look like a link, but I can't make the forum software any less stupid than it is, nor can I influence the piss-poor choice of ways to do things that seem to be the Arduino team's prefered way of doing anything), and attach your code as ONE file.

    if (strcmp(pinName, ssNames[i]) == 0) {
      if (strcmp(pinName, "x") == 0) return -1;

Do you really have "x"n the array called ssNames? If you do, why don't you KNOW its position in the array?

long unsigned last[20] = { 0 }; //Millis of last trigger (state change)

It is customary to put the qualifier(s) before the type being qualified.

  request[4] = '/0';

A NULL is '\0'. The direction that the slash leans IS important. This has been pointed out before. Why do you continue to ignore the need to fix this crap?

  int inameToGPIO;
  inameToGPIO = nameToGPIO(pinNo);

You aren't being paid by the line of code. Use one line when one line is all that is needed. Way less typing...

    incomingPacket = '\0';

You can set a pointer to NULL, but that is not the correct way.

   incomingPacket = NULL;

is the correct way.

    Serial.print("["); Serial.print(incomingPacket); Serial.print("]");

Once you've done that, it is stupid to then dereference the NULL pointer. I strongly suspect that this is where your exception is happening.

incompingPacket should almost certainly be an array, NOT a pointer to memory that you don't allocate/free.

I changed incomingPacket back to an array and it is working for the time being. I am a very forgetful person. If I'm not looking at it, it may not be fixed. So I will need to work through your recommendations one by one, so it doesn't crash the next time I move a hair.