|
|
View previous topic :: View next topic |
Author |
Message |
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
Increment variable float! |
Posted: Thu Nov 22, 2012 4:35 am |
|
|
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: 19516
|
|
Posted: Thu Nov 22, 2012 4:49 am |
|
|
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
|
|
Posted: Thu Nov 22, 2012 6:38 am |
|
|
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: 19516
|
|
Posted: Thu Nov 22, 2012 8:43 am |
|
|
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
|
|
Posted: Thu Nov 22, 2012 1:24 pm |
|
|
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: 19516
|
|
Posted: Thu Nov 22, 2012 4:07 pm |
|
|
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
|
|
Posted: Thu Nov 22, 2012 5:01 pm |
|
|
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
|
|
Posted: Thu Nov 22, 2012 9:55 pm |
|
|
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
|
|
Posted: Fri Nov 23, 2012 1:55 am |
|
|
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: 19516
|
|
Posted: Fri Nov 23, 2012 2:12 am |
|
|
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
|
|
Posted: Fri Nov 23, 2012 4:33 am |
|
|
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 |
|
|
ERICOO
Joined: 13 Jun 2011 Posts: 14 Location: NIGERIA
|
|
Posted: Sun Nov 25, 2012 3:00 am |
|
|
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: 19516
|
|
Posted: Sun Nov 25, 2012 3:32 am |
|
|
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
|
|
Posted: Sun Nov 25, 2012 7:26 am |
|
|
Hi!!
Excellent ideas Ttelmah and ERICOO !
Thanks |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Nov 25, 2012 3:24 pm |
|
|
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.
|
|
|
|
|
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
|