I have an 8 bit int called dimmerlevel which is defined thus;
dimmerlevel = 128 + rotaryvalue;
... where rotaryvalue is always less than or equal to 128.
I want to convert this 8 bit decimal into two 4 bit nibbles also expressed as decimals because I need to pass them to a function in that form. The function takes an array like this: byte lightsoff[] = {0,1,2,0,15,2,12,9,7,10}; and I want to insert my decimal versions of the two hex nibbles into the first two array values of the above.
So far I have converted it to a string as hex like so;
String dimmerstring = String(dimmerlevel, HEX);
For example let's say the rotary value is 140, then the string that gives would be "8c". I'd like to therefore get "8" converted into a decimal (i.e. 8 ) and insert it into the first value of the array mentioned above. Likewise I'd like to get "c" converted into the number 12 and insert it into the second value of the array.
So I thought all I need to do is select each character separately by addressing it in the string as an array, and convert it back to decimal. How hard could this be?
This post seemed helpful, but when I tried that in my case I simply had a whole load of different compile errors re types not being matched.
I won't post all the permutations and compile errors here, suffice to say I simply didn't manage to get it to work after a number of hours of head scratching in the area of matching value types; can someone suggest a solution?
I thought sscanf took its first argument as a string,
It does - in C, a string is a char array, with a null terminator, so char string [10] = "123";
is effectively the same as char string [10] = {0x31, 0x32, 0x33, 0, 0, 0, 0, 0, 0, 0};
A String is a class, and in my opinion, should be avoided.
Given that you said that the 8-bit int named rotaryvalue may be equal to or less than 128
dimmerlevel = 128 + rotaryvalue;
what happens when rotaryvalue is 128? This is a bug waiting in the weeds to bite you in the butt down the road.
Also, while scanf() (and its friends) makes life easy, it is often an H-bomb-to-kill-an-ant approach. If memory's not an issue, it's great. However, if you're banging up against a memory limit, writing a simple function to do the conversion you're looking for might be an alternative approach.
@econjack Aye, I did notice that hence my actual code which is; dimmerlevel = 128 + ((newPosition-1) / 4);
Re memory, I hear your point. Memory currently isn't an issue. Either way though I still can't get it to work Will post back here again after trying some more things.
void setup() {
int val = 140;
char buffer[20];
Serial.begin(115200);
decimalToHex(val, buffer);
Serial.print("decimal 140 in hex is: ");
Serial.println(buffer);
Serial.print("First hex digit value: ");
Serial.print(hexToDecimal(buffer[0]));
Serial.print(" Second hex digit value: ");
Serial.print(hexToDecimal(buffer[1]));
}
void loop() {
}
/*****
Function that converts decimal value to a hex string
Argument list:
int n; the decimal value to convert
char hex[] the buffer to hold the conversion
Return value:
void
Caution: This function assumes the buffer is large enough to hold
the output.
*****/
void decimalToHex(int n, char hex[])
{
int i = 0, rem;
while (n > 0)
{
rem = n % 16;
switch (rem)
{
case 10:
hex[i] = 'A';
break;
case 11:
hex[i] = 'B';
break;
case 12:
hex[i] = 'C';
break;
case 13:
hex[i] = 'D';
break;
case 14:
hex[i] = 'E';
break;
case 15:
hex[i] = 'F';
break;
default:
hex[i] = rem + '0';
break;
}
++i;
n /= 16;
}
hex[i] = '\0';
strrev(hex); /* Reverse string */
}
/*****
Function that converts hex digit to a decimal value
Argument list:
char hex the hex digit to convert
Return value:
int
*****/
int hexToDecimal(char hex) /* Function to convert hexadecimal to decimal. */
{
hex = toupper(hex);
int temp = hex - '0';
if (temp < 10)
return temp;
else
return hex - 'A' + 10;
}
@Robin2 I wanted to take the 8 bit decimal 220 and express it as hex (0xDC) then take each of those hex numbers (which on their own bear no relation to the original number, but that's the whole point - they are forming part of a message) and convert each hex number back into decimal, giving two integers 13 and 14.
@econjack & AWOL Thanks for the suggestions, I ended up iterating through the cases like that using a switch statement. I had thought this was a horribly inefficient way of going about things, but as econjack points out I suppose using a string function like sscanf is far sillier from a memory point of view.
hazymat: @Robin2 I wanted to take the 8 bit decimal 220 and express it as hex (0xDC) then take each of those hex numbers (which on their own bear no relation to the original number, but that's the whole point - they are forming part of a message) and convert each hex number back into decimal, giving two integers 13 and 14.
That's exactly what my example does and @jimLee has provded the code to achieve it.
Actually, the first part of @jimLee's code could be simplified to
byte nibbleHi(byte inVal) {
return inVal >> 4; // shift over the bits..
}