Shop OBEX P1 Docs P2 Docs Learn Events
Need help with decimal point method — Parallax Forums

Need help with decimal point method

Don MDon M Posts: 1,653
edited 2011-06-23 12:09 in Propeller 1
I want to be able to display a number on a VFD with 4 decimal places ( 0.0000 ). I have downloaded and installed DecimalPlace by Tom Smuts ( http://obex.parallax.com/objects/412/ ) into Full Duplex Serial and have gotten that to work very succesfully when displaying my data on PST.

So next I wanted to try and display this same number format on my VFD. Using the existing DEC method from the display driver I can display a number on the VFD and as it counts up it goes like this:

1
2
3
.... (dots just denote continuation)
9
10
...
99
100
...
999
1000

So as you can see the digits are left justified and grow to the right. The problem is as they count down and should shrink back to the left, the last number in the right most column stays at 9 as the columns to the left continue to count down until the next column to the left reaches 9 then it stays on 9 as the remaining columns to the left continue to count down etc. I know it sounds confusing but say if I count up to 9999 and then count back down to 0 I am left with 0999 on the display even though the actual count is 0. The reason I know this is PST shows the numbers counting up and down correctly simultaneous to the VFD counting (displaying) incorrectly.

Here is the part of the code that displays the numbers in both PST and on the VFD. The way it's set up in the example below I get the 0.000 format on PST which is what I want and get 0 on the VFD and it counts on the VFD as I explained above:
 repeat
  
    oldlevel := newlevel                                        ' setup to detect change 
    term.tx(HOME)                                               ' display it
    'vfd.pos(0,0)
    vfd.SetRowCol(0, 0)
    'vfd.str(string("Position: "))
    vfd.PrintStr(string("Position: "))
    term.str(string("Position: "))
    newlevel *= 3515                                            
    newlevel /= 100
    term.decdp(newlevel, 4)   '<<< This works fine in PST
    vfd.SetPos(10)
    vfd.dec(newlevel)
    'vfd.decdp(newlevel, 4)
    term.tx(CLREOL)

If I comment out vfd.dec(newlevel) and uncomment vfd.decdp(newlevel, 4) to try and get the VFD to display the 0.0000 format as on the PST, the VFD is just blank where the numbers are to show.

Here is part of the VFD display driver code that deals with the methods I have called from my code above:
PUB DEC (VALUE) | TEMP

' I copied this routine from LCD_16x2_4Bit_don in order to display numbers.
' It seems to work somewhat ok but need to figure out how to add decimal place
' control.

  IF (VALUE < 0)
    -VALUE
    PrintChr("-")

  TEMP := 1_000_000_000

  REPEAT 10
    IF (VALUE => TEMP)
      PrintChr(VALUE / TEMP + "0")
      VALUE //= TEMP
      RESULT~~
    ELSEIF (RESULT OR TEMP == 1)
      PrintChr("0")
    TEMP /= 10

PUB DecDP(value, dp) | index, divisor, numDigits

' I also added this routine for decimal place control but it doesn't work 6/22/11

'' Print a number with a decimal point to a specified number of places
'' Author: Tom Smuts
' value is the number to be printed.
' dp is the number of digits to the right of the decimal point (0 <= dp <= 10)
'--------------------------------------------------------------------------------------------  
  if value < 0                  ' Test to see if negative
    PrintChr("-")                     ' If so, print the negative sign
    -value                      ' Change value to positive
'--------------------------------------------------------------------------------------------
  Bytefill(@dp_buffer, 0, 16)   ' Clear buffer before use
  index := 0                    ' initialize index
'--------------------------------------------------------------------------------------------    
  divisor := 1_000_000_000      ' Max pos is 2_147_483_647, max neg is -2_147_483_648
  repeat 10                     ' Parse through all ten possible digits
    if value => divisor         ' Detects 1st instance of (value => divisor)
      dp_buffer[index++] := (value / divisor + "0") ' ASCII char is stored in dp_buffer[index]
      value //= divisor         ' Modulus divide, returns 32 bit remainder
      result~~                  ' Result starts as 0 (False) and is changed to -1 (True)
                                ' when the 1st non-zero digit is reached. Stays at -1
                                ' through the remainder of the repeat loop
    elseif result OR divisor == 1   ' 1st non-zero digit or last time through repeat loop
      dp_buffer[index++] := ("0") ' ASCII "0" is stored in dp_buffer[index]
    divisor /= 10               ' Divide divisor by 10
'--------------------------------------------------------------------------------------------
  dp #>= 0                      ' Limit minimum dp value to 0
  dp <#= 10                     ' Limit maximum dp value to 10
  
  if (dp > 0)                   ' No action required if dp = 0
    numDigits := index          ' Calculate the number of digits in the string

    if (dp < numDigits)         ' When True, no 0 insertion req'd, only a decimal point

      repeat dp                 ' Shift all bytes that need shifting to the right one place
        dp_buffer[index--] := dp_buffer[index - 1]      ' Shift one place to the right     
      dp_buffer[index] := (".") ' Insert decimal point

    else                        ' 0 insertion req'd in addition to decimal point

      repeat numDigits          ' Shift all bytes that need shifting to the right
        dp_buffer[index-- + dp - numDigits + 1] := dp_buffer[index - 1]
      repeat (dp - numDigits)           ' Insert zeros as req'd
        dp_buffer[index--  + dp - numDigits + 1] := ("0")             
      dp_buffer[1] := (".")     ' Insert decimal point        
      dp_buffer[0] := ("0")     ' Insert leading "0"
'--------------------------------------------------------------------------------------------
  PrintChr(@dp_buffer)               ' Print number

On the bottom line PrintChr(@dp_buffer) I also tried changing it to dec(@dp_buffer) and that did not work either.

I hope I've explained this so someone might understand what I am trying to do.

Appreciate any help.

Thanks.
Don

Comments

  • kwinnkwinn Posts: 8,697
    edited 2011-06-23 08:13
    Don, it may be that you have 2 separate problems.

    - The first is that your VFD may be a "smart" display that blanks leading 0's to save power. If you have all 0's you get a blank display. There should be a command to turn this feature off. Check the VFD data sheet/manual. It could also be in the spin code.

    - The second problem is that as you count down the number of digits decreases. When you go from 1000 to 999 you go from 4 digits in your string to 3 digits. That means there is a digit left behind on the display. This is not noticeable on PST because you display on a new line every time.
    The simplest way to deal with this is to output the same number of characters every time. Start with a string of blanks (lets say 8 blanks) and then move your string of digits into that string. The ones digit moves to the right most byte in "blanks", the 10's digit moves into the "blanks" byte to the left of the ones digit, etc.Once all the digits have been transferred you output the "blanks" string and then fill it with blanks for the next set of digits.
  • Don MDon M Posts: 1,653
    edited 2011-06-23 08:25
    kwinn wrote: »
    Don, it may be that you have 2 separate problems.

    - The first is that your VFD may be a "smart" display that blanks leading 0's to save power. If you have all 0's you get a blank display. There should be a command to turn this feature off. Check the VFD data sheet/manual. It could also be in the spin code.

    I'll look into that but I am wondering if that is possible because it does display 0 when the program first starts before I start to count up.

    On PST the numbers grow from right to left as they increase in the number of digits. On the VFD it is just the opposite.
    This is not noticeable on PST because you display on a new line every time.

    So the question is how would you get the VFD to mimic this type of action on PST display?
  • kwinnkwinn Posts: 8,697
    edited 2011-06-23 10:32
    It may be that I am not understanding the problem clearly. Can you post the data sheet/manual for the VFD? Does the VFD display ascii characters or is it a simple numeric display?

    As I suggested in the previous post it may be possible to get around this problem by starting with a string of blank characters (lets call it output), copying the characters you want to display into that string, and then outputting it to the VFD.

    For example, you have the string "output" with 8 blanks "bbbbbbbb" (b represents a space character) and you want to display "0.123". Copy the 4 digits and decimal point into the blank string so you get "bb0.123b" and output that string to the VFD. Now you have to fill "output" with 8 blanks before getting the next number to output.

    In many cases it is easier to store all the data you want to display in a string buffer in hub ram and output the entire string to the display. If you have a 16x2 alphanumeric display a 32 byte string can be used to rewrite data to the entire display in one operation. It also makes outputting data from multiple cogs simpler. Each cog stores it's data in a specific hub location and the display routine scans the locations for each cog, converts, formats, and places the data in the proper display buffer locations, and then outputs the entire string to the display.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-06-23 10:49
    Try the attached object. It has a decimal method to right-justify the numbers. (I really should start uploading this stuff to the OBEX.) This object is autodoc-ready, too. You can upload it here to get the documentation.

    -Phil
  • Don MDon M Posts: 1,653
    edited 2011-06-23 11:17
    Phil-

    Which method are you referring to? decf, decn or decz ?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-06-23 11:27
    decn

    -Phil
  • Don MDon M Posts: 1,653
    edited 2011-06-23 11:45
    So to understand how to implement this (sorry for my ignorance here...) -

    1. I include your object in the object list in my main object and I call it simp (simp : "Simple_Numbers_plus")
    2. In my program (newlevel is the variable) I call simp.decn(newlevel, 4) to invoke your object.

    And here is where I get stuck- can I simply then call vfd.dec(newlevel) which is what I had been using to print to VFD to print to VFD display? Does the returned value (or variable?) from your object then become the "new" newlevel or do I have to call it something else? I am not sure what is returned or what to do with it.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-06-23 11:53
    My object returns pointers to strings. So you would do:
    vfd.str(simp.decn(newlevel, 4))
    

    That's assuming that vfd has a str method.

    -Phil
  • Don MDon M Posts: 1,653
    edited 2011-06-23 11:56
    Yes it does. Thanks I'll give this a try.
  • Don MDon M Posts: 1,653
    edited 2011-06-23 12:01
    Hey hey! It works! I learned another trick here from you too- to embed two commands in one statement. Didn't know you could do that.

    Now to add a decimal point- looks like I could try one of your other methods that uses a decimal point....
  • Don MDon M Posts: 1,653
    edited 2011-06-23 12:09
    Phil- Thank you very much! I really appreciate it. I'm marking this as solved.
Sign In or Register to comment.