Go Down

Topic: Serial Communication (Read 2 times) previous topic - next topic

BlackDragon

Thank you very much. I reviewed the code and I am sorry to say that I do not understand it completely. I compiled it alone to help understand the process but am having difficulty when implementing into my code as to where to place it and the expected output. From the Microstrain (Inertia Link manufacturer), by the coding involved in the following link (http://www.microstrain.com/inertia-link.aspx) under documentation: 3DM-GX2® Orientation SDK: SDK master: Windows: Code: C: Library: Source: utils: there is a function called FloatFromBytes. This function does the IEEE754 conversion. To compare values, they recommended I use the website you gave with all 4 of the outputs given by my last posted code into a single line HEX input into the website. Can the Arduino Software handle such a function such as FloatFromBytes, or is it necessary to use the coding you produced? (I am sure this took much time to create--i was surprised but I need some comments or background to its process since this is a bit above my C knowledge.

Thank you

shelleycat

#21
May 05, 2009, 10:45 pm Last Edit: May 05, 2009, 11:00 pm by shelleycat Reason: 1
The inertial device sends out a number of bytes.  4 of the bytes (4*8=32bits) are a representation of the floating value, which is also 4*8=32bits.  

The arduino library does include float functions, which are also stored as 32bits, which is 4 consecutive bytes in memory.  If you declare a float variable, the compiler reserves 4 bytes space in memory for it.  It does not have a floatfrombytes as such.  

What the code does is overlay a 4 byte array, at the same point in memory, as a float value.  Both take the same amount of room.  This is the union{...}.  The union allows access to the same 4 bytes as either an array, or as a float.

So when the 4 bytes are received in, they are put in the correct position to be read as a float.

The rest of the code, is to print out the float.  First it converts the float to a long, a long can only store the integer part, so a float of say 100.25 would convert to an long of 100.  The second conversion is to get the fractional part, which is done by taking 100.25 - 100 = 0.25 (this is done as a float operation).  Then multiply 0.25 by 100 to get the value 25.  

The idea is that you declare these once:
union t_long_fl { // this assign the byte array on the same memory as the float
byte b_arr[4];
float f_var;
} ;

t_long_fl t1;
int j;

int int_part_of_float;
int frac_part_of_float;

at the top of your interpretation block.
The rest of the first code posted was to replace the blocks where you were reading in the successive bytes.  Obviously, you only need those code blocks where you are expecting a float.

Why not try to start with printing out the hex bytes in lines of 4, as the data, then put those values into the conversion website?  At least you will see if you are getting the sequencing right.

(To clarify, the first code example is for you to try; the second sketch was to verify the conversion was working.  It takes 3 commands:
enter the 4 bytes,  enter the float,  print out the bytes and the float.)

shelleycat

I've looked at floatfrombytes.

You can code that on an arduino.
It takes  a pointer to 4 bytes stored adjacently.  By pretending they are an array, it then moves each byte in turn onto the correct position on a float variable - much like my code did.  Then it returns the pattern of bits as a float.

Its doing the same as my code with the union.

The testbyteorder is to sort out which order the bytes are sent.  It must depend on the architecture of the processor; in the absence of that, just stuff the bytes in either 0-0 1-1 2-2 3-3 or 0-3 1-2 2-1 3-0

BlackDragon

i cannot get the following to compile and am concerned as to the unrecognition of "const" since it is not in brown text. Is this the reason for error? or is there another reason.




#include "i3dmgx2_Errors.h"
short convert2short(unsigned char *);
unsigned short convert2ushort(unsigned char *);
unsigned long convert2ulong(unsigned char *);
long convert2long(unsigned char*);
int calcChecksum(unsigned char *, int);

float FloatFromBytes(const unsigned char*);
char * explainError(int);
int TestByteOrder();

byte IMUByte =0;
float f;
float incomingByte = 0;     // for incoming serial data
int i;

char a;
char b;
char c;
char d;
char e;

char serOutString[11];
// array to hold string of arduino read values of digital pin


//int val=0;  // temporary value for inputs & outputs
//int val4=0;  //temp
//char val2=2;
//char val3=0;
//char val1=0;
//int p=0; // temporary value for pin




//read a string from the serial and store it in an array
//you must supply the array variable
void IMU_String (char *strArray) {
 int i = 0;
 if(Serial.available()) {    
   //Serial.print("reading Serial String: ");  //optional: for confirmation
   while (Serial.available()){            
     strArray = Serial.read();
     i++;
     // Serial.print(strArray[(i-1)]);         //optional: for confirmation
   }
   // Serial.println();                          //optional: for confirmation
 }      
}


//Print the whole string at once - will be performed only if thers is data inside it
//you must supply the array variable
void printSerialString(char *strArray) {
 int i=0;
 if (strArray != 0) {    
   while(strArray != 0) {
     //Serial.print( strArray );
     strArray = 0;                  // optional: flush the content
     i++;          
   }
 }
}


void setup()
{
Serial.begin(115200);
//e = 250;               // DEC for 0xFA   stop continuous mode
//Serial.print(e);

//a = 196;               // DEC for 0xC4   start continuous
//Serial.print(a);
//b = 193;                // DEC for 0xC1           dont change  
//Serial.print(b);
//c = 41;               // DEC for 0x29        dont change
//Serial.print(c);
d = 194;               // DEC for 0xC4     change for desired output see Microstrain Protocal
Serial.print(d);

delay(1000);

            if (Serial.available() >= 0) {
                   
float incomingBytes(const unsigned char* pBytes);
{
     float f = 0;
     
        ((BYTE*)(&f))[0] = pBytes[3];
        ((BYTE*)(&f))[1] = pBytes[2];
        ((BYTE*)(&f))[2] = pBytes[1];
        ((BYTE*)(&f))[3] = pBytes[0];
     
     
     
}


/*----------------------------------------------------------------------
* convert2long
* Convert four adjacent bytes to a signed long.
*
* parameters:  buffer : pointer to a 4 byte buffer.
* returns:     the converted value as a signed long.
*--------------------------------------------------------------------*/
long convert2long(unsigned char* plbyte) {
   long l = 0;
     {
        l = (plbyte[0] <<24) + (plbyte[1] <<16) + (plbyte[2] <<8) + (plbyte[3] & 0xFF);    
      }
           
     
       return l;
}


                      }
            }  
}          

