Need help with decimal point method
Don M
Posts: 1,653
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:
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:
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
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
- 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.
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.
So the question is how would you get the VFD to mimic this type of action on PST 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
Which method are you referring to? decf, decn or decz ?
-Phil
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.
That's assuming that vfd has a str method.
-Phil
Now to add a decimal point- looks like I could try one of your other methods that uses a decimal point....