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 CCS Technical Support

Increment variable float!
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

Increment variable float!
PostPosted: Thu Nov 22, 2012 4:35 am     Reply with quote

Hi!
It is possible to write a decimal value in a float variable, with one pin, through a button, incrementing this variable.
For example, write in the variable (float temp;) the value 25.6 °C then compare with the temperature sensor to trigger a relay!
The reason is that I have only one pin available to write the value in the variable.
How can I solve this problem!
I thank you all help possible!
Code:

#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <HDM64GS12.c>
#include <graphics.c>

#use standard_io(a)
#use standard_io(c)

char teste[6];
float temp;

void main (){

glcd_init(on);   //GLCD
delay_ms(200);
 
while(true){
if(input(PIN_C4)!=0){
tem=temp + 1; //here does not work

sprintf(teste,"%4.1f",temp);
glcd_text57(18,22,teste,3,ON);

delay_ms(100);}
}
}


Last edited by fiasgardone on Thu Nov 22, 2012 6:39 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Thu Nov 22, 2012 4:49 am     Reply with quote

Have you proved your button is working as it should be?. Same code, using an int, instead of a float?.
What you post does work, provided C4 does go high.
How is your C4 wired?. As posted, it'd need a pull down resistor, and a switch to 5v.
What compiler version?. Though I don't know of any having as 'basic' a problem as this (except with some of the DsPic versions), worth asking, then we can test the same version.
You might be causing a problem by having two variables called 'temp'. Though the compiler should use the one declared in main (local one) it is potentially dangerous.
You also need to initialise the variable. As posted, the initial value will depend on 'luck', and could be a silly value with several decimals, and then lead to the display routine overwriting the variable, when teste is not large enough.

Best Wishes
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

PostPosted: Thu Nov 22, 2012 6:38 am     Reply with quote

hello Ttelmah
I'll try to answer your questions.

Quote:
Have you proved your button is working as it should be?. Same code, using an int, instead of a float?.
What you post does work, provided C4 does go high.


Yes, I did several tests and works

Quote:

How is your C4 wired?. As posted, it'd need a pull down resistor, and a switch to 5v.


The C4 is wired to be connected to the button, the resistor pull down is also placed.

Quote:
What compiler version?.


Version 4.120

Quote:
You might be causing a problem by having two variables called 'temp'. Though the compiler should use the one declared in main (local one) it is potentially dangerous.


Well, a variable is local and the other is global, I thought no problem, tested code only with a global variable, but follows no work on the decimal.

Quote:

You also need to initialise the variable. As posted, the initial value will depend on 'luck', and could be a silly value with several decimals, and then lead to the display routine overwriting the variable, when teste is not large enough.


I've done several tests with variables float but with no result, if it is possible to do what I want, have to have your help, because I have tested all my knowledge and I could not make it work
All help is welcome

thank
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Thu Nov 22, 2012 8:43 am     Reply with quote

You also show the increment as tem=temp+1;
Obviously that wouldn't work.....

I have already tested this, and it works (with the variable name typed right).

It is just 'bad practice' to have variable names the same locally and globally. It is asking for you to talk to the wrong one.

Things I did change:

1) Made teste larger. If the variable does contain an unexpected number 5 useable characters is not enough.
2) Initialised the variable.

It runs fine.
Code:

#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <HDM64GS12.c>
#include <graphics.c>

char teste[10];
float temp_global=0;

void main (){
   glcd_init(ON);
   while(true){
   if(input(PIN_C4)!=0){
      temp_global=temp_global + 1; //here does not work

      sprintf(teste,"%4.1f",temp_global);
      glcd_text57(18,22,teste,3,ON);

      delay_ms(100);
      }
   }
}


Best Wishes
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

PostPosted: Thu Nov 22, 2012 1:24 pm     Reply with quote

Hi! Ttelmah Thanks for your help!

To show the decimal part also made the following change in the code **temp_global=temp_global + 0.1; **, and now works as I want, although it takes a while to increase the variable starting from zero to the desired value of up to!

Continuing with the tests I compare the value of the variable float temp_global, with the value of varivel float temp_sensor, which simulates the sensor value that want to control.

But compared with the variables below does not work, how to do this?

Code:
#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <HDM64GS12x.c>
#include <graphicsx.c>

#use standard_io(a)
#use standard_io(c)


char teste[10];

float temp_global=34.0; //values ​​to simulate, you should connect the....
float temp_sensor=34.0;//.....relay on pin C5, but does not work
void main (){
   glcd_init(ON);
   
   while(true)
   {
 
   if(input(PIN_C4)!=0)
   {
      glcd_fillscreen(off);

      temp_global=temp_global + 0.1; //

      sprintf(teste,"%2.1f",temp_global);
      glcd_text57(18,22,teste,3,ON);
       
      delay_ms(200);
      }
     
      if(temp_global == temp_sensor) //[b]With this comparison of variables does not work, how to do this?[/b]      {
      output_high(PIN_C5);
      delay_ms(1000);
      }
     
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Thu Nov 22, 2012 4:07 pm     Reply with quote

Testing for equality, is always going to be a problem. Float variables cannot represent numbers accurately. Some they can, but most _will_ have errors. If you ask a float to hold something like 99.9, the actual value held will probably be something like 99.8999. Then if you do an equality test, it is never going to match. So, you have to be more complex in your tests:
Code:

    if(temp_global > (temp_sensor-0.001)) {
        if (temp_global<(temp_sensor+0.001) {
            output_high(PIN_C5);
            delay_ms(1000);
        }
    }

//Or
    if (fabs(temp_global-temp_sensor)<0.001) {
        output_high(PIN_C5);
        delay_ms(1000);
    }


Tests for the two values being within 0.001 of one another.

Best Wishes
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

PostPosted: Thu Nov 22, 2012 5:01 pm     Reply with quote

Hi! Ttelmah!

The two codes as such work, the problem is that when the two values of the variables are equal to variable (temp_global) begins to increase steadily, without pressing the button!

What I really want is that when the values are equal, the PIN_C5 (relay) stay tuned.

I made several changes to the code but it continues doing the same. What is the problem ?

Thanks for your attention.
Code:

#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

#include <HDM64GS12.c>
#include <graphics.c>
#include <math.h>

#use standard_io(a)
#use standard_io(c)

char teste[10];
float temp_global=33.0;
float temp_sensor=33.5;

void main (){
   glcd_init(ON);
   
   while(true)
   {
 
   if(input(PIN_C4)!=0)
   {
      glcd_fillscreen(off);
      temp_global=temp_global + 0.1; //

      sprintf(teste,"%2.1f",temp_global);
      glcd_text57(18,22,teste,3,ON);
       
      delay_ms(200);
      }
     
    if(temp_global > (temp_sensor-0.001)) {
        if (temp_global<(temp_sensor+0.001)) {
            output_high(PIN_C5);
            delay_ms(1000);
        }
    }
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Thu Nov 22, 2012 9:55 pm     Reply with quote

Have you checked your circuit for shorts or solder bridges? If C5 and C4 are shorted, that could explain your problem. The only other thing I can think of would be to check the LCD driver doesn't use C4 for anything.

BTW, in general floats are avoided in microcontrollers. In your case, what I would do is use an int16 to hold temperatures in 0.1deg units. i.e. 335 in the variable is 33.5deg. CCS then have a special 'w' format that puts the decimal point in the right place:
Code:
sprintf(teste,"%3.1w",temp_global);
. Floating point code is a lot bigger and slower than integer code. I've never needed to use floating point.
_________________
Andrew
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 1:55 am     Reply with quote

hello my friends
I did the tests as has been proposed here, with float variables, and without float variables, and works well.
Thanks for your help

Code:
#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <HDM64GS12x.c>
#include <graphicsx.c>
#include <math.h>


#use standard_io(a)
#use standard_io(c)


char teste[10];
float temp_global=33.0;
float temp_sensor=33.5;

void main ()
  {
   glcd_init(ON);
   
   while(true)
   {
 
   if(input(PIN_C4)!=0)
   {
      glcd_fillscreen(off);
      temp_global=temp_global+0.1; //
      delay_ms(200);
      }
     if(input(PIN_C3)!=0)
      {
      glcd_fillscreen(off);
      temp_global=temp_global-0.1; //
      delay_ms(200);
      }
     
      sprintf(teste,"%3.1f",temp_global);
      glcd_text57(18,22,teste,3,ON);
     
    if(temp_global >=(temp_sensor))
      {
       output_high(PIN_C5);
       delay_ms(100);
        }
    if(temp_global <=(temp_sensor)) { 
       output_low(PIN_C5);
       delay_ms(100);
    }


    }


Code:
#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <HDM64GS12x.c>
#include <graphicsx.c>
#include <math.h>


#use standard_io(a)
#use standard_io(c)


char teste[10];
int16 temp_global=330;
int16 temp_sensor=345;

void main ()
  {
   glcd_init(ON);
   
   while(true)
   {
 
   if(input(PIN_C4)!=0)
   {
      glcd_fillscreen(off);
      temp_global=temp_global+1; //
      delay_ms(200);
      }
     if(input(PIN_C3)!=0)
      {
      glcd_fillscreen(off);
      temp_global=temp_global-1; //
      delay_ms(200);
      }
     
      sprintf(teste,"%3.1w",temp_global);
      glcd_text57(18,22,teste,3,ON);
     
    if(temp_global ==(temp_sensor))
      {
       output_high(PIN_C5);
       delay_ms(100);
        }
    if(temp_global <(temp_sensor)) { 
       output_low(PIN_C5);
       delay_ms(100);
    }


    }

     
   }
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 2:12 am     Reply with quote

It is perhaps worth repeating at this point, that float variables should probably be avoided.
Banks don't use them. Nor do most scientific instruments. Their advantage is fantastic flexibility, but their downsides are rounding errors, and loss of accuracy when working in a fixed range. If (for instance), you are reading temperature, then you are much better off working with (say) integer 'millidegrees'. Keep everything integer, till you actually output the number (CCS has a scaled output format %w, while may help). Working with 32bit integers, would give a potential maximum temperature (assuming Kelvin), of 4 billion degrees, faster maths, no rounding problems, accurate comparisons, etc. etc.. 32bit accuracy, versus only 23bit from a 4byte float....
Do a search on the forum about this.

Best Wishes
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 4:33 am     Reply with quote

Ttelmah wrote:
It is perhaps worth repeating at this point, that float variables should probably be avoided.
Banks don't use them. Nor do most scientific instruments. Their advantage is fantastic flexibility, but their downsides are rounding errors, and loss of accuracy when working in a fixed range. If (for instance), you are reading temperature, then you are much better off working with (say) integer 'millidegrees'. Keep everything integer, till you actually output the number (CCS has a scaled output format %w, while may help). Working with 32bit integers, would give a potential maximum temperature (assuming Kelvin), of 4 billion degrees, faster maths, no rounding problems, accurate comparisons, etc. etc.. 32bit accuracy, versus only 23bit from a 4byte float....
Do a search on the forum about this.

Best Wishes


Thanks Ttelmah Very Happy
ERICOO



Joined: 13 Jun 2011
Posts: 14
Location: NIGERIA

View user's profile Send private message

PostPosted: Sun Nov 25, 2012 3:00 am     Reply with quote

I just want to contribute by saying that you could use software to faster increment of the variable until it is equal the targeted value of say 25.1
Code:

while(temp_global<25.1){
temp_global+ = 0.1;
}

Be sure that temp_global has initially been declared as float.
With a single push of the push button temp_global will increment until it gets to 25.1 before the next code will executed.
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Sun Nov 25, 2012 3:32 am     Reply with quote

Or, much simpler, if you want to start at 20+, then initialise it with:
Code:

float temp_global=20;


Best Wishes
fiasgardone



Joined: 19 Jan 2010
Posts: 71

View user's profile Send private message

PostPosted: Sun Nov 25, 2012 7:26 am     Reply with quote

Hi!!

Excellent ideas Very Happy Ttelmah and ERICOO !

Thanks
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Sun Nov 25, 2012 3:24 pm     Reply with quote

fascinating....

I could not agree more forcefully with AVOIDING Floats unless absolutely required.

I've been working the past few days on a customer, project that
replaces a water-bath microscope stage micro-incubator, with a
replacement , low cost, electrically heated design.

The lock center point is 37.0 deg C
and the total range is only 31 to 44 deg C

My solution for accurate ( after offset calibration ) of a deg C
displayed environment is to actually use the Natsemi LM34 Fahrenheit sensor - digitized on a 12 bit pic 18f2523 - and an ext a/d reference of 1.234v

The internal maths convert all values for INTERNAL use
to represent deg F as a 16 bit quantity that is 10x calibrated to deg F ,
such that 98.6 deg F is INT 986. all set point management is done with deg F resolution. And to show it, as is, you simply use %3.1w formatting.

Transfer to C (37.0 nominal ) for user display is achieved with a simple conversion function when driving the LCD for eyballs to watch.
-
A source output of 10mv /deg F is much better resolved to deal with than a direct reading 10mv / deg C.

The use of nothing but integer math with decimated DISPLAY might
"float" your maths better too.


Very Happy Very Happy Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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