• AVR Freaks

Hot!LCD display prints erroneously

Author
fotios
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2008/04/25 14:09:58
  • Location: GREECE
  • Status: offline
2019/04/04 23:21:01 (permalink)
0

LCD display prints erroneously

Hi everyone
I have a Uint variable: A_UINT
I have a multiplier that gets values from 1000d - 65535d: GAIN
I have a floating point variable: A_FLP
I have a string type variable: A_STR
I use the following calculation:
A_FLP = (A_UINT * GAIN * 0.001) / 32768

Then the A_FLP is converted to string for printing on LCD display:
A_STR = FloatToString$ (A_FLP,3)
 
On the actual LCD of application is printed correctly for GAIN values from 32768 and above.
For GAIN values from 32767 and below the LCD prints 0.000.
Why this?
The application micro is PIC16F18877.
Thanks

Fotis
#1

19 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: LCD display prints erroneously 2019/04/04 23:28:09 (permalink)
    +1 (1)
    Does it make a difference if you change it to
    A_FLP = (A_UINT * GAIN * 0.001) / 32768.0


    Nearly there...
    #2
    pcbbc
    Super Member
    • Total Posts : 1099
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 02:17:30 (permalink)
    +1 (1)
    Also, what type is GAIN?
    What is the range of allowed values for A_UINT?
    What is your chosen programming language?  Does not look like C to me.  Some kind of BASIC?
    What happens if GAIN x A_UINT suffers an overflow?
    For example A_UINT is > 65537d and GAINS is 65535d
    #3
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 04:09:08 (permalink)
    0
    Hi all and thanks for the replies.
     
    To qhb :
    I will try your suggestion and let you know
    Thanks
     
    To pcbbc :
    a) GAIN is a decimal value from 1000d - 65000d that I apply on the calculation and is not defined as a variable.
    Apparently is a Uint type number.
    b) A_UINT can get values from 0d to 65535d.
    c) I use FlowCode v7.0 which compiles in C. I'm not an expert in C.
    d) Probably, you are right on this. E.g. the division of 32767 / 32768 = 0.9999.
        If we multiply: A_UINT * 0.001 * 0.9999 then the LCD prints correctly.
    The problem arises from the division in the case that results in decimal numbers of less than 1. 
    Thanks  
     
       
     

    Fotis
    #4
    NKurzman
    A Guy on the Net
    • Total Posts : 17499
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 06:31:26 (permalink)
    0
    Assuming a Uint is an unsigned int it can hold o to 65535. You first Multiplication over flows.

    Try a cast:
    A_FLP = ((float)A_UINT * GAIN * 0.001) / 32768

    You relize that this calculation does not require flaoats. Long int would work. Times 0.001 could be replaced by a division
    #5
    1and0
    Access is Denied
    • Total Posts : 9297
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 06:55:54 (permalink)
    +1 (1)
    fotios
    a) GAIN is a decimal value from 1000d - 65000d that I apply on the calculation and is not defined as a variable.
    Apparently is a Uint type number.
    b) A_UINT can get values from 0d to 65535d.

    As GAIN is not a variable, then it must be a constant literal.
     
    "For GAIN values from 32767 and below" it is a 16-bit integer, so the first multiplication A_UINT * GAIN will be performed in 16-bit math and can overflow as NK said.
     
    "For GAIN values from 32768 and above" it is a 32-bit integer, the first multiplication will be performed in 32-bit math.
     
    That is the C Standard on un-suffixed constant literal. ;)  So append the suffix uL to the GAIN literal.
     
    #6
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 12:00:36 (permalink)
    0
    Thanks a lot to all for the suggestions.
    I use a different calculation method to avoid the division. I make the division on the calculator and then I place the result in the multiplication. It is described in my previous post.
    Actually, I try to calibrate an ATM90E32AS energy monitor which off all registers are 16-bit wide except the Power registers which are 32-bit signed (2's complement).
    The GAIN literal must be calculated for 3 Voltage and 3 Current inputs and then be registered in 6 registers of 16-bit, permanently. My problem is that the GAIN exceeds in most cases the 32768d and I'm wondering if is registered erroneously. To explain, let's say GAIN = 50313d = 0xC489. If we register the 0xC489 to a 16-bit register results in -15223d??? Only in a 32-bit register could result in 50313d. I tried these calculations on Windows calculator and you cannot write 50313d in Word format. If you write C489h in Word format results in -15223d. I don't know if I'm missing something.      

    Fotis
    #7
    1and0
    Access is Denied
    • Total Posts : 9297
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 12:10:25 (permalink)
    +1 (1)
    #define GAIN 50313        // this is a 32-bit integer
    #define GAIN 32767        // this is a 16-bit integer
    #define GAIN 32767uL      // this is a 32-bit integer

     
    #8
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/05 23:42:56 (permalink)
    0
    1and0
    #define GAIN 50313        // this is a 32-bit integer
     
    #define GAIN 32767        // this is a 16-bit integer
     
    #define GAIN 32767uL      // this is a 32-bit integer
     

     


    Thanks a lot for the reply.
    However, in ATM90E32AS datasheet, the default value after reset of e.g. register UgainA = 0x8000.
    If the register is 16-bit, then results in 8000h = -32768d.
    Unless I'm missing something. That is, the registers are 32-bit wide and is not clarified within datasheet!      

    Fotis
    #9
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 00:15:43 (permalink)
    0
    In the application datasheet there is a calculation example for the UgainA register:
    "The register UgainA can be set to 58395d = E41Bh".
    For a UINT type variable that is OK, but for a 16-bit register, it makes: E41Bh = -7141d.
    I'm really confused. 

    Fotis
    #10
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 00:41:54 (permalink)
    0
    A "16 bit register" can hold a 16 bit value.
    That can be regarded either as a signed value or an unsigned value.
    The only confusion is in your head.
    Stop trying to interpret unsigned values as signed values.
     

    Nearly there...
    #11
    NKurzman
    A Guy on the Net
    • Total Posts : 17499
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 01:42:16 (permalink)
    +1 (1)
    A 16 bit unsigned value is 16 bits.
    A 16 bit signed value is effectively 15 bits plus the sign. If you are reading data from registers you most store them in the type of variable the register is.

    Example. 0xFFFF stored as 16 bit unsigned it is 65535. Stored as 16 bit signed it is -1.

    And the convention is all caps for constants.
    And not all caps for variables. It makes your code easier to read
    #12
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 03:18:31 (permalink)
    0
    NKurzman
    A 16 bit unsigned value is 16 bits.
    A 16 bit signed value is effectively 15 bits plus the sign. If you are reading data from registers you most store them in the type of variable the register is.

    Example. 0xFFFF stored as 16 bit unsigned it is 65535. Stored as 16 bit signed it is -1.

    And the convention is all caps for constants.
    And not all caps for variables. It makes your code easier to read

    Thanks, teacher!
    I know from maths but I... fear for mistakes a bitSmile
     
    So, what makes sense is not the MISO 16 bits from the slave ATM90E32, but how are registered by the master P16F18877. If the reception variable of the master is of UINT type, then a 65535d will be stored as 65535d. While, if the reception variable is of INT type, the 65535d will be stored as -1d.
    So, the juice of all the above posts is: every MISO or MOSI word of the slave ATM90 is of UINT type so take care for the variables of your master P16F18877, as each SEND word will be interpreted by the slave as UINT type and each GET word must be interpreted as UINT type by the master.   
    Thanks a lot for the detailed lesson.          
    post edited by fotios - 2019/04/06 03:29:55

    Fotis
    #13
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 12:27:08 (permalink)
    0
    Finally the solution is this: A_FLP = (A_UINT * 32767.0 * 0.001) / 32768.0
    This calculation provides correct results for printing on LCD.
    The small detail is that both literals should be written with ".0" at the end. In this way, both are taken as floating point numbers and the division is executed without errors.
    Thanks a lot
     

    Fotis
    #14
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 13:38:23 (permalink)
    0
    qhb
    Does it make a difference if you change it to
    A_FLP = (A_UINT * GAIN * 0.001) / 32768.0



    If you had pointed out that, the GAIN literal should be also written with ".0" at the end, you could save me from the beginning.   
    Thanks a lot



    Fotis
    #15
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 15:18:54 (permalink)
    0
    You only mentioned a value for GAIN, you didn't show the actual code defining it in the first post.
     
     

    Nearly there...
    #16
    pcbbc
    Super Member
    • Total Posts : 1099
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 16:33:35 (permalink)
    0
    fotiosIf you had pointed out that, the GAIN literal should be also written with ".0" at the end, you could save me from the beginning.   Thanks a lot
    If you had posted your real code in your first post, instead of pseudocode, then you could have saved us guessing.
    Thanks a lot.
    #17
    fotios
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/04/25 14:09:58
    • Location: GREECE
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 23:05:55 (permalink)
    0
    pcbbc
    fotiosIf you had pointed out that, the GAIN literal should be also written with ".0" at the end, you could save me from the beginning.   Thanks a lot
    If you had posted your real code in your first post, instead of pseudocode, then you could have saved us guessing.
    Thanks a lot.

    You are welcome.
    However, for my common sense, when a bug lies within an equation I think there is no need for a whole code upload to locate it. Because it is a matter of maths rather than of code syntax.
    The proof for that is that qhb perceived the bug from the beginning, i.e. the floating point numbers.
    As I told you from the beginning, I'm not an expert like you in C. I know to write code in C and I know from maths. I simply suffer from the structure of C.       
    Finally, the member of MatrixTSL medelec35 gave me the correct advice. 
    I quote his post:
    "Hi Fotis one important thing to remember is :
    A value in a calculation involving floats e.g 32768 are treated as integers. 
    You need to cast it to a float by adding a real portion i.e always as .0 at the end.
    So I would do:  A_FLP = (A_UINT * 32767.0 * 0.001) / 32768.0".
     
    By anyway, what matters is your kindness to reply in my posts, and Thank You A Lot for that Smile: Smile
     
    Thanks
    Regards
    Fotis 
     

    Fotis
    #18
    1and0
    Access is Denied
    • Total Posts : 9297
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: LCD display prints erroneously 2019/04/06 23:20:07 (permalink)
    0
    fotios
    So I would do:  A_FLP = (A_UINT * 32767.0 * 0.001) / 32768.0".

    That takes one floating point multiplication and one floating point division. A more efficient way is
    A_FLP = (A_UINT * 32767uL) / 32768000.0;

    which will take a long integer multiplication instead.
     
    Edit: Or better yet, combine the literals
    A_FLP = A_UINT * (32767.0 / 32768000.0);

    or
    A_FLP = A_UINT * (32767.0 * 0.001 / 32768.0);

    which takes only one floating point multiplication and NO division.
     
    post edited by 1and0 - 2019/04/06 23:34:21
    #19
    pcbbc
    Super Member
    • Total Posts : 1099
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: LCD display prints erroneously 2019/04/07 01:08:15 (permalink)
    0
    At which point you realise, for A_UINT integers in the range 1 to 32,768, and when only printing the result to 3 decimal places, the result is practically equivalent to:
    A_UINT * 0.001

    Where exactly are your A_UINT values coming from?
    I suspect that worrying about 1 part in 32,768 and accuracy at the fourth decimal place is probably neither here nor there in the grand scheme of things.
    #20
    Jump to:
    © 2019 APG vNext Commercial Version 4.5