Setting the width of a floating point number
Hi Everyone,
I'm having a little trouble with a program that involves a rotary encoder and an OLED (SSD1331) that allows the user to select a number displayed on the screen. My issue is that the "print" command that sends that number, as chosen by the rotary encoder, requires the specification of the length of the string being sent (floating point converted to string previous to the command), and my numbers have varying lengths. The minimum length is one character and the max is five. I tried using the simple numbers method that allows the specification of a width that then pads the output with spaces on the OLED screen, but when I used it, it seemed to return the address instead of the value.
Does anyone have any ideas for how I can get the padding/width setting that I need?
{{ *OLED Test 2 *Z. Schulze et. al. *6/18/21 * }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 CLK_FREQ = (_clkmode >> 6) * _xinfreq MS_001 = CLK_FREQ / 1_000 RST = 15 'OLED pins DC = 16 CS = 17 CLK_oled = 18 DIN = 19 clk_enc = 28 'Encoder pins dt = 29 btn = 11 LED0 = 3 'LED pins LED1 = 4 LED2 = 5 LED3 = 6 LED4 = 7 LED5 = 8 LED6 = 9 LED7 = 10 LE = 2 'latch pin OBJ OLED : "OLED_AsmFast v0.5 Driver" enk : "jm_encoder_1x" SPI : "SPI_Spin" f : "Float32" fs : "FloatString" int : "string.integer" sn : "Simple_Numbers" n : "Numbers" VAR long Data long Atten long DataX long AttenX PUB OLED_Test OLED.Init(CS,DC,DIN,CLK_oled,RST) enk.Start(clk_enc, dt, btn, true, 1, 0, 127) SPI.Start(15000, 1) f.Start dira[LED7..LED0]~~ wait_for_state(btn, 0, 50) OLED.clearDisplay OLED.AutoUpdateOff OLED.write1x6String(String("Manual"),6,0,0,OLED#Yellow,OLED#BLUE) OLED.write1x6String(String("Mode"),4,0,32,OLED#Yellow,OLED#BLUE) delay(500) repeat Data := enk.value Atten := f.FDiv(Data, 4) 'AttenX := sn.decf(Atten, 5) issue with this was that it seemed to return the address instead of the value AttenX := fs.FloatToString(Atten) ifnot DataX == Data OLED.clearDisplay OLED.write1x6String(AttenX,5,0,0,OLED#Yellow,OLED#BLUE) if ChkBtnPulse(btn, 0, 1) LOW1(LE) SPI.SHIFTOUT(0, 1, SPI#LSBFIRST, 8, Data) HIGH1(LE) LOW1(LE) outa[LED0] := (Data & %00000001) outa[LED1] := (Data & %00000010) >> 1 outa[LED2] := (Data & %00000100) >> 2 outa[LED3] := (Data & %00001000) >> 3 outa[LED4] := (Data & %00010000) >> 4 outa[LED5] := (Data & %00100000) >> 5 outa[LED6] := (Data & %01000000) >> 6 outa[LED7] := (Data & %10000000) >> 7 DataX := Data PUB wait_for_state(pin, state, ms) : statems | t t := cnt repeat 'enter into infinite repeat loop waitcnt(t += MS_001) 'delay for the number of clicks in one millisecond from the current count if (ina[pin] == state) 'test to see if the state of pin is equal to the state variable if (++statems == ms) 'preincrements variable statems by 1 each pass through and continues to repeat 'until statems reaches the number assigned to ms, and then the return occurs return 'exit repeat loop and method, and go to the next line in "parent method" else statems := 0 'if state of pin is not equal to state variable, then pin state not equal to state 'variable for specified amount of time, and infinite loop is continued. PUB delay(ms) waitcnt(clkfreq/1000*ms + CNT) PUB HIGH1(Pin) dira[Pin]~~ outa[Pin]~~ PUB LOW1(Pin) dira[Pin]~~ outa[Pin]~ PUB ChkBtnHoldTime(pin, activeState, mSecDelay, mSecMax) : delta | time1, time2, mSec, waitTicks, maxTicks {{ This function checks to see if a button is pressed and then times the press to determine how long the button was held down. It returns the time in milliseconds. The time returned INCLUDES the requested settle delay which must be at least 1ms. If active state is not held for at least the settle delay time then the fuction treats it as if no press occured. It blocks execution until the the button is released or mSecMax is reached if it is greater than 0. Parameters: pin - The I/O pin to watch for the button press. activeState - The digital state that is considered a button press [0 or 1]. mSecDelay - The debounce or settle time to ignore transitions during, defaults to 1 millisecond. mSecMax - The maximum time to allow the button to be held for. After that time we force a return. A zero here inidicates no timeout, the function will not return until the button is released. }} if mSecDelay < 1 'If the delay is less than 1 mSec then increase it to 1. mSecDelay := 1 delta := 0 mSec := clkfreq/1000 'Number of clock ticks per millisecond. waitTicks := mSec * mSecDelay 'Number of clock ticks for bounce settleing. maxTicks := mSec * mSecMax 'Number of clock ticks for hold timeout. 'If a timeout was requested: if maxTicks > 0 time1 := cnt 'Record the start time. if ina[pin] == activeState 'If the pin was on when we checked waitcnt(waitTicks + cnt) ' wait for the requested settle delay if ina[pin] <> activeState ' Is it still in the requested state? return ' If not return while delta is 0 else repeat until cnt > time1 + maxTicks ' Otherwise loop until the timeout is reached if ina[pin] <> activeState ' If the button is released first time2 := cnt ' Record the time. delta := ((time2 - time1))/mSec ' Calculate the delta in milliseconds. return ' Return now. time2 := cnt ' When the loop exits calculate the delta. delta := ((time2 - time1))/mSec return 'If no timeout was requested: if maxTicks == 0 time1 := cnt 'Record the start time. if ina[pin] == activeState 'If the pin was on when we checked waitcnt(waitTicks + cnt) ' wait for the requested settle delay if ina[pin] <> activeState ' Is it still in the requested state? return ' If not exit while delta = 0 else repeat until ina[pin] <> activeState ' Repeat until the button is released. time2 := cnt ' When the loop exits calculate the delta. delta := ((time2 - time1))/mSec return PUB ChkBtnPulse(pin, activeState, mSecDelay) : wasPressed | waitTicks, mSec {{ This function will return true if the button is held active for the designated delay time and then released. If this is called in a loop it will return a press only when the button has been pressed and released. Other execution is blocked while the button is held down so it will not pruduce addtional presses if the user is holding the button down. Parameters: Pin - I/O pin to check activeState - The digital state that is considered a button press mSecDelay - The debounce or settle time in milliseconds for a valid press. }} if mSecDelay < 1 'If the delay is less than 1 millisecond increase it to 1 mSecDelay := 1 mSec := clkfreq/1000 'Clock ticks per millisecond waitTicks := mSec * mSecDelay if ina[pin] == activeState 'If the pin is in the desired state. waitcnt(waitTicks + cnt) 'Wait the requested amount of settle time. if ina[pin] == activeState 'Is it still in the desired state? repeat while ina[pin] == activeState wasPressed := 1 else wasPressed := 0 'Transient as defined by the request so we won't count it.
Thanks for taking a look.
Zach
Comments
Simple_Numbers does not handle floating-point. When you call decf on a floating-point number, it treats the value that it sees as a signed 32-bit integer instead.
-Phil
You can do like this:
A:=F.FFloat(B)
C:=(FS.Setprecision(4))
C:=(FS.FloatoString(F.Fdiv(Data,4)))
lcd.str(C)
(I'm using an LCD)
Hi @DigitalBob ,
Thank you for the suggestion. I ended up figuring it out by using the FormatToString method in a different version of the FloatString object. This version that I found on OBEX is different than the one that came with the Propeller Tool's library.
Thanks,
Zach