CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Floats are broken?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Bollo



Joined: 01 Dec 2010
Posts: 25

View user's profile Send private message

Floats are broken?
PostPosted: Wed Sep 14, 2011 4:12 pm     Reply with quote

Hello I'm using CCS 4.120 currently and I have a very concerning problem. I have a calculation involving heavy use of floats. If I printf or sprintf the result of the calculation the result is correct and my system works. If I comment out the sprintf or printf the result is incorrect. Here is the calculation

Code:
current_speed=(ENC_DIF*5.82E-5)/(ENC_TIME_DIF*5E-7); //worksout speed is m/s


If I do this

Code:
sprintf(FFS,"%f",current_speed);


on the next line it works, comment it out and it doesn't. FFS is a local char array.

The ENC_DIF and ENC_TIME_DIF vars are both local signed int16 and current_speed is a local float. How can sprintf/ printf be having such a profound effect on a calculation?

To be honest I have had instances in the past where I've been convinced that using printf with a float has caused the data in the float var to change but normally I just put it down to me doing something silly.

The code is part of a DC motor controller, this part is working out speed using a magnetic encoder, the speed is passed onto a PID controller which adjusts the duty cycle according to the set desired speed.

When I say the calc is successful I mean the motor starts spinning at the desired speed when the printf or sprintf is present. Without it the motor just judders.

Any one had anything like this happen to them?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 4:22 pm     Reply with quote

This is the 2nd page of a thread that discusses a floating point problem
that may be similar to yours. See the proposed solution at the end of
the thread. I didn't try it, but you could test it. See if it makes it work.
http://www.ccsinfo.com/forum/viewtopic.php?t=45529&start=15
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Sep 14, 2011 5:16 pm     Reply with quote

just 4 grins ;-))))))

I have a much older version than you - but have had the odd float trouble in my past as well.

if you leave out the printf but do this:
Code:

current_speed= (float) ((ENC_DIF*5.82E-5)/(ENC_TIME_DIF*5E-7));



OR in the event that the named vars are NOT floats already ....

Code:

current_speed=(((float)ENC_DIF)*5.82E-5)/(((float)ENC_TIME_DIF)*5E-7);



Do either of those explicit declarations help?
Bollo



Joined: 01 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 7:37 pm     Reply with quote

Thanks for the replies. I already tried explicitly casting to no avail. I will attempt initialising them to a non zero number tomorrow (GMT) and let you know how it goes.
Bollo



Joined: 01 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 7:04 am     Reply with quote

