Displaying Fractional Inches (eg 3-11/16)
I am building a measuring system for a band saw mill with a stamp counting pulses on a hall switch . Lets say the stamp counts to 1275, how would I display it as 12-3/4 inches? with the limited math it has available?
Thanks,
Lawrence
Thanks,
Lawrence

Comments
You represent fractions as integers (like 1275 for 12.75 inches). You can display this with or without the decimal point. If you really want to display fractional inches, you might want to store your data internally in terms of fractional inches and you have to decide what your basic unit is. For example, you might keep all your data in terms of 1/16th of an inch, so 3-11/16 comes out to 3 x 16 + 11 = 59. You can add and subtract in these units and multiply and divide by integer values (like 2 or 3). When it's time to display the value, you divide by the fraction divisor (16) to display the whole inches and take the remainder (modulus) to get the number of 1/16ths of an inch to display. If you want to get fancy and figure out the smallest denominator, you can just reduce the fraction by dividing numerator and denominator (initially 16) by 2 if the numerator is even (if the remainder of the division by 2 is 0) repeatedly until the numerator is odd (checking for zero initially).
There are ways to do the same with decimal fractions. If you keep your data in hundreths as you've shown, you can have a table in EEPROM that contains the upper limit for a decimal fraction part and the characters to display. For quarters, this could be:
table DATA 75,"3/4",0 DATA 50,"1/2",0 DATA 25,"1/4",0 DATA 0You'd go through this table, checking the fractional part against the first byte of each entry. If it's greater or equal to the first byte, you'd display the string starting at the 2nd byte. If not, you'd skip over the string and it's zero delimiter and check the next entry. You'd need to check for zero before searching this table because that's a special case (with no fraction). Clearly, if you want more precision (like 3 decimal digits), you'd have to use a word for the numeric part of the entry rather than a byte value. If all of your measurements are positive, you could represent up to 65 inches with 3 decimal places.
For example (untested and probably horribly inefficent):
counts var word numerator var byte denominator var byte i var byte counts = 1275 numerator = counts // 100 if numerator > 0 then denominator = 100 for i = numerator to 1 step -1 if (numerator // i = 0) AND (denominator // i = 0) then numerator = numerator / i denominator = denominator / i exit endif next debug #counts / 100, "-", #numerator, "/", #denominator else debug #counts / 100 endifHarrison
Post Edited (Harrison.) : 3/16/2007 5:05:07 AM GMT
The above does not round off. It rounds down, so 99/100 becomes 15/16. Maybe the mechanism is set already with the offset. Otherwise it could be done in the math. The operation (t=NCD (n REV 4)) is a trick. Suppose x=1275, so n=12 (meaning 12/16). In binary the numerator is %1100, and the REV4 turns that into %0011. The NCD finds the highest bit that is a one, in this case t=2. So then it shifts both the numerator and denominator two bits right, so 12/16 becomes 3/4.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
x VAR Word ' for example 1275 p VAR Byte ' e.g. 12, the integer part n VAR Byte ' e.g. 3, the numerator d VAR Byte ' e.g. 4, the denominator, either 2,4,8 or 16 t VAR Nib ' a scratch variable i VAR Byte DO x = x + 1 p = x/100 ' integer part n = x//100 * 16 / 100 ' fractional numerator, implied denominator of 16 d = 16 FOR i = 0 TO 2 t = n / 2 'test to see if n is divisible by 2 t = t * 2 IF (t = n) THEN n = n / 2 'if it is, divide both n and d by two d = d / 2 ELSE GOSUB PrntResult 'if not, we're done! ENDIF NEXT ' stupid FOR NEXT, 'cause I couldn't get DO WHILE working. PrntResult: PAUSE 50 DEBUG CLS, DEC p, "-", DEC n, "/", DEC d, 34, CR LOOP▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Also another one I have been playing with is trying to get this to work with signed negative numbers. I thought I could get it to work by doing something like adding 4000 to x and subtracting 40 from p and using SDEC, but it did not work. Is there a way to divide signed negative numbers on a stamp at all?
Thanks a Million!
Lawrence Shafer
Hmmm. It seems to work okay for me. Enclose the whole routine in DO and LOOP so you can enter different values quickly in succession.
I've attached a modified program that steps through a sequence of values from 1.27 down to -1.28 (yes, negative) and displays the fractional equivalent. Here is the start of that sequence as displayed. 127 is the Stamp's internal integer representation of decimal 1.27.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
' ========================================================================= ' ' This code runs on the stamp connected to the VFD. ' ' {$STAMP BS2} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[noparse][[/noparse] I/O Definitions ]------------------------------------------------- VFD PIN 15 ' VFD Serial I/O Pin SI PIN 0 ' serial input FC PIN 1 ' flow control pin ' -----[noparse][[/noparse] Constants ]------------------------------------------------------- Baud CON 6 ' 38.4 Kbps (BS2) ' These are constants for common control characters on the display. ' Remember, some are already defined in the editor, like CR and LF. BS CON $08 ' Back Space HT CON $09 ' Horizontal Tab HOM CON $0B ' Home Position CLR CON $0C ' Display Clear ' -----[noparse][[/noparse] Variables ]------------------------------------------------------- index VAR Word ' Main Counter Variable dispData VAR Byte ' Display Data inches VAR Word result VAR Word last VAR Word swap VAR Bit x VAR Word ' for example 1275 p VAR Byte ' e.g. 12, the integer part n VAR Byte ' e.g. 3, the numerator d VAR Byte ' e.g. 4, the denominator, either 2,4,8 or 16 t VAR Nib ' a scratch variable i VAR Byte z VAR Word z0 VAR Word z1 VAR Word ' -----[noparse][[/noparse] Initialization ]-------------------------------------------------- HIGH VFD ' Initialize I/O Pin PAUSE 200 ' Allow Time To Settle ' This command resets the display settings to deafult values, but the input ' buffer is not affected (contents remain). SEROUT VFD, Baud, [noparse][[/noparse]$1B, $40, $0C] ' Initialize Display PAUSE 200 ' Allow Time To Settle ' You need to set this if you plan to write to the non-visible display ' memory. Write Screen Mode Select: 0=Display Screen, 1=All Screen SEROUT VFD, Baud, [noparse][[/noparse]$1F, $28, $77, $10, $01] ' This digit is the one to change ^^ ' -----[noparse][[/noparse] Program Code ]---------------------------------------------------- Start: GOSUB Splash ' GOSUB Mag_2XY GOSUB Read_Inputs GOSUB Print_Result Main: DO GOSUB Get_Reading GOSUB Read_Inputs GOSUB Print_Result LOOP ' Loop Forever ' -----[noparse][[/noparse] Subroutines ]----------------------------------------------------- Mag_2XY: SEROUT VFD, Baud, [noparse][[/noparse]$1F, $28, $67, $40, $02, $02] RETURN ' ------------------------------------------------------------------------- Get_Reading: SERIN 1, 17197, 1000, No_Connection, [noparse][[/noparse]WAIT("XZ"),sDEC x] ' receive position from other stamp RETURN ' ------------------------------------------------------------------------- No_Connection: PAUSE 100 SEROUT VFD, Baud, [noparse][[/noparse]CLR, "ERROR 83,"] SEROUT VFD, Baud, [noparse][[/noparse]CR, LF, "No Connection -"] PAUSE 3000 SEROUT VFD, Baud, [noparse][[/noparse]CR, "To Sensor Module"] PAUSE 3000 SEROUT VFD, Baud, [noparse][[/noparse]CLR] GOSUB Main RETURN ' ------------------------------------------------------------------------- Read_Inputs: INPUT 4 ' read swap switch INPUT 7 ' read zero switch IF (IN7 = 1) THEN ' if pin 7 is high, zero z (relative) z = x ENDIF IF (IN4 = 0) THEN 'swap z1 and z0 to swap positions on display z0 = z z1 = 0 ELSE z0 = 0 z1 = z ENDIF RETURN ' ------------------------------------------------------------------------- Conv_to_Inches: last = x ' save x so we can corectly calculate the second number on the display next time. IF (x.BIT15 = 1) THEN ' convert negetive signed to positive else leave it alone. We need to have singed numbers x = x - (x * 2) ' for the zeroing function to work properly, but the conversion below will not work with SDEC, ENDIF ' so we have this strange little trick here to make it all work together. p = x/100 ' integer part n = x//100 * 16 / 100 ' fractional numerator, implied denominator of 16 ' at this point we want to shift the binary numerator and denominator right ' by the same amount TO get rid of zeros in the lsbs. t = 4 - NCD (n REV 4) ' find how many places to shift n = n >> t ' make fraction in lowest terms, e.g., 12/16 will become 3/4 d = 16 >> t IF (n = 0) THEN ' zero the denominator if the numerator is zero. d = 0 ENDIF x = last ' restore x to it's SDEC state. RETURN ' ------------------------------------------------------------------------- Print_Result: x = x - z0 GOSUB Conv_to_Inches x = x + z0 SEROUT VFD, Baud, [noparse][[/noparse]HOM, $1F, $28, $67, $40, $01, $01, $1F, $28, $67, $40, $02, $02, DEC2 p, $1F, $28, $67, $40, $01, $01, DEC n, "/", DEC d, " ", " "] x = x - z1 GOSUB Conv_to_Inches x = x + z1 SEROUT VFD, Baud, [noparse][[/noparse]CR, LF, HT, HT, HT, HT, HT, HT, " ", DEC p, "-", DEC n, "/", DEC d, " "] RETURN ' ------------------------------------------------------------------------- Splash: ' -----[noparse][[/noparse] EEPROM Data ]------------------------------ ShaferLabs DATA %11111111, %11111111, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00011100, %00000100, %00100010, %00000010, %01000001, %00000010, %01000001, %00000010, %01000000, %10000010, %01000000, %10000010, %01000000, %01000010, %01000000, %01000100, %00100000, %00111000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %01111111, %11110000, %00000010, %00000000, %00000010, %00000000, %00000010, %00000000, %00000010, %00000000, %00000010, %00000000, %00000010, %00000000, %00000010, %00000000, %00000010, %00000000, %01111111, %11110000, %00000000, %00100000, %00000000, %01000000, %00000000, %10000000, %00000001, %00000000, %00000010, %00000000, %00000110, %00000000, %00001010, %00000000, %00010010, %00000000, %00100010, %00000000, %01111111, %11110000, %00000000, %00000000, %00000000, %00000000, %01111111, %11110000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %01111111, %11110000, %01000010, %00010000, %01000010, %00010000, %01000010, %00010000, %01000010, %00010000, %01000010, %00010000, %01000010, %00010000, %01000000, %00010000, %00000000, %00000000, %00000000, %00000000, %01111111, %11110000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %01000010, %00000000, %00100101, %00000000, %00011000, %11110000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %01101010, %11000100, %01001010, %10101010, %01001010, %10100010, %01001110, %11000100, %01001010, %10101000, %01001010, %10101010, %01000100, %11000100, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %11111111, %11111111 Dragon DATA %00000000, %00000000, %00011100, %00000000, %00001101, %00000000, %00000101, %10000000, %00000101, %10000000, %00001101, %10000000, %00001101, %10000000, %00011011, %10000000, %00111111, %10000000, %00101111, %10000000, %00101111, %11000000, %00111111, %11100000, %00111111, %11100000, %00011111, %11110000, %00000111, %11111000, %00000001, %11111000, %00011000, %11111100, %00111110, %01111100, %01111111, %11111110, %01111111, %11111110, %11111100, %01111110, %11111000, %11111110, %11110001, %11111110, %11100011, %11111110, %11100111, %11111110, %11001111, %11111100, %10011111, %11111000, %10111111, %11110000, %00111111, %11100000, %00111111, %11000000, %00111111, %11000000, %00111111, %11000000, %00011111, %11100000, %00001111, %11110000, %00000111, %11111000, %00000011, %11111000, %00000001, %11111100, %00011000, %11111100, %00111110, %01111110, %01111111, %11111110, %01111100, %11111110, %01111000, %01111110, %01110000, %11111110, %01100001, %11111110, %01100011, %11111110, %01000111, %11111100, %01001111, %11111000, %00011111, %11110000, %00111111, %11100000, %00111111, %11000000, %00111111, %11000000, %00111111, %11000000, %00011111, %11000000, %00001111, %11100000, %00000111, %11110000, %00000011, %11111000, %00000001, %11111100, %00001100, %11111100, %00011111, %11111110, %00111110, %01111110, %00111100, %01111110, %00111000, %01111110, %00110000, %11111110, %00100001, %11111110, %00100011, %11111110, %00000111, %11111100, %00001111, %11111000, %00011111, %11110000, %00011111, %11100000, %00011111, %11100000, %00011111, %11100000, %00001111, %11100000, %00000111, %11110000, %00000011, %11111000, %00000001, %11111100, %00000000, %11111110, %00000000, %01111110, %00000000, %01111110, %00000000, %01111110, %00000000, %01111110, %00000000, %11111110, %00000001, %11111110, %00000011, %11111100, %00000111, %11111000, %00011111, %11100000, %00011111, %11100000, %00011111, %11100000, %00001111, %11100000, %00000111, %11100000, %00000011, %11110000, %00000001, %11111000, %00000000, %11111100, %00000000, %01111100, %00000000, %01111100, %00000000, %01111100, %00000000, %11111100, %00000001, %11111000, %00000011, %11110000, %00000111, %11100000, %00001111, %11000000, %00001111, %11000000, %00000111, %11100000, %00000011, %11110000, %00000001, %11110000, %00000000, %11111000, %00000000, %11110000, %00000001, %11100000, %00000011, %11000000, %00000011, %11000000, %00000001, %10000000, %00000001, %10000000, %00000000, %00000000 ' -----[noparse][[/noparse] Initialization ]-------------------------------------------------- HIGH VFD ' Initialize I/O Pin PAUSE 200 ' Allow Time To Settle SEROUT VFD, Baud, [noparse][[/noparse]$1B, $40, $0C] ' Initialize Display PAUSE 500 ' Allow Time To Settle ' -----[noparse][[/noparse] Program Code ]---------------------------------------------------- SplashMain: ' Write Screen Mode Select: 0=Display Screen, 1=All Screen SEROUT VFD, Baud, [noparse][[/noparse]$1F, $28, $77, $10, $01] ' Specify Real-Time Bit-Image Display: 224 Pixels X 16 Pixels SEROUT VFD, Baud, [noparse][[/noparse]$1F, $28, $66, $11, 224, 0, 02, 0, 1] FOR index = 0 TO 447 READ ShaferLabs + index, dispData ' EEPROM Data For Bitmap Display SEROUT VFD, Baud, [noparse][[/noparse]dispData] ' Write To VFD memory NEXT PAUSE 4000 ' Wait 2 Second ' Scroll Display 112 Pixels Left SEROUT VFD, Baud, [noparse][[/noparse]$1F, $28, $61, $10, 2, 0, 224, 0, 1] PAUSE 2000 ' Allow Time To Complete SEROUT VFD, Baud, [noparse][[/noparse]CLR] PAUSE 2500 SEROUT VFD, Baud, [noparse][[/noparse]" Loading Saved", CR, LF, " Settings...."] ' Wait for other stamp to initialize and load last position + look really cool! PAUSE 1500 SEROUT VFD, Baud, [noparse][[/noparse]CLR] RETURN' ' This code runs on the satmp connected to the hall, zero, and direction sensors ' ' {$STAMP BS2} ' {$PBASIC 2.5} eeval VAR Word xctr VAR Word ' Holds the #transitions on P8. xprev VAR Bit ' Holds the previous state of P8. xcurr VAR Bit ' Holds the current state of P8.. INIT: xctr = 0 ' Initialize all variables. xcurr = IN8 xprev = xcurr READ 1, Word xctr START: xcurr = IN8 ' Read input pins. IF (xcurr = 1) THEN HIGH 7 ' blink LED with the hall switch to indicate what's going on. ELSE LOW 7 ENDIF IF (IN9 = 1) THEN ' detect dir of movement. xctr = xctr + (xcurr ^ xprev & xprev) ' Calculate and add transitions only. ELSE xctr = xctr - (xcurr ^ xprev & xprev) ' Calculate and subtract transitions only. ENDIF xprev = xcurr ' Update the 'prev' registers. SEROUT 1, 17197, [noparse][[/noparse]"XZ",SDEC xctr] IF (IN11 = 0) THEN Power_Down ' see if power has been removed and save position IF IN10 = 0 THEN START ' If P10 is grounded xctr = 0 ' then clear the count regisers. GOTO START ' Repeat forever. Power_Down: READ 1, Word eeval ' read eeprom IF (eeval = xctr) THEN ' if eeprom matches curr position, then dont write PULSOUT 7, 200 ' indicate on LED that Power_Down has been executed GOTO Dont_Write ELSE ' else write position to eeprom WRITE 1, Word xctr PULSOUT 7, 200 ' indicate on LED that Power_Down has been executed ENDIF Dont_Write: GOTO START