unsigned char <--> char problem

Hi guys,

I have to read an array of type unsigned char using a function-call: rxBuf. Because this is a library I cannot play with the type of this array. After that I have to copy the content of the array to another array of type char: wifiBuf. After that wifiBuf is send out via WiFi using the WiFi-Library functions (which means I also cannot change the type of wifiBuf).

(Everything down here is in hexadecimal)
Via CAN I am sending the following message to my CAN-shield: ID 100h Data: 14 55 0B CD CD FF DD 45
When I send this via WiFi I receive on my laptop: ID 100 Data: 0

I tried debugging it in the Arduino terminal:
rxBuf: 14 55 0B CD CD FF DD 45
wifiBuf: 14 55 b ffcd ffcd ffff ffdd 45

Other examples:
Via CAN I send: ID 101h Data: 55 55 01
Received laptop: ID 101h Data: 55 55 01
rxBuf: 55 55 01
wifiBuf: 55 55 01

Via CAN I send: ID 102h Data: 20 00 00 0B 00 FF 00 00
Received laptop: ID 102h Data: 20 00 00 00 00 00 00 00
rxBuf: 20 0 0 b 0 ff 0 0
wifiBuf: 20 0 0 b 0 ffff 0 0

--> I found out that in my terminal everytime when a char from wifiBuf is bigger than 127 it adds an ff to it. This is probably because the range of char is from -128 <--> 127. But this is only in the debugging part where I work with ITOA(). In the receiving code on my laptop it does not uses ITOA, but it really looks at all the bits that it is receiving.

Has this something to do with the fact I am using unsigned char for rxBuf and char for wifiBuf? Here is my code:

void SENDviaWIFI(){
    long unsigned int rxId;
    unsigned char     rxLen;
    unsigned char     rxBuf[8];
    char wifiBuf[10] = {0,0,0,0,0,0,0,0,0,0};
    
    CAN.readMsgBuf(&rxLen, rxBuf);
    rxId = CAN.getCanId();
    
    wifiBuf[0] = (char) ((rxId >> 8) & 0xFF);
    wifiBuf[1] =  (char) (rxId & 0xFF);
    
    int i;
    for(i=0; i<rxLen; i++){
      wifiBuf[i+2] = (rxBuf[i] & 0xFF);
    }
    while(i<8){
      wifiBuf[i+2] = (0 & 0xFF);
      i++;
    }

    //debugging
    for(i=0;i<8;i++){
      Serial.print(itoa(rxBuf[i],buf,16));  
      Serial.print(" ");
    }
    Serial.println();
    
    for(i=2;i<10;i++){
      Serial.print(itoa(wifiBuf[i],buf,16));  
      Serial.print(" ");
    }
    Serial.println();
 
    Udp.beginPacket("192.168.1.26", 9000);
    Udp.write(wifiBuf);
    Udp.endPacket();
}

without your code I cannot replicate,

But I assume the char is "upcasted" to an integer while printing

    Udp.write(wifiBuf);

Udp.write sends a single byte NOT THE ARRAY.

Mark

I found out that in my terminal everytime when a byte is bigger than 127

A "byte" is unsigned, but a "char" or "int" is not

robtillaart:
without your code I cannot replicate,

But I assume the char is "upcasted" to an integer while printing

I added my debugging code in my first post :wink:

holmes4:

    Udp.write(wifiBuf);

Udp.write sends a single byte NOT THE ARRAY.

Mark

Ohhh Ok! Now I got it, so I have to call the write() function for each byte I want to send. I have a go on this idea.

AWOL:

I found out that in my terminal everytime when a byte is bigger than 127

A "byte" is unsigned, but a "char" or "int" is not

I actually meant that everytime when a char in the wifiBuf is bigger than 127. I changed it in the post above :wink:

holmes4:

    Udp.write(wifiBuf);

Udp.write sends a single byte NOT THE ARRAY.

Mark

I think it sends the array, because when I send the following: ID: 101h Data: 55 55 01 it works. And when I send: ID: 100h Data: 14 55 0B CD CD FF DD 45 it doesn't work. After what you said I have tried the following:

    int packetSize =0;    
    Udp.beginPacket("192.168.1.26", 9000);
    Udp.write((char)((rxId >> 8) & 0xFF));
    Udp.write((char)(rxId & 0xFF));
    Udp.write((char)(rxBuf[0]&0xFF));
    Udp.write((char)(rxBuf[1]&0xFF));
    Udp.write((char)(rxBuf[2]&0xFF));
    Udp.write((char)(rxBuf[3]&0xFF));
    Udp.write((char)(rxBuf[4]&0xFF));
    Udp.write((char)(rxBuf[5]&0xFF));
    Udp.write((char)(rxBuf[6]&0xFF));
    packetSize = Udp.write((char)(rxBuf[7]&0xFF));
    Udp.endPacket();
    Serial.print("Packet size: ");
    Serial.println(packetSize);

But this is not the way to go,... It only sends out 1 byte now when I monitor packetSize in the Arduino IDE.

How should I tackle this problem to send out 10 bytes as follows:
byte0: ID_high_byte
byte1: ID_low_byte
byte2: payload_byte0
byte3: payload_byte1
byte4: payload_byte2
byte5: payload_byte3
byte6: payload_byte4
byte7: payload_byte5
byte8: payload_byte6
byte9: payload_byte7

  1. No there are two versions of write one sending a single byte and one which sends a number of bytes. Look it up!

  2. char and unsigned char are both 8 bits so no need to do all that converting.

  3. you can put more than one call to write between the beginpacket and the endpacket so no need to create a single array.

    Udp.beginPacket("192.168.1.26", 9000);
    Add code here to send the two byte header you want.
    Udp.write(rxBuf,number of bytes);
    Udp.endPacket();

Mark

    packetSize = Udp.write((char)(rxBuf[7]&0xFF));

That does not get you the size of the buffer.

Mark

holmes4:

  1. No there are two versions of write one sending a single byte and one which sends a number of bytes. Look it up!

  2. char and unsigned char are both 8 bits so no need to do all that converting.

  3. you can put more than one call to write between the beginpacket and the endpacket so no need to create a single array.

    Udp.beginPacket("192.168.1.26", 9000);

Add code here to send the two byte header you want.
   Udp.write(rxBuf,number of bytes);
   Udp.endPacket();




Mark

Mark! Thanks a lot :slight_smile: It is working. It is not that I did not had a look at the udp.write() page, I just misinterpreted it. Here is my final simple solution to the problem:

    Udp.beginPacket("192.168.1.134", 9000);
    Udp.write(rxId >> 8);
    Udp.write(rxId & 0xFF);
    Udp.write(rxBuf,rxLen);
    Udp.endPacket();