[solved] behavior of char array and "string" when calling a function

Hello everybody.

I am currently working with NodeMCU development boards and wondered about the behavior of char arrays.

I have a function sendUDP (I left out the unnecessary parts). And there are two ways to call this function

void sendUDP(char massage[]){}

//1. way of calling sendUDP
sendUDP("SM05xxxx");

//2. way of calling sendUDP
char mssg[]="SM05xxxx";
sendUDP(mssg);

When calling sendUDP the first way, everything works fine, but when I call sendUDP the second way it dosn't. But I want to send a message via UDP where I can manipulate the 'x' chars in the message with bitWrite and I can't change the x when calling the function the first way.

In case this is not enough information to give a clear answer, here a bit more detail:

I am using WiFiUdp.h and ESP8266Wifi.h
(first the code, then the explanation; as bevor, I left out the unnecessary lines)

char* udp_BufferSend[] = {" ", " ", " ", " ", " ", " "}; //buffer which holds outgoing data
byte udp_CurrBuffSendPos = 0; //nr of elements in bufferSend
bool udp_TxBufferBusy = false;

void handleUDPtx(){
  if(udp_CurrBuffSendPos>0){
    Udp.beginPacket(clientA, portClientA);
    Udp.write(udp_BufferSend[0]);
    Udp.endPacket();
  }
}

void sendUDP(char massage[]){
  if(!udp_TxBufferBusy){
    udp_BufferSend[udp_CurrBuffSendPos] = &massage[0];
    udp_CurrBuffSendPos++;
    if(udp_CurrBuffSendPos==5){
      udp_TxBufferBusy = true;
    }
  }
}

The handler function "handleUDPtx" is called in the loop every 200ms. When I want to send a message I call "sendUDP" and this function will add my message to the "udp_BufferSend". So whenever "handleUDPtx" is called, it will send the first message of the buffer and afterwards another function will remove that message from the buffer (that's something I left out).

To be more specific about my question: Why don't I receive "SM05xxxx" at the Client side, when I call sendUDP the second way?
When calling sendUDP the second way with char mssg[]="SM05xxxx" (without changing the bits of the 'x' chars) then I will always get the same 8 Bytes, that are seemingly random?
10 8B FE 3F C0 A8 89 15

I hope you can help me.
CodeCrafter1

udp_BufferSend[0] is a single character, in the example you posted.

Try:

    Udp.write(udp_BufferSend);

Don't forget the required zero terminator in a C-string. This is not a valid C-string:

char* udp_BufferSend[] = {" ", " ", " ", " ", " ", " "}; //buffer which holds outgoing data

Always post ALL the code, or if it is too large, the smallest example that will compile and run to demonstrate the problem.

jremington:
Don't forget the required zero terminator in a C-string. This is not a valid C-string:

char* udp_BufferSend[] = {" ", " ", " ", " ", " ", " "}; //buffer which holds outgoing data

I see an array of six pointers to well-formed 1 char / 2 byte C-strings.

jremington:
udp_BufferSend[0] is a single character, in the example you posted.

See above.

Ahh, you are (partially) right. I wasn't paying attention.

avr-gcc will form an array of six identical pointers to ONE two byte string, consisting of a blank and a zero terminator.

But not enough was posted to determine the real problem.

Now I used the last hour to make two lighter versions of the code, so you can have a compileable version.

Client NodeMCU code

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

IPAddress serversIP(...,...,...,...);
const uint32_t serversPort = 1337;

IPAddress myIP(...,...,...,...);
const uint32_t localPort = 1337;
IPAddress mySubnet(...,...,...,...);
IPAddress myGateway(...,...,...,...);

const char* WiFissid = "...";
const char* WiFipass = "...";

WiFiUDP Udp; 

void startWiFi(){
  WiFi.disconnect();
  delay(20);
  WiFi.config(myIP,myGateway,mySubnet);
  WiFi.mode(WIFI_STA);
  Serial.println("init WiFi:");
  WiFi.begin(WiFissid, WiFipass);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("UDP server on port "); Serial.println(localPort);

  Udp.begin(localPort); //start UDP-Server
}

int checkUDPServer()
{
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    char incomingPacket[UDP_TX_PACKET_MAX_SIZE];
    Serial.print("Received "); Serial.print(packetSize);
    Serial.print(" from IP "); Serial.print(Udp.remoteIP());
    Serial.print(" Port "); Serial.println(Udp.remotePort());
    // read the packet into packetBufffer
    int len = Udp.read(incomingPacket, 255);

    for(byte i = 0; i<len;i++) {
      Serial.print(incomingPacket[i], HEX); Serial.print(" ");
    }
    Serial.println();
    for(byte i = 0; i<len;i++) {
      Serial.print(incomingPacket[i]);
    }
    Serial.println();
    
    incomingPacket[len] = 0;
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write("OK");
    Udp.endPacket();
  }
}
void setup() {
  Serial.begin(9600);

  startWiFi();
  
  Udp.beginPacket(serversIP, serversPort);
  Udp.write("HI21");
  Udp.endPacket(); 
}