I initialised all my floats to non zero (1's in fact) and still no change, the only thing that will make it work is sprintf / printf. It looks like floats are broken Shocked I will attempt to remove as many as I can and replace them with integer calculations.
Bollo



Joined: 01 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 8:19 am     Reply with quote

Oh I take it back! The one explicit cast I didn't try was casting current_speed to a float (even though a handful of lines above I initialise the variable as a float)



Code:
int8 ENC_GET_SPEED(){
   signed int16 ENC_TIME_DIF,ENC_DIF;
   unsigned int16 ENC_TIME2,ENC_POS2;
   float current_speed=1.111;
      

      if (GLOBAL_ERROR==1){return 2;} //Needs to be at the top of every top level function
      if (duty == 0){SPEED=0.0;}
      else{      
         ENC_TIME2=ENC_TIME1;  //record the old time ready for the the new
         ENC_POS2=ENC_POS1;
         ENC_POS1=get_enc_pos();   
         ENC_TIME1=get_timer3();
         ENC_TIME_DIF = ENC_TIME1 - ENC_TIME2;
         if (ENC_TIME_DIF<0){ENC_TIME_DIF=(65535-ENC_TIME2)+ENC_TIME1;} //deals with 1 single overflow
            
         ENC_DIF = ENC_POS2-ENC_POS1;
         
      //   if (ENC_DIF<0){ENC_DIF=(1023-ENC_POS1)+ENC_POS2;} //deals with overflow

         if (ENC_DIF<-5){ENC_DIF=(1023-ENC_POS1)+ENC_POS2;}
            if (ENC_DIF<0){ENC_DIF=0;}

         
         float current_speed=(ENC_DIF*5.82E-5)/(ENC_TIME_DIF*5E-7); //worksout speed is m/s
         //   printf("<%1.2f>,",current_speed);
         delay_us(100);
         SPEED=rollingav(current_speed);
      }

}


This also has the same effect as a printf / sprintf. The calculation now works. Very odd.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Sep 15, 2011 8:44 am     Reply with quote

thats a heck of a function your wrote .
&&
all to return the nearest signed 8 bits
THAT YOU NEVER ACTUALLY ASSIGN ANYWAY ?????

yes heck of a function

your blend of a float constant with
signed and unsigned int16s with god-knows-what from rollingav()
is awesome but i'm amazed the compiler would accept it all.

1- makes my head spin.
2- proves how really EXCELLENT CCS is at dealing with sloppy code

just my 2 cents
Bollo



Joined: 01 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 9:06 am     Reply with quote

Sorry I should explain more. The float constant is not really a constant, it was an experiment to see if initialising the float to non zero would help the problem (see PCM's post above). The returning of the int8 is nothing to do with the actual function of the code, it returns an error code. The rolling average function takes in the current speed and returns a rolling average of the current speed (with past speeds of course). The purpose of the function is to update global variable SPEED which is used in many of the other top level functions. Now I'm not brilliant at coding, but I'm struggling to see how it could be done better.

Here it is cleaned up from the experimenting.

Code:
int8 ENC_GET_SPEED(){
   signed int16 ENC_TIME_DIF,ENC_DIF;
   unsigned int16 ENC_TIME2,ENC_POS2;
   float current_speed;
   
      if (GLOBAL_ERROR){return 2;} //Needs to be at the top of every top level function
      if (duty == 0){SPEED=0.0;}
      else{      
         ENC_TIME2=ENC_TIME1;                                   //record the old time ready for the the new
         ENC_POS2=ENC_POS1;                                    // record the old position ready for the new
         ENC_POS1=get_enc_pos();                                 // get motor position from encoder
         ENC_TIME1=get_timer3();                               // get current time
         ENC_TIME_DIF = ENC_TIME1 - ENC_TIME2;                      //calculate the difference in time
         if (ENC_TIME_DIF<0){ENC_TIME_DIF=(65535-ENC_TIME2)+ENC_TIME1;}    //deals with 1 single overflow
         ENC_DIF = ENC_POS2-ENC_POS1;                            //calculate the difference in motor positions
         if (ENC_DIF<0){ENC_DIF=(1023- ENC_POS1)+ENC_POS2;}             //deals with overflow
         float current_speed=(ENC_DIF*5.82E-5)/(ENC_TIME_DIF*5E-7);       //works out speed is m/s
         
         SPEED=rollingav(current_speed);                         //return the weighted rolling average of the speed
      }
}


I don't think the code is as sloppy as you think! Sad

Now please if you have any ideas on how to do this in a more efficient way please let me know. Very Happy
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 9:53 am     Reply with quote

Quote:
This is the 2nd page of a thread that discusses a floating point problem
that may be similar to yours. See the proposed solution at the end of
the thread. I didn't try it, but you could test it. See if it makes it work.


I have no active PIC16 projects now, so I'm reviewing the discussion out of curiosity. If I understand the results right, the present compiler version has still bugs with float and you are trying to find a workaround?
Bollo



Joined: 01 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 10:04 am     Reply with quote

I'm using a PIC18F26K20, and yes there seems to be bugs with floats and/or printf and floats. I have not come across a consistent work around so far.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 2:46 pm     Reply with quote

Do you have a minimum complete example that reproduces the problem? The code snippets posted in this thread as well in the other quoted ones have been never complete and several posts saying "can't reproduce the issue".

It would be helpful, if the example can be run in the simulator without depending on ADC input voltage or similar things.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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