Pushing the Evelope
I need help with some tricky coding!
We have 8 push-buttons that visitors trigger, each of which turns on a 12VDC water valve to activate a portion of an exhibit. I want this done very quickly so when a visitor pushes the buttons, the valve opens for a certain short period of time and closes.
To achieve this, I used a HC595 for outputs and HC165 to read the inputs. This gives me a byte showing the status of the push-buttons, and an output byte from the BS2 to trigger the valves via the 595. I also added a 5k pot to control the amount of time the valves stay on.
I developed a simple code to do this - attachedCombined Pumps.bs2. The circuit and code work but it is sluggish unless the value of the pot (the wait time or the rate the switches are being read) is very low. The problem here is that if the wait is too short, the valve don't stay on long enough.
Further, it would be ideal if I can have different on-time for each valve.
I can write the code by looking at each input individually but that slows things down. Also, having BS2 circuits is not an option!
Any ingenious way of doing this?
Many thanks in advance,
Al
We have 8 push-buttons that visitors trigger, each of which turns on a 12VDC water valve to activate a portion of an exhibit. I want this done very quickly so when a visitor pushes the buttons, the valve opens for a certain short period of time and closes.
To achieve this, I used a HC595 for outputs and HC165 to read the inputs. This gives me a byte showing the status of the push-buttons, and an output byte from the BS2 to trigger the valves via the 595. I also added a 5k pot to control the amount of time the valves stay on.
I developed a simple code to do this - attachedCombined Pumps.bs2. The circuit and code work but it is sluggish unless the value of the pot (the wait time or the rate the switches are being read) is very low. The problem here is that if the wait is too short, the valve don't stay on long enough.
Further, it would be ideal if I can have different on-time for each valve.
I can write the code by looking at each input individually but that slows things down. Also, having BS2 circuits is not an option!
Any ingenious way of doing this?
Many thanks in advance,
Al
Comments
-Phil
Whether a button is pressed or not pressed the "getswitches" will scan and then goto "sendout". So if no button has been pressed the Stamp is just going to be unresponsive for as long as 2 seconds until it comes back to scan the switches again. During that time it is possible it may miss the users input.
Also the switches must be in a pressed state when "inload" receives its pulse, this means that if you had for example 5 users pressing buttons any small difference in time between when they pressed the buttons would give you an apparent error on the output, in other words you would read some but not all of the user inputs.
I think it would be better if you verified there actually was user input before moving into the output routine. Something like the following might work, the first read checks for input and the second read gives time for everyone to press. The pause can be adjusted to whatever works best.
getSwitches: newSW=0 Do While newSW < 1 PULSOUT inLoad, 5 ' load switch inputs SHIFTIN inData, inClock, MSBPRE, [newSW] ' shift them in Loop PAUSE 20 ' allow time for all users to press PULSOUT inLoad, 5 ' load switch inputs SHIFTIN inData, inClock, MSBPRE, [newSW] ' shift them in RETURN
Jeff T.
What time range do you want to have for the individual pump run times? Do you need to have these individual pump run times field programmable, or could they be fixed?
If you maintain 8 separate timers for each pump, you could have different times for each of them and they could run simultaneously. Eliminating the re-reading of the POT will speed processing up, and if the pump run times don't change (or are only changed by you) then they can be done outside of the normal loop.
Al
Thanks for your thought...
What I'm suggesting is to setup 8 counters that all run in parallel, and only one pause to set the timing on them. I've added that to your original program. Take a look and see if it works for you.
' {$STAMP BS2} ' {$PBASIC 2.5} ' pin assignment outData PIN 2 ' Data pin to 74HC595. outClock PIN 0 ' Shift clock to '595. outLoad PIN 1 ' Moves data from shift register to output latch. inData PIN 7 ' shift clock (74HC165.2) inClock PIN 9 ' serial data (74HC165.7) inLoad PIN 8 ' input load (74HC165.1) LED PIN 14 ' red indicator LED Pot PIN 15 ' adjust water valve on-time ' variables onTime VAR Word ' calibrated pot value in ms ' pot rane 0-6000. max on time = 2000ms i VAR Byte ' general counter oldSW VAR Byte ' previous reading from the HC165 newSW VAR Byte ' current value of switches valves VAR Byte ' binary represetatio of the output to the HC595 switches VAR Byte ' switches that just turned on counter VAR Byte(8) ' counters for each switch DATA 10,20,30,40,50,60,70,80 ' valve run times in multiples of onTime ' onTime should be small, like 1/10 second Reset: HIGH inLoad GOSUB readPot FOR i = 1 TO 3 HIGH LED : PAUSE onTime : LOW LED : PAUSE 500 NEXT valves = 0 : GOSUB sendOut oldSW = 0 : newSW = 0 monitor: GOSUB getSwitches ' get switch inputs DEBUG HOME, BIN8 newSW ' display current status switches = oldSW ^ newSW & newSW ' new switch presses in switches oldSW = newSW ' update old value 'DEBUG HOME, BIN8 ? oldSW, BIN8 ? newSW, BIN8 ? valves 'valves = newSW : GOSUB sendOut GOSUB ticker ' check the counters GOSUB sendOut ' update valve status PAUSE onTime ' pause a short time (onTime should be small, try 100ms) GOTO monitor ' start over ticker: valves = 0 ' all valves off unless set by a timer FOR i = 0 TO 7 ' eight timers IF 1<<i & switches THEN ' switch just pressed READ i,counter(i) ' loads a unique time for each counter, stored in EEPROM ENDIF IF counter(i) > 0 THEN ' counter not zero valves = 1<<i | valves ' turn on valve counter(i) = counter(i) - 1 ' decrement counter ENDIF NEXT RETURN sendOut: SHIFTOUT outData,outClock,MSBFIRST,[valves] PULSOUT OUTLoad,1 RETURN getSwitches: PULSOUT inLoad, 5 ' load switch inputs SHIFTIN inData, inClock, MSBPRE, [newSW] ' shift them in RETURN readPot: HIGH pot ' charge the cap PAUSE 1 RCTIME pot, 1, onTime onTime = onTime/3 DEBUG DEC ? onTime RETURN
I will try it and report back.
Many thanks Sapphire.
Al