View previous topic :: View next topic |
Author |
Message |
snipsnip
Joined: 10 Feb 2014 Posts: 74 Location: Melbourne
|
Posted: Sun Feb 16, 2014 10:43 pm Post subject: constrain a variable? |
|
|
hi all,
is there an easy way to set a value range for a variable, ie 100-200 or say 0-255?
If Backlvl < 1 Then Backlvl = 1
If Backlvl > 250 Then Backlvl = 250
I'm using the above method which works, but gets messy if I want to incr or decr in +10 (steps)values,
as the main reason I'm using it is to stop a byte rolling back to 255 when its decremented below 0.
Locate 1 , 1
Lcd " brightness"
Do
Gosub Keypad
Select Case Kpad
Case 0 : Incr Backlvl 'incr fast
Case 1 : Incr Backlvl : Waitms 200 'incr slow
Case 2 : Decr Backlvl : Waitms 200 'decr slow
Case 3 : Decr Backlvl 'decr fast
Case 4 : Exit Do
End Select
Locate 2 , 1
Lcd " " ; Backlvl ; " "
If Backlvl < 1 Then Backlvl = 1
If Backlvl > 250 Then Backlvl = 250
Pwm2b = Backlvl
Loop
Ebacklvl = Backlvl
Incr A
Return
thanks
(BASCOM-AVR version : 2.0.7.7 ) |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Sun Feb 16, 2014 11:02 pm Post subject: |
|
|
If you just want to limit the range, write a sub for that.
First argument could be the value to check, second and third argument min and max. By default values are passed by reference, means the address of the original variable is passed, this way the value can be modified from within the sub.
For min and max use the keyword ByVal, this way you can use constants as arguments.
Usage would be then like:
Code: | LimitValue Backlvl, 1, 250 |
|
|
Back to top |
|
|
Visovian
Joined: 31 Oct 2007 Posts: 584 Location: Czech
|
Posted: Mon Feb 17, 2014 4:41 am Post subject: |
|
|
Quote: | If Backlvl < 1 Then Backlvl = 1
If Backlvl > 250 Then Backlvl = 250
I'm using the above method which works, but gets messy if I want to incr or decr in +10 (steps)values,
as the main reason I'm using it is to stop a byte rolling back to 255 when its decremented below 0. |
You need "Backlvl" to be a signed type. Try
Dim Backlvl as Integer. |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Mon Feb 17, 2014 7:36 am Post subject: |
|
|
Visovian wrote: | You need "Backlvl" to be a signed type. Try
Dim Backlvl as Integer. |
In the example he tests for < 1, which is 0 and sure tests ok also in unsigned variables. So signed ones are unnecessary, as long decrease is not bigger than 1. |
|
Back to top |
|
|
snipsnip
Joined: 10 Feb 2014 Posts: 74 Location: Melbourne
|
Posted: Mon Feb 17, 2014 8:18 am Post subject: |
|
|
MWS wrote: | Visovian wrote: | You need "Backlvl" to be a signed type. Try
Dim Backlvl as Integer. |
In the example he tests for < 1, which is 0 and sure tests ok also in unsigned variables. So signed ones are unnecessary, as long decrease is not bigger than 1. |
Hi mate,
except for id like to speed up the counting by incrementing by 10 or 20ish
Case 0 : Backlvl = backlvl+20 'incr fast
I'm using one of those cheapie arduino lcd shields which use a volt divider and the adc (all buttons on the one input).
kind of slows things down, not a problem with the byte example I posted but when trying to set a large parameter > 3000
it takes a bit of time + the LCD isn't helping with the speed thing .
Not a real problem - its commercially acceptable as is, but its in my head that it needs reworking
I can do it with many lines of code, just hoping for an elegant solution.
Cheers
Simon |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Mon Feb 17, 2014 9:47 am Post subject: |
|
|
snipsnip wrote: | except for id like to speed up the counting by incrementing by 10 or 20ish
...
I can do it with many lines of code, just hoping for an elegant solution. |
I did explain that you can write a sub for this purpose.
In this sub you add the desired functionality, and everywhere a dec/inc is needed in your program, simply call the sub.
You can add an argument for the amount to dec/inc, the sub will check for over-/underrun and returns the corrected source variable. Even unsigned source variables will work, if you assign it in said sub to a signed variable and do the test for over-/underrun thereon.
Simply place repeatedly used code into subs or functions.
That's what's finally called programming |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Mon Feb 17, 2014 11:12 pm Post subject: |
|
|
One other way to implement a fast/slow inc/dec is to use a timer to set the delay, then run the timeout shorter the longer the button is held down. Reset the timer to the long delay as soon as the button is released. Saves you the complexity of inc/dec by large numbers, but adds complexity in the timing system. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
snipsnip
Joined: 10 Feb 2014 Posts: 74 Location: Melbourne
|
Posted: Mon Feb 17, 2014 11:59 pm Post subject: |
|
|
AdrianJ wrote: | One other way to implement a fast/slow inc/dec is to use a timer to set the delay, then run the timeout shorter the longer the button is held down. Reset the timer to the long delay as soon as the button is released. Saves you the complexity of inc/dec by large numbers, but adds complexity in the timing system. |
I think this may be the go, but id have to use the timer interrupt to skip the lcd display - ie use the timer to update the display every 500ms or so.
its the LCD that's slowing it all down.
Another way I'm looking at is below, (it doesn't work yet : ) ) but if I can figure out how to compare the two flags, do some math - should be able to check for byte rollover??
but yeah, using integers and writing a sub/function would be the smart thing to do
Gosub Keypad
Select Case Kpad
Case 0 : Backlvl = Backlvl + 10 : Waitms 200
Case 1 : Incr Backlvl : Waitms 200
Case 2 : Decr Backlvl : Waitms 200
Case 3 : Backlvl = Backlvl - 10 : Waitms 200
Case 4 : Exit Do
End Select
Toggle Flag
If Flag = 1 Then Poke 1 , Backlvl
If Flag = 0 Then Poke 2 , Backlvl
X = Peek(1)
Y = Peek(2) |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Tue Feb 18, 2014 12:16 am Post subject: |
|
|
what you can do is this :
Code: | dim Backlvl as byte , kpad as byte
declare sub Check(var as byte , byval change as byte)
do
input "kpad? " , kpad 'just to simulate
Select Case Kpad
Case 0 : check Backlvl , 0
Case 1 : check Backlvl , 1
Case 2 : check Backlvl , 2
Case 3 : check Backlvl , 3
Case 4 : Exit Do
End Select
loop
sub Check(var as byte , byval change as byte)
local w as word
Select Case Kpad
Case 0 : w = Backlvl + 10
Case 1 : w = Backlvl + 1
Case 2 : w = Backlvl - 1
Case 3 : w = Backlvl - 10
End Select
if w < 1 then
w = 1
elseif w > 250 then
w = 250
end if
var = w
waitms 200
end sub |
the check could also get the minim and maximum values. this is more or less how MWS suggested it.
I have no idea what peek/poke must do in your code but take care with poking. _________________ Mark |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Tue Feb 18, 2014 1:58 am Post subject: |
|
|
I would argue that you should always use a timer. Processors are much faster than we humans, and its almost always the case that you need to slow down things like display updates. But at the same time, you want the processor to do as much real processing as possible, so get rid of those wait statements, which are a pure waste. Use a timer and its interrupt to set flags for the display update, and anything else you need to run 'slowly', and process the flags in the main loop. Then you have no waiting around, and your main loop runs as fast as possible. Also means that as you extend your program to do more things, you dont have to juggle those waits to compensate.
Code: |
'after startup:
do 'main loop
if displayflag = 1
displayflag = 0 'clear flag ready for next
call UpdateDisplay 'write data to display
end if
call ReadKeyboard 'read keyboard for next press
'do all other processing, read sensors, etc, etc
loop 'end of main loop
timer_ovf ''timer IRQ
displayflag = 1
return
|
Back in the olden days, before timers and interrupts were invented, we used to do things like this:
Code: |
'after startup:
displayflag = displayMax 'preset flag to max
do 'main loop
decr displayflag
if displayflag = 0 then
displayflag = displayMax ' some constant to get the update period about right
call UpdateDisplay 'write data to display
end if
call ReadKeyboard 'read keyboard for next press
'do all other processing, read sensors, etc, etc
loop 'end of main loop
|
While that worked, and still meant the main loop ran as fast as possible, it meant we had to adjust the DisplayMax number arbitrarily as we added more stuff into the main loop. But it was still better than introducing wait statements. Of course, interrupts would add unpredictable times to the main time cycle, but in general these were pretty small, if we used interrupts at all. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
snipsnip
Joined: 10 Feb 2014 Posts: 74 Location: Melbourne
|
Posted: Tue Feb 18, 2014 7:37 am Post subject: |
|
|
Thanks guys,
I just tried doing a timer interrupt to update the lcd - but its way too clunky, works but looks crap/ugly.
its too much work to write a sub to turn a byte into a pseudo signed byte.
(i'll still try sometime - could use it elsewhere)
Mark, I don't think your example would work unless w is dimmed as integer, a word will still rollover with the +10 increments?
just going to use integers for all setup variables , hope there's enough eram? 1k is heaps yeah ,
below works beautifully with backlvl as an integer, pretty much the same as what I started with : )
I'm throwing the towel in on this one.
Test:
Incr A
Waitms 200
Pwm2b = 250
Do
Gosub Keypad
Select Case Kpad
Case 0 : Backlvl = Backlvl + 20
Case 1 : Incr Backlvl : Waitms 200
Case 2 : Decr Backlvl : Waitms 200
Case 3 : Backlvl = Backlvl - 20
Case 4 : Exit Do
End Select
If Backlvl < 1 Then Backlvl = 0
If Backlvl > 1250 Then Backlvl = 1250
Locate 2 , 1
Lcd " " ; Backlvl ; " "
Loop
Incr A
Return |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Tue Feb 18, 2014 11:08 am Post subject: |
|
|
sorry, working way too late. yes the W should be an integer. just change the type of it to integer and the sample will work for byte ranges.
for integer ranges the type should be a long. _________________ Mark |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|