| Author |
Message |
|
|
Posted: Jul 31, 2012 - 08:35 PM |
|

Joined: Jul 01, 2010
Posts: 45
Location: Zagreb, Croatia
|
|
Hi,
I use ltoa() function to transfer long integer to string and them display it on HD44780 lcd.
Problem is when number (long) becomes greather then 60000, after it becomes -59999 , and as long is raising it goes to 0.
Code:
char str[10];
long P;
ltoa(P, str, 10);
lcd_puts(str);
similar thing happends with ultoa(), after 60000 numbers stays unsigned but with no sense.
I use alank2 lcd library which I found to work very well (true,till now numbers were always lower
Thanks!
fil |
|
|
| |
|
|
|
|
|
Posted: Jul 31, 2012 - 08:52 PM |
|


Joined: Feb 19, 2001
Posts: 25909
Location: Wisconsin USA
|
|
Perhaps check your calculation of "P". Is there an overflow of 16-bit arithmetic, perhaps? Do you get the same results with "P = 67890L;"?
(If you are displaying various values, I hope you are clearing the LCD line first, or right-justifying and padding, so you don't have "old stuff" remaining at LCD positions that are not being written by the string.) |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 01:25 AM |
|

Joined: Jul 16, 2009
Posts: 1579
|
|
Hi,
Also, don't forget to allocate your string to include the 0 byte terminator. If you want a 10 character string, you need 11 bytes, 10 for the characters and a final 0 byte.
Good luck,
Alan |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 04:07 AM |
|

Joined: Jul 22, 2011
Posts: 123
|
|
| does the same happen when you use sprintf? |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 07:33 AM |
|

Joined: Jul 01, 2010
Posts: 45
Location: Zagreb, Croatia
|
|
|
theusch wrote:
Perhaps check your calculation of "P". Is there an overflow of 16-bit arithmetic, perhaps? Do you get the same results with "P = 67890L;"?
(If you are displaying various values, I hope you are clearing the LCD line first, or right-justifying and padding, so you don't have "old stuff" remaining at LCD positions that are not being written by the string.)
I think I found mistake. long P is signed, 2 bytes for +, 2 for - values, I need values greather then 65536, so I'll change to unsigned long P.
But why it changes to - values after reaching 60000?
I'll try this and let you know! |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 07:34 AM |
|

Joined: Nov 17, 2004
Posts: 13840
Location: Vancouver, BC
|
|
|
Quote:
If you want a 10 character string, you need 11 bytes, 10 for the characters and a final 0 byte.
And a long can be up to 11 characters for negative numbers, so you really want 12 bytes here. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 08:13 AM |
|

Joined: Jul 01, 2010
Posts: 45
Location: Zagreb, Croatia
|
|
|
Koshchi wrote:
Quote:
If you want a 10 character string, you need 11 bytes, 10 for the characters and a final 0 byte.
And a long can be up to 11 characters for negative numbers, so you really want 12 bytes here.
Yes, this is for power (W) and power consumption (kWh) calculation of solar hot water system. It will be used for similar systems too (heat pump, cooling,..) so it needs to calculate and show only positive numbers, greater then 65536 W. |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 09:03 AM |
|


Joined: Jul 23, 2001
Posts: 2438
Location: Osnabrueck, Germany
|
|
|
Quote:
I think I found mistake. long P is signed, 2 bytes for +, 2 for - values, I need values greather then 65536
Nonsense. It's 31 bits for the value and 1 bit for the sign. Max positive value of a signed long is 2147483647.
Quote:
But why it changes to - values after reaching 60000?
I bet you have an error in the calculation of P. Show all the involved calculations and the declarations of all involved variables. |
_________________ Stefan Ernst
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 09:22 AM |
|


Joined: Mar 27, 2002
Posts: 18555
Location: Lund, Sweden
|
|
|
Quote:
But why it changes to - values after reaching 60000?
Because the moon is made out of green cheese, or gremlins have occupied your computer, or it is just the energy fields where you have the computer placed at the moment.
Any more serious suggestions require this: Post a minimal program that builds, runs and displays the problem.
Note the "minimal". Cut out everything that has no direct connection to the problem. During such a cut-down process it is not unlikely that you will see where the problem is yourself. If that does not happen - post the minimal program here and we will be on to it like hungru vultures.  |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 10:15 AM |
|

Joined: Jul 01, 2010
Posts: 45
Location: Zagreb, Croatia
|
|
|
sternst wrote:
Quote:
I think I found mistake. long P is signed, 2 bytes for +, 2 for - values, I need values greather then 65536
Nonsense. It's 31 bits for the value and 1 bit for the sign. Max positive value of a signed long is 2147483647.
You're absoutely right, sorry  |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 01:03 PM |
|

Joined: Jul 16, 2009
Posts: 1579
|
|
Hi,
Where everyone is going with this is that you have a bug in your calculation that is similar to this:
Code:
int i1,i2;
long li1;
i1=40000;
i2=50000;
li1=i1*i2; //i1*i2 will be treated as int*int which
//will overflow into an int (-32768 to 32768)
li1=long(i1)*i2; //will cast i1 as long and be treated
//as long*int which will not overflow
My example may not be right as I did not test it; many people around here know much more about how the compiler works...
Good luck!!
Alan |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 04:51 PM |
|


Joined: Dec 06, 2007
Posts: 2512
Location: Redmond, WA USA
|
|
|
JohanEkdahl wrote:
...post the minimal program here and we will be on to it like hungru vultures.
Especially if you were to post C++ code for Johan to dissect.  |
_________________ Larry
Those afraid to embrace the future will quickly fade into the past. - larryvc
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 08:19 PM |
|

Joined: Jul 01, 2010
Posts: 45
Location: Zagreb, Croatia
|
|
|
larryvc wrote:
JohanEkdahl wrote:
...post the minimal program here and we will be on to it like hungru vultures.
Especially if you were to post C++ code for Johan to dissect.
here is minimum code that compile & run. So why is calculated power negative?? It should be >60k
Code:
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr\pgmspace.h>
#include <avr\sfr_defs.h>
#include "hd44780.h"
void main(void)
{
char str[10];
int CV,RO,temp_c,temp_c1;
long dt,P,CP;
lcd_init();lcd_clrscr();
_delay_ms(1000);
while(1)
{
lcd_goto(0x00);
temp_c=494;
itoa(temp_c,str,10);
lcd_puts(str);
lcd_goto(0x40);
temp_c1=230;
itoa(temp_c1,str,10);
lcd_puts(str);
dt=temp_c-temp_c1;
RO=9974;CP=4180;CV=2050;
P=dt*CP/100;
P=P*RO/100;
P=P*CV/100;
P=P/360;
ltoa(P, str, 10);
lcd_goto(0x09);lcd_puts(str);
}
}
I don't see cast problem in formulas, cause one is always long.. P is power in Watts |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 08:51 PM |
|


Joined: Jul 23, 2001
Posts: 2438
Location: Osnabrueck, Germany
|
|
|
Quote:
here is minimum code that compile & run. So why is calculated power negative??
Because P*CV overflows. |
_________________ Stefan Ernst
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 08:58 PM |
|


Joined: Jan 08, 2009
Posts: 1153
Location: Lund, Sweden
|
|
I'm too slow .
Anyway, if you write
Code:
P=(long long)P*CV/100;
P will be 62674 in the end. |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 09:17 PM |
|


Joined: Mar 27, 2002
Posts: 18555
Location: Lund, Sweden
|
|
Not really the minimal program that demonstrates the problem. Below is what I have after throwing out the LCD and delay stuff, and removing the loop.
I then ran this in the Atmel Studio 6 Simulator, with optimization turned off, stepping through the calculations and watching the values of variables. I have added comments at the computations noting the resulting values.
Code:
#include <avr/io.h>
int main(void)
{
char str[10];
int CV,RO,temp_c,temp_c1;
long dt,P,CP;
temp_c=494;
temp_c1=230;
dt=temp_c-temp_c1; // dt = 264
RO=9974;
CP=4180;
CV=2050;
P=dt*CP/100; // P == 11035
P=P*RO/100; // P == 1100630
P=P*CV/100; // P == -20386757
P=P/360; // P == -56629
ltoa(P, str, 10);
}
So, now you can see where it goes wrong. While the end result of your computation should be small enough to fit as a positive value in a long, an intermediate computation clearly wraps around to negative.
This happens because of the 1100630*2050 which unsigned is 2256291500, but since you're using signed longs which has a largest positive value of 2147483647 it's wrapping to negative.
I most definitively urge you to redo this exercise in AVR/Atmel Studio yourself. As you see, the simulator can be a powerful tool for finding bugs. Learn it. Use it.
There are at least two possible solutions to your problem:
1) Rearrange the computations so that you do not overflow your signed long variables.
2) Use unsigned longs. You must still take care so that you do not overflow those too! If so, solution 1) again needs to be applied.
EDIT: Beaten to it by the brief posters... |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 10:06 PM |
|