void loop() {
  checkUDPServer();
}

Server NodeMCU code:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>


IPAddress myIP(...,...,...,...);
IPAddress mySubnet(...,...,...,...);
IPAddress myGateway(...,...,...,...);
const uint32_t localPort = 1337;

IPAddress clientA(...,...,...,...);
const uint32_t portClientA = 1337;

const char* WiFissid = "...";
const char* WiFipass = "...";

WiFiUDP Udp;

void startWiFi(){
  WiFi.disconnect();
  delay(20);
  WiFi.config(myIP,myGateway,mySubnet);
  WiFi.mode(WIFI_STA);
  Serial.print(F("init WiFi:"));
  WiFi.begin(WiFissid, WiFipass);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.print(F("Connected! IP address: "));
  Serial.println(WiFi.localIP());
  Serial.printf("UDP server on port %d\n", localPort);

  Udp.begin(localPort);
}

char* udp_BufferSend[] = {" ", " ", " ", " ", " ", " "}; //buffer which holds outgoing data
byte udp_CurrBuffSendPos = 0; //nr of elements in bufferSend
bool udp_TxBufferBusy = false; 

void handleUDPtx(){
  static uint32_t previousSend = 0;
  if(udp_CurrBuffSendPos>0){
    //if mssg in buffer...
    if (millis() - previousSend > 200){
      Serial.println(udp_BufferSend[0]);

      Udp.beginPacket(clientA, portClientA);
      Udp.write(udp_BufferSend[0]);
      Udp.endPacket();    
      previousSend = millis();
    }
  }
}

void sendUDP(char massage[]){
  if(!udp_TxBufferBusy){
    udp_BufferSend[udp_CurrBuffSendPos] = &massage[0];
    udp_CurrBuffSendPos++;
    if(udp_CurrBuffSendPos==5){
      udp_TxBufferBusy = true;
    }
  }
}

void handleUDPrx(){
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    // buffers for receiving and sending data
    char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1];// buffer to hold incoming packet,
    char ReplyBuffer[] = "OK";
    Serial.printf("Received packet of size %d from %s:%d\n    (to %s:%d, free heap = %d B)\n",
                  packetSize,
                  Udp.remoteIP().toString().c_str(), Udp.remotePort(),
                  Udp.destinationIP().toString().c_str(), Udp.localPort(),
                  ESP.getFreeHeap());
    // read the packet into packetBufffer
    int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    packetBuffer[n] = 0;
    Serial.println(packetBuffer);
    //handle received mssg
    if(packetBuffer[0] == 'O' && packetBuffer[1] == 'K'){ 
      //confirmation message "OK"
      Serial.println(F("OK mssg arrived")); //DEBUG
      if(udp_CurrBuffSendPos>0){
        char space[] = " ";
        //push every mssg forward
        udp_BufferSend[0] = udp_BufferSend[1];
        udp_BufferSend[1] = udp_BufferSend[2];
        udp_BufferSend[2] = udp_BufferSend[3];
        udp_BufferSend[3] = udp_BufferSend[4];
        udp_BufferSend[4] = udp_BufferSend[5];
        udp_BufferSend[5] = &space[0];
        udp_CurrBuffSendPos--;
        udp_TxBufferBusy = false;
      }
      return;
    }
    if(packetBuffer[0] == 'H' && packetBuffer[1] == 'I'){
      if(packetBuffer[2] == '2' && packetBuffer[3] == '1'){
        char mssg[]="SM05xxxx";
        sendUDP(mssg);
      }
    }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println();

  startWiFi();
}

void loop() {
  handleUDPrx();
  delay(50);
  handleUDPtx();
  delay(50);
}

First start the server NodeMCU. Afterwards the client NodeMCU. The Client will send one message "HI21" and the server will answer with the problem I showed (see handleUDPrx at server code)

    if (packetBuffer[0] == 'H' && packetBuffer[1] == 'I') {
      if (packetBuffer[2] == '2' && packetBuffer[3] == '1') {
        char mssg[] = "SM05xxxx";
        sendUDP(mssg);
      }
    }

mssg[] is local to the if statement. You pass it to sendUDP() where you then store a pointer to the local variable in udp_BufferSend. At the end of the if statement, mssg[] ceases to exist and the memory where it is stored is being overwritten by other code.

Passing a string literal to sendUDP() creates a const char array in memory to store the literal, and does not overwrite it with other data.

Thanks for this clarification @david_2018.

After changing mssg to a global var, it now works.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.