Weirdness with an array of hex values


#1

So im plannign on controlling an external device via serial that takes hex values. Using a simple bit of test code ive noticed that the array is only ever a size of 4 and thats all that gets transmitted to the device.
Here is the code…

#define TIMEOUT 2000
unsigned long timer;

const char cmdTosend[] = {0xAA,0x11,0x01,0x01,0x01,0x14};

void setup()
{
      Serial.begin(9600);
      Serial1.begin(9600);
}

void loop()
{
    sendHex(cmdTosend);
    timer = millis();
    while (!Serial.available() && millis() <= timer + TIMEOUT) SPARK_WLAN_Loop();
    
}

void sendHex(const char *cmd)
{
    Serial.write("Size of array is " + String(sizeof(cmd)));
     for(int i = 0; i <sizeof(cmd); i++)
     {
     Serial1.write(cmd[i]);
     
     }

}

Not sure what im doing wrong. Any advice much appreciated


#2

@HughB Welcome to Particle Community.

Suggestion is that:

SYSTEM_THREAD(ENABLED);

is used then you don’t have to worry about calling SPARK_WLAN_Loop() - which in any case should be Particle.process();

In setup() I would place the while(!Serial.available()) delay(10); This will then loop there until you connect the Serial terminal and press a key.

In loop() I assume you trying to send your cmdTosend every 2 seconds, in which case I would call it like this

if (millis() - timer >= TIMEOUT) {
timer = millis();
sendHex(cmdTosend);
}

In sendHex()

I would use Serial.printlnf("Size of array is %d", sizeof(cmd)); instead of Serial.write();
Better if you get the sizeof char array once - int sizeOfCmd = sizeof(cmd);
Then

Serial.printlnf("Size of array is %d", sizeOfCmd);`
Serial.write(cmd, sizeOfCmd);

If you want to check it has been sent then int bytesCmdSent = Serial.write(cmd, sizeOfCmd);
And Serial.printlnf("Size of array sent is %d", bytesCmdSent);


#3

Thanks @armor ive made the changes and changed the array to a byte array, however it still only returns a value of 4 for the length of the array.
image
If i change the array to {0xAA,0x11,0x01} it returns the lenght as 4 but actually sends 0xAA 0x11 0x01 0x53 (as recieved by a PC)
Even if i set the array to 1 (0xAA) it still shows as 4 but sends 0xAA 0x53 0x69 0x7A
Very confusing…
Here is the updated code. I am a bit of a novice but learning fast :wink:

#define TIMEOUT 2000
unsigned long timer;
SYSTEM_THREAD(ENABLED);

const byte cmdTosend[] = {0xAA}; //,0x01,0x01,0x14};

void setup()
{
     while (!Serial.available()) delay(10);
      Serial.begin(9600);
      Serial1.begin(9600);
}

void loop()
{
    if (millis () - timer >= TIMEOUT){
        timer = millis();
        sendHex(cmdTosend);
    }
    
}

void sendHex(const byte *cmd)
{
    int sizeOfCmd = sizeof(cmd);
    Serial.printlnf("Size of array is %d", sizeOfCmd);
    
    int bytesCmdSent = Serial1.write(cmd, sizeOfCmd);
    Serial.printlnf("size of array sent %d", bytesCmdSent);

}

#4

It is perfecly normal that a pointer - and cmd is nothing else than a mere pointer - will give you a size of four bytes.
const byte *cmd is not the same thing as your cmdTosend array.

That is common C behaviour and also the reason why standard C functions that take an array pointer also demand the size of the array to be passed.
Passing a pointer is only passing the address but no meta data about the “thing” it points to.


#5

I think you should change sendHex to also take in the length of the array, since calling sizeof on a pointer to byte will return the size of the pointer (4 bytes), and not the length of the byte array.

void sendHex(const byte *cmd, unsigned int length)

Since you’re not passing the length of the array, any data printed after 0xAA is garbage, since you specified Serial1.write to print 4 bytes.


#6

Ah of course! that makes perfect sense. I was confusing size with length. So in the past using C# there is a method to get an array length by using myarray.length() for example. The equivilent in C++ seems to be int arrayLen = sizeof(myarray) / sizeof(myarray[0]);
So I tried it out and bingo I can now get the size of the array of hex values i want to send and it sends correctly.

Many thanks for the pointers (sorry about the pun) guys. I really apprecite it.
Here is my working test sample if anyone is interested.

#define TIMEOUT 2000
unsigned long timer;

SYSTEM_THREAD(ENABLED);

const byte cmdTosend[] = {0xAA,0x01,0x01,0x14,0x12,0xA1};

void setup()
{
     while (!Serial.available()) delay(10);
      Serial.begin(9600);
      Serial1.begin(9600);
}

void loop()
{
    if (millis () - timer >= TIMEOUT){
        timer = millis();
        // get the number of items in the array
        int len = sizeof(cmdTosend) / sizeof(cmdTosend[0]);
        
        // send it 
        sendHex(cmdTosend, len);
    }
}

void sendHex(const byte *cmd, unsigned int length)
{
    //show the length of the array thats been passed in
    Serial.printlnf("Size of array is %d", length);
    
    // send to the device.
    int bytesCmdSent =  Serial1.write(cmd, length);
    Serial.printlnf("size of array sent %d", bytesCmdSent);
}