Joined: Feb 19, 2001
Posts: 25909
Location: Wisconsin USA
|
|
|
Quote:
here is minimum code that compile & run. So why is calculated power negative?? It should be >60k
Sigh. What did I suggest some time ago?
Quote:
Do you get the same results with "P = 67890L;"?
Did you try that? If not, why not? If a constant value displays correctly with your sequence, then it isn't a problem with ltoa(0 etc., is it? Then it must be in the calculations... |
|
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 10:10 PM |
|


Joined: Dec 06, 2007
Posts: 2512
Location: Redmond, WA USA
|
|
|
JohanEkdahl wrote:
EDIT: Beaten to it by the brief posters...
Nonetheless, much more informative and educational.  |
_________________ Larry
Those afraid to embrace the future will quickly fade into the past. - larryvc
|
| |
|
|
|
|
|
Posted: Aug 02, 2012 - 07:45 AM |
|

Joined: Jul 01, 2010
Posts: 45
Location: Zagreb, Croatia
|
|
Thanks a lot for all these explanations. It comes down to one point P*CV=2256291500 > 2147483647. I tought complete expression P*CV/100 must not exceed 2147483647. It's clear now! With time I'll learn
One more very simple question:
how to right justify these numbers using ltoa()?
with suppressing zeros ofcourse.. |
|
|
| |
|
|
|
|
|
Posted: Aug 02, 2012 - 07:57 AM |
|


Joined: Mar 27, 2002
Posts: 18555
Location: Lund, Sweden
|
|
|
Quote:
how to right justify these numbers using ltoa()?
ltoa() can can not do that. Either switch to using something out of the printf() family, or code your own little thing for right-adjusting the buffer contents. There are many possible variants for that algorithm, and it has been discussed here in the past. A search of AVRfreaks might come up with something good. |
|
|
| |
|
|
|
|
|