Arduino String to float - string

I'm trying to convert a string of HEX to a single float value. The string is 4 bytes long. It was defined as:
String B = "";
It is a substring of a longer string:
B = input.substring(6,14);
This results in the string I am trying to convert in to a single float value.
Online I found following code:
float y = *(float*)&B;
This compiles without an error, but when I run the code it's always 0.000000. I'm guessing I can't use that function with a string. A typical string can be "bb319ba6" which should be -0.002710083. For that I'm using a IEEE 754 converter I found online.
I basically need to do the same conversion on the Arduino. I hope somebody can help me with that.

You really shouldn't use String on these limited-RAM Arduinos. It can cause weird errors and hangs after random amounts of time (more info here). Just use a character array to hold the characters received from the sensor. Here's some code that will work with either String or a char[]:
uint8_t fromHex( char c )
{
if ((0 <= c) && (c <= '9'))
return (c - '0');
if ('A' <= c) && (c <= 'F'))
return (c - 'A');
if ('a' <= c) && (c <= 'f'))
return (c - 'a');
return 0; // not a hex digit
}
void foo()
{
float y;
uint8_t *yPtr = (uint8_t *) &y; // a pointer the the 4 bytes of `y`
for (uint8_t i=0; i<sizeof(y); i++) {
*yptr = fromHex( B[ 6+2*i ] ) << 4;
*yptr++ = fromHex( B[ 6+2*i + 1] );
}
...
It simply stores the 4 bytes into the float, since Arduino floats already use the IEEE 754 format. No need to decode the exponent, mantissa, etc.

Related

Finding the binary composition of a binary number

Very new to C#, so this could be a silly question.
I am working with alot of UInt64's. These are expressed as hex right? If we look at its binary representation, can we return such an array that if we apply the 'or' operation to, we will arrive back at the original UInt64?
For example, let's say
x = 1011
Then, I am looking for an efficient way to arrive at,
f(x) = {1000, 0010, 0001}
Where these numbers are in hex, rather than binary. Sorry, I am new to hex too.
I have a method already, but it feels inefficient. I first convert to a binary string, and loop over that string to find each '1'. I then add the corresponding binary number to an array.
Any thoughts?
Here is a better example. I have a hexadecimal number x, in the form of,
UInt64 x = 0x00000000000000FF
Where the binary representation of x is
0000000000000000000000000000000000000000000000000000000011111111
I wish to find an array consisting of hexadecimal numbers (UInt64??) such that the or operation applied to all members of that array would result in x again. For example,
f(x) = {0x0000000000000080, // 00000....10000000
0x0000000000000040, // 00000....01000000
0x0000000000000020, // 00000....00100000
0x0000000000000010, // 00000....00010000
0x0000000000000008, // 00000....00001000
0x0000000000000004, // 00000....00000100
0x0000000000000002, // 00000....00000010
0x0000000000000001 // 00000....00000001
}
I think the question comes down to finding an efficient way to find the index of the '1's in the binary expansion...
public static UInt64[] findOccupiedSquares(UInt64 pieces){
UInt64[] toReturn = new UInt64[BitOperations.PopCount(pieces)];
if (BitOperations.PopCount(pieces) == 1){
toReturn[0] = pieces;
}
else{
int i = 0;
int index = 0;
while (pieces != 0){
i += 1;
pieces = pieces >> 1;
if (BitOperations.TrailingZeroCount(pieces) == 0){ // One
int rank = (int)(i / 8);
int file = i - (rank * 8);
toReturn[index] = LUTable.MaskRank[rank] & LUTable.MaskFile[file];
index += 1;
}
}
}
return toReturn;
}
Your question still confuses me as you seem to be mixing the concepts of numbers and number representations. i.e. There is an integer and then there is a hexadecimal representation of that integer.
You can very simply break any integer into its base-2 components.
ulong input = 16094009876; // example input
ulong x = 1;
var bits = new List<ulong>();
do
{
if ((input & x) == x)
{
bits.Add(x);
}
x <<= 1;
} while (x != 0);
bits is now a list of integers which each represent one of the binary 1 bits within the input. This can be verified by adding (or ORing - same thing) all the values. So this expression is true:
bits.Aggregate((a, b) => a | b) == input
If you want hexadecimal representations of those integers in the list, you can simply use ToString():
var hexBits = bits.Select(b => b.ToString("X16"));
If you want the binary representations of the integers, you can use Convert:
var binaryBits = bits.Select(b => Convert.ToString((long)b, 2).PadLeft(64, '0'));

garbage in loop for no reason

i wrote a function that receives a string as a char array and converts it to an int:
int makeNumFromString(char Str[])
{
int num = 0, len = 0;
int p;
len = strlen(Str);
for (p = 0; p<len; p++)
{
num = num * 10 + (Str[p] - 48);
}
return num;
}
the problem is that no matter how long the string i input is, when "p" gets to 10 the value of "num" turns to garbage!!!
i tried debbuging and checking the function outside of the larger code but no success.
what could be the problem and how can i fix it?
THANKS
Perhaps your int can only store 32 bits, so the number cannot be higher than 2,147,483,647.
Try using a type for num with more storage, like long.

Method to convert binary number to decimal

I tried to write a program that converts a binary number to a decimal but am getting a number of errors and I cannot figure out where I am going wrong.
// Takes exponent from the user and calculates 2 ** exponent
int power2(int exponent) {
result = 2 ** exponent
return result
}
// Converts binary number to decimal
int binary2decimal(String binary) {
result = 0
count = 0
for (i = binary.length(); i-- > 0;) {
int d = Integer.parseInt(binary.charAt(i))
if (d == 1) {
result = result + power2(count)
}
count ++
}
return result
}
binary2decimal("101110")
Change
int d = Integer.parseInt(binary.charAt(i))
to
int d = Integer.parseInt("${binary[i]}")
and it will work.
An alternative implementation to yours is:
int binary2decimal2(String binary) {
binary.reverse()
.toList()
.indexed()
.collect { Integer idx, String val -> Integer.parseInt(val) * (2 ** idx)}.sum()
}
Assuming you want the shortest route to a clean solution, use:
Integer.parseInt(String base2num, int radix), where radix = 2.
See http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String,%20int)