void loop() {}

Thanks. This is our last step thankfully. Then after this is complete, then we need to organize the data by a record so we have AccelX = the float value, same for Y,Z? Do you need a record like they do, or is there another way?

shelleycat

Blackdragon, there are quite a few things wrong.  Can you get a local coder to help you.  I'm still not sure what you are trying to do...

1.  Structure needs correcting.  You cannot nest a function inside another function, hence you must move convert2long and incomingBytes out of setup().  

2.  Unless you have put the header file i3dmgx2_Errors.h into your arduino ide in the correct place, it will error and not compile.  Try taking it out and see what else errors.

3  All the "prototypes", which define functions, short covert2short(unsigned char *) are probably not needed (in this environement, the arduino ide tries to generate them for you).  Try removing them.

4  IMU_String should add a 0 to the end of the string to terminate it.  See how printSerialString is looking for a 0 to stop processing.  

5  const is OK, its a valid keyword.  Its probably not the problem. Remove it if you want.

6  brackets at the end do not look balanced.

7  You don't need printSerialString,
you get the same result with Serial.print(strArray).  The String library will print a string or a (null terminated) array of characters.

8 If you define a function, nothing happens unless you later call it.  For example convert2long would be a function definition if it were outside setup.  To call it - to actually make the computer do that processing -  you need a statement like this:

l = convert2long( char_array);

8  Can you plan out the overall code and show that?  Then code from that skeleton.

9  Have a close look at some examples of sketches.

I will try to have a look at the coding tomorrow, but its bedtime now.




Go Up