View previous topic :: View next topic |
Author |
Message |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
problem with dividing 2 float numbers |
Posted: Sun Jan 29, 2012 5:47 am |
|
|
I have similar program as :
Code: |
float num1,num2,num3;
num1=100;
num2=110;
num3=109;
num1=num1*num2/num3;
|
and the controller returns value for num1 - 0
What`s the problem??
Is the problem in the mantissa?? I think it`s some kind of overflowing.
Is there a way to restrict the numbers after the decimal point??? |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Sun Jan 29, 2012 7:31 am |
|
|
I see nothing wrong with what you show. Give us a short complete compilable program including output and maybe we can help you. Include your PIC type and compiler version number. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sun Jan 29, 2012 8:41 am |
|
|
Big question is 'how are you looking at the result'?.
If I'm understanding what you are saying - that you are seeing a small -ve number, then almost certainly you are using a simulator or debugger, and have set it to display a number formatted in IEEE float, rather than Microchip float, and so would see a value of -0.001.
Best Wishes |
|
|
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Sun Jan 29, 2012 9:02 am |
|
|
I`m using my own board with LCD display. I have a program which transfers float numbers using simple extracting 100, 10 , 1 to display the number.
When (in the example) num2>num3 everything is allright, but when num2<mun3 the num1 become 0.
Is the problem in the format transfering??? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Jan 29, 2012 10:22 am |
|
|
Why not just use the CCS supplied printf(...) function instead of your own creation ? |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1933 Location: Norman, OK
|
|
Posted: Sun Jan 29, 2012 10:25 am |
|
|
Who knows what compiler he is using or what else he is doing...
Quote: | I see nothing wrong with what you show. Give us a short
complete compilable program including output and maybe we can help
you. Include your PIC type and compiler version number. |
Still waiting.... _________________ Google and Forum Search are some of your best tools!!!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sun Jan 29, 2012 3:22 pm |
|
|
My guess would be your output code.
Seriously:
1) As temtronic says, 'why not use the supplied printf'.
2) If you still have problems, then look at dyeatman's post, and supply a _program_, as small as possible, including details of the PIC etc.
Assuming num1, stays at '100', then the key change when num2<num3, is that you stop having any data in the '100' column. I'd guess your output code is failing when this happens....
Best Wishes |
|
|
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Mon Jan 30, 2012 2:16 am |
|
|
I'm using CCS v4.078. PIC18F4620.
This is parts of my original code:
Code: |
int adc1,adc2;
float sum,coef;
adc1=read_adc();
.....
adc2=read_adc();
coef=adc1/adc2;
sum=arr[i]*coef;
|
And when adc2 become bigger than adc1, I have 0 for coef result and for sum respectively. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Mon Jan 30, 2012 2:34 am |
|
|
Of course it will.
This is completely different from what you originally posted.
You are dividing two _integers_, not two float values, using integer maths.
99/100 _integer_ = zero.....
The code to perform the division with _float_ arithmetic is:
coef=(float)adc1/adc2;
Best Wishes |
|
|
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Mon Jan 30, 2012 3:02 pm |
|
|
Thanks!
I want to ask another thing. Is there a problem if I compare int and float values???
For example:
Code: |
int var1=5;
float var2=6.0;
if(var1>var2) .....
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Mon Jan 30, 2012 4:39 pm |
|
|
Stick with integers. Floats cost you a _lot_ in time. For the comparison, it'll work, but what happens is that the integer is converted to a float, and then the comparison performed. Probably something in the order of 50* slower than an integer comparison.
Seriously, the same applies with your 'coefficient' value. You could (for example), keep the incoming values as integers (possibly int32), and multiply the top one by (say) 1024, and generate an _integer_ coefficient 1024* larger than the 'float' value. Then perform your scaling with this, and divide at the end. If you use a factor like 256, 512, 1024, then the division is fast (binary division of an integer, just involves a shift operation), and this is normally the slowest integer operation.
Integer code, is smaller, and faster. Used with some thought it can do 99% of the things that are normally done with float's, in most standard applications...
Best Wishes |
|
|
cenar
Joined: 31 Jan 2012 Posts: 7
|
|
Posted: Tue Jan 31, 2012 11:12 am |
|
|
hello everybody,
i have a similar issue and i didn't want to flood the forum with opening a new thread. i write a code to read the value from analog pin and calculate the pwm values for a differential steering robot. shortly, its a proportional control. my question is, when i try to divide two integers and give the result to a float variable ( like 5/2 = 2.5 ), it just doesnt work properly. my friend told me to make it 5.0/2.0, it doesnt worked. and i tried variable =(float) num1/num2 thing as it is mentioned on an earlier post, it didn't worked very well too. i don't know what am i doing wrong, i will post my code here because maybe i couldnt tell my problem well. sorry for this long post.
thanks in advance!
Code: |
#include <16F877A.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=4000000)
float value=0,turn=0,pwm1=0,pwm2=0,error=0;
void main()
{
setup_adc(ADC_CLOCK_DIV_16);
setup_adc_ports(AN0);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
setup_timer_2(T2_DIV_BY_16,255,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_ccp1(ccp_pwm);
setup_ccp2(ccp_pwm);
while (1) {
set_Adc_channel(0);
delay_ms(10);
value = read_adc();
error = value - 32736;
turn = error/64;
pwm1 = 128 + turn;
pwm2 = 128 - turn;
set_pwm1_duty(pwm1);
set_pwm2_duty(pwm2);
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Tue Jan 31, 2012 11:19 am |
|
|
You should have your program printout (send to PC or LCD) the variables you use. You only have 5 so that's easy.
Use a pot on the ADC input to run the test...
Look at what you get and compute. Does it seem right ?
What looks wrong? Show us..... |
|
|
cenar
Joined: 31 Jan 2012 Posts: 7
|
|
Posted: Tue Jan 31, 2012 11:57 am |
|
|
thank you for replying,
i dont know how to display the current values of the variables, but i run a simulation on isis and studied the pwm cycles with an oscilloscope, and noted these:
2 volts in analog pin: pwm1 = 32 and pwm2 = 160,
2.1 volts: pwm1=160 and pwm2= 32
2.2 volts: pwm1=96 and pwm2=96
i tried 0 volt, 5 volts and others but values were not following a pattern. as you can see, values are like randomly given and doesnt have a real pattern, thus i didn't studied so deep. i tried this code in real, put 2 leds in pwm pins. leds were blinking, not dimming. it looks like resetting the pic. maybe this can help, or gives a clue.
thanks |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Tue Jan 31, 2012 1:57 pm |
|
|
Have the PIC print out value, error, turn, pwm1, pwm2. This can be done with a software UART on any unused pin.
I would make all of these long ints instead of floats. Only use floats if you really can't find any way to avoid it. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
|