Tonyboy
October 11, 2019, 10:53am
1
Dear members!
I want to convert a large number (int) to 4 bytes. I have a code which works for 2 bytes as an example the number DEC 12345 , HEX 3039 uses 2 bytes BIN 0011 0000 0011 1001 . The output on "Serial.print" is:
bytes_array[0] = 39
bytes_array[1] = 30
bytes_array[2] = 0
bytes_array[3] = 0
bytes_array[4] = CE
When I tried with this number DEC 123456 , HEX 1 E240 which uses 2.5 bytes the output were:
bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF
bytes_array[4] = CE
Is there someone who can help me to fix that?
Thanks in advance!
Here is the code so far:
void int2Bytes(uint32_t val, uint8_t* bytes_array){
int my_int = 12345;
// Create union of shared memory space
union {
uint32_t unit_variable;
uint8_t temp_array[4];
} u;
// Overite bytes of union with in variable
u.unit_variable = val;
// Assign bytes to input array
memcpy(bytes_array, u.temp_array, 4);
Serial.print("bytes_array[0] = ");
Serial.println(bytes_array[0],HEX);
Serial.print("bytes_array[1] = ");
Serial.println(bytes_array[1],HEX);
Serial.print("bytes_array[2] = ");
Serial.println(bytes_array[2],HEX);
Serial.print("bytes_array[3] = ");
Serial.println(bytes_array[3],HEX);
Serial.print("bytes_array[4] = ");
Serial.println(bytes_array[4],HEX);
}
12345 != 123456
And 123456 doesn't fit in a sixteen bit int.
Tonyboy
October 11, 2019, 11:33am
3
Hi,
For testing, I am changing the number manually. Yes, that number will not feet on 16 bits (see attached file) Therefore I need 4 bytes for being able to convert bigger numbers than 123456. But the code works for 12345 which uses 2 bytes.
BR
PieterP
October 11, 2019, 11:49am
4
The union you're using is completely unnecessary, and even worse, it actually makes your program invalid. Using unions for type punning is not allowed in C++ .
The reason it's not working, is because you are saving 123456 as an int, which is only 16 bits wide on most basic Arduinos. 123456 does not fit an int, because log2 (123456) = 16.9 > (16 - 1).
123456 overflows to a negative number, so when you later convert it to a 32-bit integer, it is sign extended, and the two most significant bytes are all ones (0xFFFF).
Finally, you're accessing beyond the bounds of your array. bytes_array[4] is not an element of the array if the array is of size 4.
You can add the number of elements to the signature of the function so the compiler can give an error if you try to use an array of the incorrect size.
[color=#00979c]void[/color] [color=#000000]int2Bytes[/color][color=#000000]([/color][color=#00979c]uint32_t[/color] [color=#000000]val[/color][color=#434f54],[/color] [color=#00979c]uint8_t[/color] [color=#000000]([/color][color=#434f54]&[/color][color=#000000]bytes_array[/color][color=#000000])[/color][color=#000000][[/color][color=#000000]4[/color][color=#000000]][/color][color=#000000])[/color] [color=#000000]{[/color]
[color=#d35400]memcpy[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#434f54],[/color] [color=#434f54]&[/color][color=#000000]val[/color][color=#434f54],[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]val[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
[color=#00979c]static_assert[/color][color=#000000]([/color][color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]val[/color][color=#000000])[/color] [color=#434f54]==[/color] [color=#000000]4[/color][color=#434f54],[/color] [color=#005c5f]"Error: uint32_t expected to be 4 bytes"[/color][color=#000000])[/color][color=#000000];[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[0] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]0[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[1] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]1[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[2] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]2[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[3] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]3[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]
[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
[color=#5e6d03]while[/color] [color=#000000]([/color][color=#434f54]![/color][b][color=#d35400]Serial[/color][/b][color=#000000])[/color][color=#000000];[/color]
[color=#00979c]uint8_t[/color] [color=#000000]bytes[/color][color=#000000][[/color][color=#000000]4[/color][color=#000000]][/color][color=#000000];[/color]
[color=#000000]int2Bytes[/color][color=#000000]([/color][color=#000000]12345[/color][color=#434f54],[/color] [color=#000000]bytes[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]int2Bytes[/color][color=#000000]([/color][color=#000000]123456[/color][color=#434f54],[/color] [color=#000000]bytes[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]
[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color][color=#000000]}[/color]
Pieter
JCA34F
October 11, 2019, 12:01pm
5
Your binary displays does not show leading zeros, try it with a large negative number like -1564384201.
Hi,
I tried the code above and the output was :
bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF
and should be:
bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = 01
bytes_array[3] = 00
Hi,
Yes, but when I am using int2Bytes(my_int, bytes); instead int2Bytes(123456, bytes); like:
uint8_t bytes[4];
int my_int = 123456;
int2Bytes(my_int, bytes);
the output is:
bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF
That is because I will have an integer which will be converted to bytes to be able to build CAN message.
This function works perfectly for integers which use 2 bytes:
void CAN_Write() {
MCP2515 mcp2515(CS_CAN_PIN);
SPI.begin();//----------Start CAN------------------------
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
struct can_frame frame1;//Message nr1
frame1.can_id = 0x100;
frame1.can_dlc = 4;
frame1.data[0] = 0x00;
int my_int = 123456;
int2Bytes(my_int,&frame1.data[0]);
mcp2515.sendMessage(&frame1);
digitalWrite(CS_CAN_PIN, HIGH);
SPI.end();
}
Tonyboy:
uint8_t bytes[4];
int my_int = 123456;
int2Bytes(my_int, bytes);
PieterP:
The reason it's not working, is because you are saving 123456 as an int, which is only 16 bits wide on most basic Arduinos. 123456 does not fit an int, because log2(123456) = 16.9 > (16 - 1).
123456 overflows to a negative number, so when you later convert it to a 32-bit integer, it is sign extended, and the two most significant bytes are all ones (0xFFFF).
int my_int = 123456;
123456 doesn't fit into 16 bits.
This has already been pointed-out.
Tonyboy
October 11, 2019, 2:14pm
11
Yes, therefore I want to fix that to be able to send 4 bytes or 32 bits threw CAN as 1 message
Tonyboy:
Yes, therefore I want to fix that to be able to send 4 bytes or 32 bits threw CAN as 1 message
So, don't use a sixteen bit int.
Tonyboy
October 11, 2019, 4:06pm
13
Thank you all for your time!
BR Anton
Tonyboy
October 13, 2019, 5:00pm
14
Hello,
I tried with long instead of int and it worked perfectly
Thanks!
BR
PieterP
October 13, 2019, 5:20pm
15
The correct type to use for 4 bytes is not long, but uint32_t , as demonstrated by the code I posted earlier.