Go Down

Topic: Conversion from int/hex to char (Read 45704 times) previous topic - next topic

multivir

Hi,

I'm building a midi controller with Arduino. In order to send messages I use commands like Serial.print(char(0x01));
As you can see, although the message itself is a hex value, it has to be sent in the char format.
With toggle switches that only know two states it was easy to do (only 0x01 or 0x7F - two values), but I haven't figured out how I can convert an analog value that I've read into a int variable with a potentiometer (127 different values possible).

I can do "Serial.print(hex(pot_value))", but it won't give me the result I need as it's in the wrong format.
I also tried "Serial.print(char(hex(pot_value)))" which didn't work either.
How do I cast a int value that I have into pure characters, so that I get it to do Serial.print(char(0xPot_hex_value_as_char))?

Thanks,

M.

mrdovey

#1
Apr 28, 2012, 03:19 am Last Edit: Apr 28, 2012, 03:22 am by Morris Dovey Reason: 1
You could use sprintf(), but how about (for values in the range 0x00 - 0xFF):

Code: [Select]
char c2h(char c)
{  return "0123456789ABCDEF"[0x0F & (unsigned char)c];
}

Serial.print(c2h(val>>4));
Serial.print(c2h(val));

Grumpy_Mike

Do not use Serial.print() but Serial.write() the value in the brace will be sent as a character no matter what format it is in.

multivir

Hi Mike,

I tried your suggestion, but it doesn't seem to do what I'm expecting.
I get an "invalid conversion from 'int' to 'const uint8_t*'".

Here's the simplified test code I ran:

Code: [Select]


int decimalValue = 25;

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

void loop(){
  Serial.println("S_Print");
  Serial.print(decimalValue,HEX);
  Serial.println("S_Write");
  Serial.write(decimalValue,HEX);
}


For now I assume that I need int if I want to read out a potentiometer value with an analog in.

Thanks,

M.

I'll see if Morris' suggestion will work, but for now I haven't really got it yet.

SurferTim

Quote
I tried your suggestion, but it doesn't seem to do what I'm expecting.

What are you expecting? Do you want to print the integer variable? Or just use the lower 8 bits of the integer?

Code: [Select]
Serial.write(lowByte(decimalValue));


multivir

I expect a char that contains the hex value from my potentiometer, mapped to a range from 0 to 127
(the mapping is not an issue).

--> 0x00 to 0x7F in char format, so that the numbers and the "x" are characters

SurferTim

The character will never contain a hex value. Decimal, hex, and octal are only skinware representations of binary values. If you want to display the binary value of the lower byte in hex format:
Code: [Select]
Serial.println(lowByte(decimalValue),HEX);


Skinware = "ugly bags of mostly water" = human

multivir

I agree with you on the skin ware thing you said. I tried the low byte, but it doesn't do what I need.

The MIDI message I try to compose consists of three parts.

Here's how I write the first two parts:

Code: [Select]
Serial.print(char(0xB0));
Serial.print(char(0x01));


If I had a switch that would just switch between the max/min value, I'd just send another Serial.print(char(...)) with the corresponding value. (I have switches on my midi controller as well, and they're working fine with this method)

Now since I'm using a potentiometer, I have to take the value that I get from there, use "map" to get a value between 0 and 127 and write this value in hex. (0x00 - 0x7F)

That sounds pretty simple. The point where I'm struggling is that if I use Serial.print(midiValue,HEX) the value is written as HEX, not as a char containing the HEX value as plain text (yes, I do realize that in the end it's all zero's & one's). So when I look at the serial monitor on my computer, I can see that the working Serial.print(char(...)) messages just get me a "°" where the print of the hex will return a value (00-7F).
I do need that value, but in the same format as the other stuff.

I hope that explains it a bit better.

SurferTim

It's the skinware thing has you again. It also applies to input.

Code: [Select]
int decimalValue = 255;
int hexValue = 0xFF;

These both store 11111111 binary in the variables.

So this would evaluate to true, even tho you entered it as 0xFF
Code: [Select]
if(hexValue == 255)

If you need to send just the value, and not the representation, then send it.

Code: [Select]
Serial.write(lowByte(decimalValue));


Serial.write does no skinware conversion. It will send it as-is.

multivir

Ok. Got it.  8)

I'm learning a lot right now... Thanks a lot.

I tried it with lowByte, but my MIDI Monitor application that I use to debug the MIDI messages I'm sending shows me all kinds of weird information. I double checked with a commercial hardware midi controller with the same potentiometer and I'm getting correct data.

I also get correct values in my Arduino test program / serial console.
So I assume that I'm still not sending them in the correct format.

You explained that hexValue 0xFF and decimalValue 255 both have the same binary value 11111111.
But what's stored if I do 'char charValue = "0xFF" ' ?

I would assume that the binary string behind the char field is much longer. And that's what I'm sending out to my MIDI device. It works for the switches, so I assume that it will also work for the potentiometer.

So if I'm not completely on the wrong path - there's another cast / conversion that has to be done.
I just don't know how.

Thanks for your help,

M.

SurferTim

Quote
But what's stored if I do 'char charValue = "0xFF" ' ?

== 11111111 binary.
== 0xFF hex
== 255 unsigned
== -1 signed

All are stored as 11111111.

mrdovey

Quote
But what's stored if I do 'char charValue = "0xFF" ' ?


That should produce an error because you declared charValue to be a single char and "0xFF" is four characters plus a NUL terminator.

If you want charValue to be initialized to all-bits-on, you'll need to code
Code: [Select]
char charValue = 0xFF;
without the quotes. If you do that, your result will be as SurferTim describes.

AWOL

Quote
If you want charValue to be initialized to all-bits-on, you'll need to code
Code: [Select]
char charValue = ~0;

mrdovey

AWOL contributed
Code: [Select]
char charValue = ~0;

Yuppers, there are a lot of expressions that evaluate to all-bits-on.   :smiley-mr-green:

multivir

Hello everybody,

I have to admit that I don't understand it yet. In order to test what Tim said, I came up with this little test:
Code: [Select]

int hexValue = 0xB1;

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

void loop(){
  Serial.print(char(0xB0));
  delay(1000);
  Serial.print(lowByte(hexValue));
  delay(1000);
}


If I understood Tim correctly, then you should be able to put this program on your Arduino, run it and the serial console would be showing "°" only. Every second a new one...

But it doesn't. It alternates between "°" and "177". The 177 is produced by the lowByte print.
The "correct" way to send data if I want my MIDI device to understand what I'm doing produces the "°".
How do I get serial print to send the value in the correct format?

Go Up