Convert binary ( integer and fraction) from VHDL to decimal, negative value in C code

I have a 14-bit data that is fed from FPGA in vhdl, The NIos II processor reads the 14-bit data from FPGA and do some processing tasks, where Nios II system is programmed in C code
The 14-bit data can be positive, zero or negative. In Altera compiler, I can only define the data to be 8,16 or 32. So I define this to be 16 bit data.
First, I need to check if the data is negative, if it is negative, I need to pad the first two MSB to be bit '1' so the system detects it as negative value instead of positive value.
Second, I need to compute the real value of this binary representation into a decimal value of BOTH integer and fraction.
I learned from this link (Correct algorithm to convert binary floating point "1101.11" into decimal (13.75)?) that I could convert a binary (consists of both integer and fraction) to decimal values.
To be specified, I am able to use this code quoted from this link (Correct algorithm to convert binary floating point "1101.11" into decimal (13.75)?) , reproduced as below:
#include <stdio.h>
#include <math.h>
double convert(const char binary[]){
int bi,i;
int len = 0;
int dot = -1;
double result = 0;
for(bi = 0; binary[bi] != '\0'; bi++){
if(binary[bi] == '.'){
dot = bi;
}
len++;
}
if(dot == -1)
dot=len;
for(i = dot; i >= 0 ; i--){
if (binary[i] == '1'){
result += (double) pow(2,(dot-i-1));
}
}
for(i=dot; binary[i] != '\0'; i++){
if (binary[i] == '1'){
result += 1.0/(double) pow(2.0,(double)(i-dot));
}
}
return result;
}
int main()
{
char bin[] = "1101.11";
char bin1[] = "1101";
char bin2[] = "1101.";
char bin3[] = ".11";
printf("%s -> %f\n",bin, convert(bin));
printf("%s -> %f\n",bin1, convert(bin1));
printf("%s -> %f\n",bin2, convert(bin2));
printf("%s -> %f\n",bin3, convert(bin3));
return 0;
}
I am wondering if this code can be used to check for negative value? I did try with a binary string of 11111101.11 and it gives the output of 253.75...
I have two questions:
What are the modifications I need to do in order to read a negative value?
I know that I can do the bit shift (as below) to check if the msb is 1, if it is 1, I know it is negative value...
if (14bit_data & 0x2000) //if true, it is negative value
The issue is, since it involves fraction part (but not only integer), it confused me a bit if the method still works...
If the binary number is originally not in string format, is there any way I could convert it to string? The binary number is originally fed from a fpga block written in VHDL say, 14 bits, with msb as the sign bit, the following 6 bits are the magnitude for integer and the last 6 bits are the magnitude for fractional part. I need the decimal value in C code for Altera Nios II processor.
OK so I m focusing on the fact that you want to reuse the algorithm you mention at the beginning of your question and assume that the binary representation you have for your signed number is Two's complement but I`m not really sure according to your comments that the input you have is the same than the one used by the algorithm
First pad the 2 MSB to have a 16 bit representation
16bit_data = (14_bit_data & 0x2000) ? ( 14_bit_data | 0xC000) : 14_bit_data ;
In case value is positive then value will remained unchanged and if negative this will be the correct two`s complement representation on 16bits.
For fractionnal part everything is the same compared to algorithm you mentionned in your question.
For integer part everything is the same except the treatment of MSB.
For unsigned number MSB (ie bit[15]) represents pow(2,15-6) ( 6 is the width of frationnal part ) whereas for signed number in Two`s complement representation it represents -pow(2,15-6) meaning that algorithm become
/* integer part operation */
while(p >= 1)
{
rem = (int)fmod(p, 10);
p = (int)(p / 10);
dec = dec + rem * pow(2, t) * (9 != t ? 1 : -1);
++t;
}
or said differently if you don`t want * operator
/* integer part operation */
while(p >= 1)
{
rem = (int)fmod(p, 10);
p = (int)(p / 10);
if( 9 != t)
{
dec = dec + rem * pow(2, t);
}
else
{
dec = dec - rem * pow(2, t);
}
++t;
}
For the second algorithm that you mention, considering you format if dot == 11 and i == 0 we are at MSB ( 10 integer bits followed by dot) so the code become
for(i = dot - 1; i >= 0 ; i--)
{
if (binary[i] == '1')
{
if(11 != dot || i)
{
result += (double) pow(2,(dot-i-1));
}
else
{
// result -= (double) pow(2,(dot-i-1));
// Due to your number format i == 0 and dot == 11 so
result -= 512
}
}
}
WARNING : in brice algorithm the input is character string like "11011.101" whereas according to your description you have an integer input so I`m not sure that this algorithm is suited to your case
I think this should work:
float convert14BitsToFloat(int16_t in)
{
/* Sign-extend in, since it is 14 bits */
if (in & 0x2000) in |= 0xC000;
/* convert to float with 6 decimal places (64 = 2^6) */
return (float)in / 64.0f;
}
To convert any number to string, I would use sprintf. Be aware it may significantly increase the size of your application. If you don't need the float and what to keep a small application, you should make your own conversion function.

How to count two characters in a string?

There are three parameters (String s, char c, char d)
How do I define a method so that it returns as an int, the number of times the char c occurs in the String s added to the number of times the char d occurs in the String s?
Depending on the language, there could already be an existing function that does this for you.
Otherwise, you'd need to treat the string like an array (if the language does that, then great. If it doesn't, then you need to cast it into an array), run a loop and use a counter. If you want to look for specific characters, you can pass that in a function along with the string/array).
Example (this is just psudo-code, since I don't know what language you're using):
function countCharsInString(string s, char c1, char c2)
{
int count = 0;
for(i = 0; i < s.Length; i++)
{
if(s[i] == c1 || s[i] == c2)
{
count++;
}
}
return count;
}

Resources