Hello guys,
Been coding for a while now. I would like to say that i'm becoming better at it. But one thing is keeping me awake for a while now.... I just can't find out what is wrong...
The sprintf() function is not working the way I want. I want to make one string, that is received over a CAN network to print as one long string. But the placement in the string is not correct.
My code snippet:
void loop(){
if(!digitalRead(CAN0_INT)) // If CAN0_INT pin is low, read receive buffer
{
CAN0.readMsgBuf(&rxId, &lenrx, rxBuf); // Read data: len = data length, buf = data byte(s)
if(rxId != 1088 and rxId != 1352 and rxId != 1344 and rxId != 1348){ //ignore CAN messages
for(byte i=lenrx; i<8; i++){
rxBuf[i]=0;
}
sprintf(ReceString, "%.3X %.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2XX", rxId,rxBuf[0],rxBuf[1],rxBuf[2],rxBuf[3],rxBuf[4],rxBuf[5],rxBuf[6],rxBuf[7]);
ReceString[3]=lenrx+'0';
Serial.println(ReceString);
Serial.println(rxBuf[0]);
}
}
}
The output of this code is:
103100A8000000000000X
168
I expect it to be:
1031A800000000000000X
168
That's because the A8 (dec 168) is at the first %.2X in the sprintf() function. But somehow it always end up were rxBuf[1] acutally is. I just don't know why... Probably a user error of me, but I just don't see it... Tried everything.
Anyone an idea? I hope i'm clear...
Regards, Rico
little update:
Shortening to:
sprintf(ReceString, "%.3X %.2XX", rxId,rxBuf[0]);
gives:
103100X
168
Can you make a small sketch for us that we can try ?
The code you showed does not tell if the variables are integers or bytes: http://snippets-r-us.com/.
The %X on a Arduino Uno is for a two-byte unsigned integer that will be showed in hexadecimal format as capitals. The sprintf will read two bytes for every %X.
test code (did the same)
I've added one more %.2X so all 8 (or 9
) bytes are shown.
unsigned char rxBuf[8]={0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22};
long unsigned int rxId = 0x103;
char ReceString[32];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
sprintf(ReceString, "%.3X %.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2XX", rxId,rxBuf[0],rxBuf[1],rxBuf[2],rxBuf[3],rxBuf[4],rxBuf[5],rxBuf[6],rxBuf[7]);
ReceString[3]=7+'0';
Serial.println(ReceString);
Serial.println(rxBuf[0]);
delay(1000);
}
%.2X is the wrong way to specify the number of digits. It should be %2X and if you want the leading zero for numbers less than 0x10, then the format should be %02X.
Pete
You should study how the sprinft works, and perhaps start with a few simple examples.
When you use a 4-byte parameter, you have to specify in the format string that a 4-byte parameter is used. For example with "%03lX". The 'X' is for a 2-byte parameter, the extra 'l' makes it 4-byte.
When you specify in the format that a 2-byte parameter is used, you have to give the sprintf a 2-byte parameter, not a single byte parameter.
This works:
unsigned char rxBuf[8]= { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22 };
unsigned long rxId = 0x103;
char ReceString[32];
void setup()
{
Serial.begin( 9600);
}
void loop()
{
sprintf(ReceString, "%03lX %02X%02X%02X%02X%02X%02X%02X%02XX",
rxId,
(unsigned int) rxBuf[0],
(unsigned int) rxBuf[1],
(unsigned int) rxBuf[2],
(unsigned int) rxBuf[3],
(unsigned int) rxBuf[4],
(unsigned int) rxBuf[5],
(unsigned int) rxBuf[6],
(unsigned int) rxBuf[7]);
ReceString[3]=7+'0';
Serial.println(ReceString);
Serial.println(rxBuf[0]);
delay(1000);
}
You could add the '7' at position 3 in the format string. There is no need to do that afterwards.
Tinkercad:
Thank you both. Works like a charm!
I did not modify the %.2X because it was in an example code. So I thought that it would be ok. Funny thing is I this half a year ago at school. So that makes it extra awkward..
I think that %.2X does the same as %02X, they are both the minimal size with added zeros. However, everyone uses %02X and no one uses %.2X for an integer.