Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
fbonacic
PostPosted: Jul 31, 2012 - 08:35 PM
Rookie


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 Wink

Thanks!

fil
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
theusch
PostPosted: Jul 31, 2012 - 08:52 PM
10k+ Postman


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.)
 
 View user's profile Send private message  
Reply with quote Back to top
alank2
PostPosted: Aug 01, 2012 - 01:25 AM
Posting Freak


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
 
 View user's profile Send private message  
Reply with quote Back to top
midea31
PostPosted: Aug 01, 2012 - 04:07 AM
Hangaround


Joined: Jul 22, 2011
Posts: 123


does the same happen when you use sprintf?
 
 View user's profile Send private message  
Reply with quote Back to top
fbonacic
PostPosted: Aug 01, 2012 - 07:33 AM
Rookie


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!
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Koshchi
PostPosted: Aug 01, 2012 - 07:34 AM
10k+ Postman


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.
 
 View user's profile Send private message  
Reply with quote Back to top
fbonacic
PostPosted: Aug 01, 2012 - 08:13 AM
Rookie


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.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
sternst
PostPosted: Aug 01, 2012 - 09:03 AM
Raving lunatic


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
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 01, 2012 - 09:22 AM
10k+ Postman


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. Very Happy
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
fbonacic
PostPosted: Aug 01, 2012 - 10:15 AM
Rookie


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 Smile
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
alank2
PostPosted: Aug 01, 2012 - 01:03 PM
Posting Freak


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
 
 View user's profile Send private message  
Reply with quote Back to top
larryvc
PostPosted: Aug 01, 2012 - 04:51 PM
Raving lunatic


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. Very Happy

Especially if you were to post C++ code for Johan to dissect. Wink

_________________
Larry

Those afraid to embrace the future will quickly fade into the past. - larryvc
 
 View user's profile Send private message  
Reply with quote Back to top
fbonacic
PostPosted: Aug 01, 2012 - 08:19 PM
Rookie


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. Very Happy

Especially if you were to post C++ code for Johan to dissect. Wink


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
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
sternst
PostPosted: Aug 01, 2012 - 08:51 PM
Raving lunatic


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
 
 View user's profile Send private message  
Reply with quote Back to top
snigelen
PostPosted: Aug 01, 2012 - 08:58 PM
Posting Freak


Joined: Jan 08, 2009
Posts: 1153
Location: Lund, Sweden

I'm too slow Wink.
Anyway, if you write
Code:
P=(long long)P*CV/100;
P will be 62674 in the end.
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 01, 2012 - 09:17 PM
10k+ Postman


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...
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
theusch
PostPosted: Aug 01, 2012 - 10:06 PM
10k+ Postman


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...
 
 View user's profile Send private message  
Reply with quote Back to top
larryvc
PostPosted: Aug 01, 2012 - 10:10 PM
Raving lunatic


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. Smile

_________________
Larry

Those afraid to embrace the future will quickly fade into the past. - larryvc
 
 View user's profile Send private message  
Reply with quote Back to top
fbonacic
PostPosted: Aug 02, 2012 - 07:45 AM
Rookie


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 Smile

One more very simple question:
how to right justify these numbers using ltoa()?
with suppressing zeros ofcourse..
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 02, 2012 - 07:57 AM
10k+ Postman


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.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits