How to `Serial.print()` "full" hexadecimal bytes? - arduino

I am programming Arduino and I am trying to Serial.print() bytes in hexadecimal format "the my way" (keep reading for more information).
That is, by using the following code
byte byte1 = 0xA2;
byte byte2 = 0x05;
byte byte3 = 0x00;
Serial.println(byte1, HEX);
Serial.println(byte2, HEX);
Serial.println(byte3, HEX);
I get the following output in the Serial Monitor:
A2
5
0
However I would like to output the following:
A2
05
00
In words, I would like to print the "full" hexadecimal value including 0s (05 instead of 0 and 00 instead of 0).
How can I make that?

Simple brute force method, is to write a routine as:
void p(char X) {
if (X < 16) {Serial.print("0");}
Serial.println(X, HEX);
}
And in the main code:
p(byte1); // etc.

sorry - not enough reputation to comment but found previous answer is not fully correct. Actually, the nice light way to code it should be :
void p(byte X) {
if (X < 10) {Serial.print("0");}
...
giving the code:
void p(byte X) {
if (X < 10) {Serial.print("0");}
Serial.println(X, HEX);
}
And in the main code:
p(byte1); // etc.
hope this helps

Use sprintf to print into a buffer (two chars per byte + null terminator):
byte byte1 = 0xA2;
byte byte2 = 0x05;
byte byte3 = 0x00;
char s[7];
sprintf(s, "%02x\n%02x\n%02x", byte1, byte2, byte3);
Serial.println(s);
Added new lines in between to get each on new line. About '%02x', the % means here comes formatting information, 0 means to pad with 0, 2 means pad input until 2 characters wide and x means give me this as hexadecimal.
For other formatting options see http://linux.die.net/man/3/sprintf

The lowest footprint in Memory, Code and runtime would be classic bit playing
byte b;
Serial.print(b>>4, HEX);
Serial.print(b&0x0F,HEX);
Which is working fine on any 8bit type. For any other mask also the first line to
Serial.print((b>>4)&0x0F, HEX);

Try this:
//Converts the upper nibble of a binary value to a hexadecimal ASCII byte.
//For example, btohexa_high(0xAE) will return 'A'.
unsigned char btohexa_high(unsigned char b)
{
b >>= 4;
return (b>0x9u) ? b+'A'-10:b+'0';
}
//Converts the lower nibble of a binary value to a hexadecimal ASCII byte.
// For example, btohexa_low(0xAE) will return 'E'.
unsigned char btohexa_low(unsigned char b)
{
b &= 0x0F;
return (b>9u) ? b+'A'-10:b+'0';
}
And in main code:
comand_mod=0xA1; //example variable
Serial.print(btohexa_high(comand_mod));
Serial.print(btohexa_low(comand_mod));

wow! 7 years ago and I felt here, my answer might be useful for you (hopefully not anymore) or others looking for the answers like me.
Use "Serial.write()" to send a hex byte over serial.
All Serial.print() eg. println, printf, sprint, print will "print" your value in ASCII.

Related

Parsing char array to integer, atoi() returns squares

I'm using an android app to send values to control servos.
Code:
char inputData[4];
char buffer[3];
void loop()
{
if(Serial.available() > 3) {
for (int i = 0; i < 4; i++){
inputData[i] = Serial.read();
}
char buffer[4];
buffer[0] = inputData[1];
buffer[1] = inputData[2];
buffer[2] = inputData[3];
buffer[3] = '\0';
int angle = atoi(buffer);
Serial.write(angle);
}
}
Issue: I'm getting the values + A-F letters to address each servo - A10, A180, B30 etc. Now the trouble is turning this to an actual integer. As you can see I've declared a character array to store the integers in and as suggested in a post on the arduino forum, I added a \0 at the end of the array. Currently, the Atoi returns random characters, mostly squares and some random numbers. I've tried even assigning them to a string and then .toInt() but same issue there, mostly squares.
Any ideas?
Thanks!
Use print or println to see the number as text. write sends it as byte and Serial Monitor shows a symbol with that ASCII code.

Raspi I2C communication with Arduino issues with wiringPi

I'm experiencing unexpected results using wiringPi's wiringPiI2CWriteReg16() function, and I'm not sure if it's due to incorrect usage, or something else. This is the declaration for the function:
extern int wiringPiI2CWriteReg16 (int fd, int reg, int data);
There are notes within the wiringPiI2C.c file that state it resembles Linux's SMBus code, if that helps.
On my Arduino (both an Uno R3 and a Trinket Pro), I am running this pared-down sketch:
#include <Wire.h>
#define SLAVE_ADDR 0x04
void receive_data (int num_bytes){
Serial.print("bytes in: ");
Serial.println(num_bytes);
while(Wire.available()){
int data = Wire.read(); // tried char, uint8_t etc
Serial.println(data);
}
Serial.print("\n");
}
void setup() {
Serial.begin(9600);
Wire.begin(SLAVE_ADDR);
Wire.onReceive(receive_data);
}
void loop() {
delay(500);
}
I would think that Wire.read() would break things apart at the byte boundary, but that's not occurring in my case. Perhaps this is my issue... a misunderstanding.
Nonetheless, I have this C code (requires wiringPi v2.36+ to be installed):
// word.c
#include <wiringPiI2C.h>
void main (){
int fd = wiringPiI2CSetup(0x04);
wiringPiI2CWriteReg16(fd, 0x00, 255);
wiringPiI2CWriteReg16(fd, 0x01, 256);
}
Compiled like this:
gcc -o word word.c -lwiringPi
When run, ./word, I receive the following on my Arduino's serial output:
bytes in: 3
0
255
0
bytes in: 3
1
0
1
In the first call to wiringPiI2CWriteReg16(), I expect the first byte in the output to be zero (0x00) as that's the register address I'm requesting. The second byte (255) is also correct. The third byte (0) is meaningless from what I can tell (as I'm only sending in one byte as data).
However, in the second call to that function, I do get the correct output for the register (first byte as 0x01 == 1), but the second byte is zero, and the third byte has what appears to be the correct remainder (255 == one byte, + 1). The problem is, is that the second byte is 0.
The exact same effect happens if I pass in 511 or for that matter, any number as the data in the call.
My question is whether I'm missing something glaringly obvious (I'm relatively new to C and Arduino), and/or if I can get some pointers on how to troubleshoot this more thoroughly.
I found that the problem was in my Arduino code. In the official Raspi forums, Gordon tipped me off that the bytes are read in separately, LSB first. Throughout all of my searching, I hadn't come across that, and really didn't quite understand what was happening. After changing my I2C read loop code in my Arduino sketch to this:
while(Wire.available()){
Wire.read(); // throw away register byte
int16_t data = Wire.read(); // LSB
data += Wire.read() << 8; // MSB
Serial.print("data: ");
Serial.println(data);
}
...everything works. In effect, that's at least one way to read two-byte values over I2C on the Arduino and put the bytes back together.

Serial Communication Between Arduino and EPOS: CRC Calculation Problems

I am trying to interface with an EPOS2 motor controller over RS232 Serial with an Arduino Duemilanove (because it's what I had lying around). I got it to work for the most part - I can send and recieve data when I manually calculate the CRC checksum - but I'm trying to dynamically control the velocity of the motor which requires changing data, and therefore, changing checksum. The documentation for calculating the checksum is here, on page 24:
http://www.maxonmotorusa.com/medias/sys_master/8806425067550/EPOS2-Communication-Guide-En.pdf
I copied the code directly out of this documentation, and integrated it into my code, and it does not calculate the checksum correctly. Below is a shortened version of my full sketch (tested, yielding 0x527C). The weirdest part is that it calculates a different value in my full sketch than in the one below, but both are wrong. Is there something obvious that I'm missing?
byte comms[6] = { 0x10, 0x01, 0x03, 0x20, 0x01, 0x02 }; // CRC should be 0xA888
void setup() {
Serial.begin(115200);
}
void loop() {
calcCRC(comms, 6, true);
while(1);
}
word calcCRC(byte *comms, int commsSize, boolean talkative) {
int warraySize = commsSize / 2 + commsSize % 2;
word warray[warraySize];
warray[0] = comms[0] << 8 | comms[1];
Serial.println(warray[0], HEX);
for (int i = 1; i <= warraySize - 1; i++) {
warray[i] = comms[i * 2 + 1] << 8 | comms[i * 2];
Serial.println(warray[i], HEX);
}
word* warrayP = warray;
word shifter, c;
word carry;
word CRC = 0;
//Calculate pDataArray Word by Word
while (commsSize--)
{
shifter = 0x8000;
c = *warrayP ++;
do {
carry = CRC & 0x8000;
CRC <<= 1;
if (c & shifter) CRC++;
if (carry) CRC ^= 0x1021;
shifter >>= 1;
} while (shifter);
}
if (talkative) {
Serial.print("the CRC for this data is ");
Serial.println(CRC, HEX);
}
return CRC;
}
I used the link below to calculate the checksum that works for this data:
https://www.ghsi.de/CRC/index.php?Polynom=10001000000100001&Message=1001+2003+0201
Thanks so much!!
Where to begin.
First off, you are using commsSize-- for your loop, which will go through six times when you have only three words in the warray. So you are doing an out-of-bounds access of warray, and will necessarily get a random result (or crash).
Second, the build of your first word is backwards from your other builds. Your online CRC suffers the same problem, so you apparently don't even have a reliable test case.
Third (not an issue for the test case), if you have an odd number of bytes of input, you are doing an out-of-bounds access of comms to fill out the last word. And you are running the CRC bits too many times, unless the specification directs some sort of padding in that case. (Your documentation link is broken so I can't see what's supposed to happen.) Even then, you are using random data for the padding instead of zeros.
The whole word conversion thing is a waste of time anyway. You can just do it a byte at a time, given the proper ordering of the bytes. That also avoids the odd-number-of-bytes problem. This will produce the 0xa888 from the input you gave the online CRC calculator (which are your bytes in a messed up order, but exactly as you gave them to the calculator):
unsigned char dat[6] = { 0x10, 0x01, 0x20, 0x03, 0x02, 0x01 };
unsigned crc1021(unsigned char *dat, int len) {
unsigned crc = 0;
while (len) {
crc ^= *dat++ << 8;
for (int k = 0; k < 8; k++)
crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;
len--;
}
return crc & 0xffff;
}

Bitshifting QBytearray?

I'm looking for a way to sbitshift a QByteArray.
QByteArray statusByte = QByteArray::fromHex("40"); // 0100 0000
What i need to achieve is to get statusByte to 0x20 by bit shifting. Since I can't directly bit shift the QByteArray, what is the simplest method for achieving the shift?
You don't really need a byte array if you only want to get a single numeric (byte) value from a hexadecimal representation of one byte, not multiple bytes.
#if 1
// Qt 5, C++11 compilers
quint8 byte = QStringLiteral("40").toInt(nullptr, 16);
#endif
#if 0
// Qt 5, pre-C++11 compilers
quint8 byte = QStringLiteral("40").toInt(NULL, 16);
#endif
#if 0
// Qt 4
quint8 byte = QByteArray("40").toInt(NULL, 16);
#endif
byte >>= 1;
Q_ASSERT(byte == 0x20); // this is for demonstration only
If you need to bit-shift multiple bytes at once, of course it's also possible - please amend your question to make that clear.
Bit shifting is not a problem when you are talking about single byte, this is trivial (I don't know why you claim it is impossible).
QByteArray statusByte = QByteArray::fromHex("40");
statusByte[0] = statusByte[0]>>1;
statusByte[0]>>=1; // this should also work
if you have multiple bytes then it is more complicated!
endian! How do you define shift where the oldest bit should go, to next byte or to previos byte?
what should happen when array ends? loose data, or extend array?

Receive message that is read read in hexadecimal

I'm programming with arduino 1.0.5 in lunix/windows
With this piece of code:
void readSerialString () {
char buffer[8];
if(Serial.available()) {
while (Serial.available()){
sb = Serial.read();
buffer[indexB] = sb;
indexB++;
}
}
Serial.println(buffer);
}
I'm trying to send (by serial terminal) a message that can be seen in hexadecimal.
For exemple if I write: "\xaa\x22\xa1"
It will not read as hexadecimal, will it?
How can I let the program read the string in input as hexadecimal?
No your mistaking the data and it s format.
do you have access to printf ? If so use printf("%x",char) to see a char as hexadecimal.
Arduino solution
Serial.print(78, HEX) gives "4E"
see http://arduino.cc/en/Serial/Print
[edit]
I need the contrary of print. I need that the string that has been token from the serial terminal is interpreted as hex.
To do this use read(), but you will have to implement the convertion function from ascii HEX to data, as an HEX data for a byte hols on 2 chars, my function take two chars as input)
char hex_ascii_to_databyte(char c1, char c2){
char res=0;
if(c1>=48 && c1<=57) res = c1-48;
else if(c1>=65&& c1<=70) res = c1 - 65 + 0xa;
else if(c1>=97&& c1<=102) res = c1 - 97 + 0xa;
else{//error
}
//idem c2 in res2
res=res<<4;
res+=res2;
return res;
}
for each hex read, call twice read (to read the 2 ascii chars) then call this func

Resources