|
|
View previous topic :: View next topic |
Author |
Message |
SEptic
Joined: 02 Sep 2008 Posts: 3
|
Sending a float through CANbus |
Posted: Tue Sep 02, 2008 6:46 am |
|
|
So ive got two PICs connected via CAN bus using those MCP2551 CAN bus transceiver thingies. Ive got it working 100% no problems everythings fine.... wait for it... BUT .. there it is :P
can-18xxx8.c
... as far as my mind can stretch, it understands that wen u send a message over canbus, u are essentially sending an array of integers (8bits x 8integers) .. yea???
... now how would i go about taking a floating point variable, cutting it up into four bytes, sending it over Canbus and on the other side, make em into a foating point variable again???
i know how to do that when writing floats to eeprom, u gotta like do a for loop thingy and then index address ur float. i would obviously have to do sumthing like that yea???
a point in the right direction would be really really awesomeness and appreciated
chow for now |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Sep 02, 2008 7:02 am |
|
|
There are several ways to do this.
With a union
Sending:-
Code: |
union myval {
float fl;
int8 bytes[4];
}
fl = 0.14;
putc(bytes[0]);
putc(bytes[1]);
putc(bytes[2]);
putc(bytes[3]);
|
Recieving
Code: |
union myval {
float fl;
int8 bytes[4];
}
bytes[0] = getc();
bytes[1] = getc();
bytes[2] = getc();
bytes[3] = getc();
printf("%f", fl);
|
Using a pointer
Code: |
int8 *fl_ptr;
float fl;
fl = 0.14;
fl_ptr = &fl;
putc(*fl_ptr++);
putc(*fl_ptr++);
putc(*fl_ptr++);
putc(*fl_ptr);
|
Code: |
int8 *fl_ptr;
float fl;
fl_ptr = &fl;
*fl_ptr++ = getc();
*fl_ptr++ = getc();
*fl_ptr++ = getc();
*fl_ptr = getc();
printf("%f", fl);
|
|
|
|
SEptic
Joined: 02 Sep 2008 Posts: 3
|
|
Posted: Tue Sep 02, 2008 7:08 am |
|
|
wow thanks for such a quick reply
awesome lemme try it out
thank you very much wayne |
|
|
SEptic
Joined: 02 Sep 2008 Posts: 3
|
|
Posted: Tue Sep 02, 2008 8:49 am |
|
|
Wayne_ .... you're my hero!
awesome got it working using a union thing,
took a few tries and a bit of chop and change
but i got it working nicely
many many thanx mate :D
laters |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Sep 02, 2008 10:08 am |
|
|
Glad to be of help.
Enjoy |
|
|
ratgod
Joined: 27 Jan 2006 Posts: 69 Location: Manchester, England
|
|
Posted: Sun Sep 07, 2008 12:35 am |
|
|
I've tried several different methods, including your 2 but I cannot seem to get any to work right.
Code: |
float float1=123.45f,float2=0;
byte a=0,b=0,c=0,d=0;
void float_to_bytes(byte *a,*b,*c,*d,float data1)
{
union myval
{
float fl;
int8 bytes[4];
} x;
x.fl = data1;
*a=x.bytes[0];
*b=x.bytes[1];
*c=x.bytes[2];
*d=x.bytes[3];
}
float bytes_to_float(byte a,b,c,d)
{
union myval
{
float fl;
int8 bytes[4];
} x;
x.bytes[0] = a;
x.bytes[1] = b;
x.bytes[2] = c;
x.bytes[3] = d;
return(x.fl);
} |
these are called by these lines
Code: | printf(" %4.4f : %4.4f : %x : %x : %x : %x \r\n",float1,float2,a,b,c,d);
float_to_bytes(&a,&b,&c,&d,&float1);
printf(" %4.4f : %4.4f : %x : %x : %x : %x \r\n",float1,float2,a,b,c,d);
float2=bytes_to_float(a,b,c,d);
printf(" %4.4f : %4.4f : %x : %x : %x : %x \r\n",float1,float2,a,b,c,d);
|
but all I seem to get out of from this is this:
Code: |
123.4500 : 0.0000 : 00 : 00 : 00 : 00
123.4500 : 0.0000 : 86 : 5c : 00 : 00
123.4500 : 220.0000 : 86 : 5c : 00 : 00
|
I don't know enough about memory organisation of float to tell if the problem is at the float_to_bytes or bytes_to_float routine.
I get the same result when using both of your examples. same when I use a modified version of these routines http://www.ccsinfo.com/faq.php?page=write_eeprom_not_byte
any idea where I'm going wrong? |
|
|
Ttelmah Guest
|
|
Posted: Sun Sep 07, 2008 2:47 am |
|
|
Your pointer handling is screwed up... You have _global_ variables called 'a,b,c,d', and local variables with the same name. Always risky. But then you pass the four integer value _addreses_ (OK), but then pass the _address_ of the float. The routine wants the _value_... Hence what you see, are the two bytes representing the address of the float variable...
The union approach is likely to be slightly quicker (depends how good the optimisation is on the PIC). Why not just use the union locally?. Calling the routine is an extra overhead. So:
Code: |
union conv {
float f;
int8 b[4];
};
union conv val1, val2;
//Pt a float value into the first variable
val1.f=123.45;
printf(" %4.4f : %x : %x : %x : %x \r\n",val1.f,\
val1.b[0],val1.b[1],val1.b[2],val1.b[3]);
//The four bytes that make up the float
//Put four bytes into the second
val2.b[0]= 0x86;
val2.b[1]= 0x6A;
val2.b[2]= 0x8F;
val2.b[3]= 0x5C;
printf(" %4.4f : %x : %x : %x : %x \r\n",val2.f,\
val2.b[0],val2.b[1],val2.b[2],val2.b[3]);
//The new float value, and the bytes that make it.
|
Remember you have the Pconvert tool in your PICC directory (if you have the 'W' version compiler), that allows you to see what bytes should make up a number.
Best Wishes |
|
|
ratgod
Joined: 27 Jan 2006 Posts: 69 Location: Manchester, England
|
|
Posted: Sun Sep 07, 2008 7:53 am |
|
|
What I'm doing here is simulating the buffer and conversion ready to drop into my CAN code.
The variables a,b,c,d are global as they represent the payload part of my packet buffer. Float1 would represent a voltage or current value read from ADC and float2 would represent the buffer for this value on the target system.
I'm still learning about pointers and haven't got my head around them completely unfortunately, but I understand what you mean.
Ok, just made the alterations (local variables are named uniquely and removed & from passing the float).
It works great,
many thanks for that, I will keep it all in mind from now on. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|