Go Down

Topic: translating strings to hex/dec/bin (Read 28205 times) previous topic - next topic

jabstarr

hello,

i trying to read and decode a string sent from processing.
the string looks like this: XFF100000
it is 8 hex values to describe the individual settings of 8 LEDs (with 16 step grey scale). the first X is for string recognition.

i'm trying to read the 8 bytes and encode it properly to a maxim 7219 LED driver. for starters, i'm only doing simple on/off control of the LEDs (so, if value>8 then LED is ON else OFF)

i've assembled an array of 1s and 0s which i would like to feed to the max7219 chip, but i can't figure out how to translate string/array to one 2 digit hex number (or a decimal number between 0 and 255)

i have defined an array called serInString[]: int serInString[8];

but what i'd really like, is to just define a string and add to it like in processing. and then convert the string to hex with a simple hex(string) command? i'm confused as to how much of processings syntax can be used in arduino. and the link to float and string seems to be broken in the reference?!

anyways, here is my feeble code attempts as of so far:

Code: [Select]
 // read the serial port
 int val = Serial.read();

 // if the input is '-1' then there is no data
 // at the input, otherwise check out if it is 'X'
 if (val != -1) {
   if (val == 'X') {
     digitalWrite(ledPin, HIGH);
     for (int y=0; y<8; y++) {
       int rowval=0;
       for (int x=0; x<8; x++) {
         val = Serial.read();
         if (val > 8) {
           serInString[x] = 1;
         }
         else
         {
           serInString[x] = 0;
         }
       }
       max7219_put(max7219_row0, byte(serInString[]));
       delay(100);
     }
     digitalWrite(ledPin, LOW);
   }

kg4wsv

Quote
 val = Serial.read();
         if (val > 8)

Here's one problem.

You are reading characters that are the ASCII representation of numbers, not the actual (binary) numbers themselves; i.e. you're reading '8' which is an entirely different animal than the integer 8 in decimal, or base ten (frequently written as 810).  Note the quotes make it a character 8 with an ASCII value of 56, not the value of 810 you're looking for.  The way your code is written val will always be greater than 810.

to convert val from ASCII to an integer, do this after Serial.read():

Code: [Select]
val = val - '0';
This subtracts the ASCII value of '0' from the ASCII value of the character you just read, giving you the integer value of the digit it represents.  Note this assumes that val contains an ASCII character between '0' and '9'.  Check for out of range values if appropriate (e.g., you want to check for transmission errors).


Quote
i have defined an array called serInString[]: int serInString[8];


Since you are dealing with characters, char serInString[8] is more appropriate.

Hope this helps.

-j

CosineKitty

See also this thread, for the dangers of calling Serial.read() without checking for -1 (no character ready):

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1168202119

I am also a little confused here because you give "XFF100000" as a sample string, which appears to be "X" followed by 8 hex digits, which is a 32-bit integer.  But you say you are trying to scan this into a value 0..255?  I guess you mean the first 2 hex digits, ignoring the remaining 6?

Here is how I would read 2 hex digits and convert them into a byte value from 0..255:

Code: [Select]

byte WaitAndRead()
{
   while (Serial.available() == 0) {
       // do nothing
   }
   return (byte) Serial.read();
}

int SerialReadHexDigit()
{
   byte c = WaitAndRead();
   if (c >= '0' && c <= '9') {
       return c - '0';
   } else if (c >= 'a' && c <= 'f') {
       return c - 'a' + 10;
   } else if (c >= 'A' && c <= 'F') {
       return c - 'A' + 10;
   } else {
       return -1;   // getting here is bad: it means the character was invalid
   }
}

int SerialReadHexByte()
{
   byte a = SerialReadHexDigit();
   byte b = SerialReadHexDigit();
   if (a<0 || b<0) {
       return -1;  // an invalid hex character was encountered
   } else {
       return (a*16) + b;
   }
}

jabstarr

thank you! i will give this a shot a bit later today.  :)
i can see that this was a bit unclear:
the reason that XFF100000 could become 0..255 is that i'm evaluating every hex character one-by-one to determine if they are more or less than 8, and then assigning them a binary value, adding them in turn to my array/string, forming a binary number of 8 digits (0..255 dec)

CosineKitty

Ahhh... that makes more sense now.  So you could just use my WaitAndRead(), and check the return value against '8' (not 8, but '8', the character in single quotes).  8 == 8, but '8' == 56, as  kg4wsv mentioned.

greatwitenorth

anyone have suggestions on how you would convert a decimal to hex?

Coding Badly

If you want to send a value in hexidecimal out the serial port...
Serial.print( MyValue, HEX );

If you need the value in hexidecimal later in your program...
sprintf( MyBuffer, "%X", MyValue );

Grumpy_Mike

Quote
convert a decimal to hex

It depends on how the decimal is stored. If it is coming in one character at a time, then you accumulate it in a variable:-
in pseudo code:-
acc = 0  // accumulation variable
get character - finish if not a number
convert to a number n
acc = (acc * 10) + n
go:- to get character statement

Remember all integer numbers are stored in computer variables as binary values. We can look at those binary values as hex or decimal depending on the print statement but if we want to manipulate them then they are in binary. Hex is just a short hand way of writing down a binary bit pattern.

Go Up