|
|
View previous topic :: View next topic |
Author |
Message |
hillcraft
Joined: 22 Sep 2003 Posts: 101 Location: Cape Town (South africa)
|
Math issue |
Posted: Wed Mar 14, 2007 8:06 am |
|
|
When the value of m3 is multiplied by 100 before being added to the variable then strange things happen under certain circumstances. If the value of m3 = 2 then it is ok but if the value of m3 is 3 then it gets very confused.
m1,m2, m4 all seem fine
if m3 is not multiplied by 100 then all is ok.
if m3 = 3 and multiplied by 100 then the answer is 44
if m3 = 4 and multiplied by 100 then the answer is 144
if m3 = 5 and multiplied by 100 then the answer is 244
The data does come through correctly from the PC
Pic side
---------
Code: |
float XdroPos=0;
float m1=0;
float m2=0;
float m3=0;
float m4=0;
if (usb_enumerated()) {
if (usb_kbhit(2)) {
usb_get_packet(2, rx_data, 8);
if (rx_Data[0]==2) { // DRO
if (rx_Data[1]==0) { // X DRO
m1 = rx_Data[4] & 0x0F; // blank off the high byte
XdroPos = m1;
m2 = (((rx_Data[4] & 0xF0) >> 4)*10); // blank off the low byte
XdroPos = XdroPos + m2;
m3 = ((rx_Data[3] & 0x0F)*100); // blank off the high byte
XdroPos = XdroPos + m3;
m4 = (((rx_Data[3] & 0xF0) >> 4)*1000); // blank off the low byte
XdroPos = XdroPos + m4;
if (rx_Data[2]=='-')
XdroPos = XDroPos * -1;
printf("m1 %09.4f m2 %09.4f m3 %09.4f m4 %09.4f X DRO %09.4f ",m1,m2,m3,m4,XdroPos);
}
}
// printf("Data Endpoint 2: ");
// for (i=0;i<=7;i++)
// printf("%C ",rx_data[i]);
// printf("0x%X ",rx_data[i]); |
PC side
---------
Code: | OutputReport[0]= 0; //this is just a report number, always zero
// lets update the X dro
CncCSDRO = GetDRO(800);
sprintf(CncCSDROBuffer, "%09.4f",abs(CncCSDRO)); // make sure that the - does not move the string about
// test the data move to the handheld
OutputReport[1] = 2; // DRO report
OutputReport[2] = 0; // X DRO
if (CncCSDRO>0)
OutputReport[3] = '+';
else
OutputReport[3] = '-';
OutputReport[4] = ((CncCSDROBuffer[0]-48) <<4) + (CncCSDROBuffer[1]-48); // take ascii back to a number
OutputReport[5] = ((CncCSDROBuffer[2]-48) <<4) + (CncCSDROBuffer[3]-48); // take ascii back to a number
OutputReport[6] = ((CncCSDROBuffer[5]-48) <<4) + (CncCSDROBuffer[6]-48); // take ascii back to a number
OutputReport[7] = ((CncCSDROBuffer[7]-48) <<4) + (CncCSDROBuffer[8]-48); // take ascii back to a number |
|
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Wed Mar 14, 2007 8:30 am |
|
|
Instead of multiplying by 10, 100 or 1000 try 10.0, 100.0 and 1000.0. Since they are multiplying floats things might get confused if you're multiplying a float by and integer.
Ronald |
|
|
hillcraft
Joined: 22 Sep 2003 Posts: 101 Location: Cape Town (South africa)
|
Ronald- Cured |
Posted: Wed Mar 14, 2007 8:45 am |
|
|
Hi Ronald,
Thanks, the problem is now cured. |
|
|
Ttelmah Guest
|
|
Posted: Wed Mar 14, 2007 9:21 am |
|
|
Not a case of 'getting confused', but exactly what you would expect!...
Presumably 'rx_data', is declared as an integer, or character array. Hence the multiplication will be done using this arithmetic type.
You could save significant time, by using (for example):
m3 = ((int16)(rx_Data[3] & 0x0F)*100); // blank off the high byte
Which will convert the value to an int16, and perform the arithmetic with this (whereas changing to 100.0, will force floating point arithmetic). The difference, is between 3.2uSec for the int16 multiply, and 35.8uSec for the float (on a 40MHz PIC18).
Best Wishes |
|
|
hillcraft
Joined: 22 Sep 2003 Posts: 101 Location: Cape Town (South africa)
|
(int16) |
Posted: Wed Mar 14, 2007 9:43 am |
|
|
Fair enough. I did not realize that by not using (int16) that I would get an error on only one digit if that digit is bigger than 2.
What about the folliwng X 0.1, 0.01, 0.001, 0.0001
This is what the entire number looks like:
-9999.9999
Code: | XdroPos = (rx_Data[6] & 0x0F)*0.0001; // blank off the high byte
XdroPos = XdroPos + (((rx_Data[6] & 0xF0) >> 4)*0.001); // blank off the low byte
XdroPos = XdroPos + (rx_Data[5] & 0x0F)*0.01; // blank off the high byte
XdroPos = XdroPos + (((rx_Data[5] & 0xF0) >> 4)*0.1); // blank off the low byte
XdroPos = XdroPos + (rx_Data[4] & 0x0F); // blank off the high byte
XdroPos = XdroPos + (((rx_Data[4] & 0xF0) >> 4)*10.0); // blank off the low byte
XdroPos = XdroPos + ((rx_Data[3] & 0x0F)*100.0); // blank off the high byte
XdroPos = XdroPos + (((rx_Data[3] & 0xF0) >> 4)*1000.0); // blank off the low byte |
|
|
|
Ttelmah Guest
|
|
Posted: Wed Mar 14, 2007 2:21 pm |
|
|
Series of choices.
1. Just do the decimal ones using FP.
2. Don't store the number like this, but *1000, in an int32. Then you can use int3 arithmetic throughout, and the %w option to print it as if it was 1/1000th the size (scaled integer working).
Best Wishes |
|
|
|
|
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
|