Water drop controller

premelec

Senior Member
Sorry - I thought you said you were running just not as well as desired... Persist! With coding it's always almost good :) A lot of times it helps to go back to zero and start again with the insight you've acquired along with frustration past... and have a cuppa tea... or stout or whatever... good luck..
 

bfgstew

Senior Member
I am really struggling with this coding, so any help would be appreciated.

I want to be able to write to the OLED via 4 x 4 keypad and change values shown as 0 or 0000 that are already on the screen, then that value needs to be able to change automatically the value in the programme, so if the screen is showing P1-0000 and I change it to P1-0030, then that will alter the pause time accordingly in the main programme and so on.
I think I have got myself totally confused with this and can't see the wood for the trees, please help, thank you.

Stewart
 

nick12ab

Senior Member
I am really struggling with this coding, so any help would be appreciated.

I want to be able to write to the OLED via 4 x 4 keypad and change values shown as 0 or 0000 that are already on the screen, then that value needs to be able to change automatically the value in the programme, so if the screen is showing P1-0000 and I change it to P1-0030, then that will alter the pause time accordingly in the main programme and so on.
I think I have got myself totally confused with this and can't see the wood for the trees, please help, thank you.

Stewart
A rough draft example:
Code:
serout C.1,N2400,(254,128,"Enter number:     ",254,142)
for b27 = 0 to 3
    prc_X
    if varX < 10 then
        bptr = 20 + b27            'Store numbers in variables b20-23
        @bptr = varX
        serout C.1,N2400,(#varX)
    end if
next b27
w0 = b20 * 10 + b21 * 10 + b22 * 10 + b23
pause w0
make prc_X your keypad checking subprocedure and varX whatever variable is set by the keypad checking procedure.
 

bfgstew

Senior Member
Ok Nick, I have tried your example and to be honest a lot of it I don't get, some I do.

I have adding my stuff to it but all i get so far is 'Enter number:12121212' up on screen.

Code:
keypad:
	serout C.1,N2400,(254,128,"Enter number:     ",254,142)
	for b27 = 0 to 3
	readadc 2,b1
    	readadc 2,b2
 	readadc 2,b3
    	readadc 2,b4
    	readadc 2,b5
	readadc 2,b6     
	readadc 2,b7   	
 	readadc 2,b8  	
	readadc 2,b9   	 
 	readadc 2,b0
	if b27 < 10 then
      bptr = 20 + b27            'Store numbers in variables b20-23
      @bptr = b1
      serout C.1,N2400,(#1)
      @bptr = b2
      serout C.1,N2400,(#2)
      endif
      next b27
      w0 = b20 * 10 + b21 * 10 + b22 * 10 + b23
      pause w0
I don't understand the last but one line - w0 = b20* 10 + b21 * 10 + b22 * 10 + b23
and - bptr = 20 + b27 'Store numbers in variables b20-23

Sorry if I sound ungrateful, but I need a bit more explanation for me to understand it more.

Stewart
 

nick12ab

Senior Member
w0 = b20* 10 + b21 * 10 + b22 * 10 + b23
and - bptr = 20 + b27 'Store numbers in variables b20-23
The first of those lines is to merge the four digits into one word variable and the second one is just a simple equation for setting a pointer so that the entire loop can be done with just maths and no IF statements - as b27 in this example is the loop variable, in the loops the values of bptr will be 20,21,22 and 23 respectively because 20 is being added to the loop variable. If you want different variables to be used instead, you simply change 20 to something else.

Looking at the rest of the code that you posted, it does look very different from what I posted.

What's this?
Code:
	readadc 2,b1
    	readadc 2,b2
 	readadc 2,b3
    	readadc 2,b4
    	readadc 2,b5
	readadc 2,b6     
	readadc 2,b7   	
 	readadc 2,b8  	
	readadc 2,b9   	 
 	readadc 2,b0
 

nick12ab

Senior Member
That is supposed to be my keypad code, I sense this is not how it is done...................:confused:
What I don't get is why you're reading it into ten variables. One readadc should be enough. Also, my original 'prc_X' used a matrix keypad and returned the number on the pressed key so in your analogue one you will need to use IF or SELECT...CASE statements to determine the number of key pressed. To find out what the ADC readings are, simply use this code and open the Terminal:
Code:
do
    readadc 2,b0
    sertxd (#b0,CR,LF)
loop
Your final prc_X will look something like this:
Code:
prc_X:
    readadc 2,b0
    if b0 > 28 and b0 < 32 then : b1 = 0
    elseif b0 > 40 and b0 < 44 then : b1 = 1
........
    end if
    return
You can use 10 and 11 for * and #.
 

bfgstew

Senior Member
I think the penny may have dropped, thanks Nick, will try again, now I have a better understanding.

Stewart
 

bfgstew

Senior Member
The penny may have dropped, but I think it may have got stuck somewhere en route................!!!!!!!

I feel so foolish that I am struggling with this. I have copied Nick's code and put the prc_X and var_X bits in and tried it and that comes up is 4 zeros on the OLED screen, is that supposed happen?????

Code:
serout C.1,N2400,(254,128,"Enter number:     ",254,142)
for b27 = 0 to 3
prc_X:
    readadc 2,b0
    	if b0 > 176 and b0 < 180 then : b1 = 0
    	elseif b0 > 121 and b0 < 125 then : b1 = 1
    	elseif b0 > 114 and b0 < 118 then : b1 = 2
    	elseif b0 > 104 and b0 < 108 then : b1 = 3
    	elseif b0 > 148 and b0 < 152 then : b1 = 4
    	elseif b0 > 143 and b0 < 147 then : b1 = 5
    	elseif b0 > 137 and b0 < 141 then : b1 = 6
    	elseif b0 > 166 and b0 < 170 then : b1 = 7
    	elseif b0 > 162 and b0 < 166 then : b1 = 8
    	elseif b0 > 159 and b0 < 163 then : b1 = 9
    	elseif b0 > 179 and b0 < 183 then : b1 = 10
      elseif b0 > 174 and b0 < 178 then : b1 = 11
    	elseif b0 > 159 and b0 < 163 then : b1 = 12
    	elseif b0 > 159 and b0 < 163 then : b1 = 13
    	elseif b0 > 159 and b0 < 163 then : b1 = 14
    	elseif b0 > 159 and b0 < 163 then : b1 = 15
    	end if
    if b1 < 10 then
        bptr = 20 + b27            'Store numbers in variables b20-23
        @bptr = b1
        serout C.1,N2400,(#b1)
    end if
next b27
w0 = b20 * 10 + b21 * 10 + b22 * 10 + b23
pause w0
 

nick12ab

Senior Member
Try this instead. The thing about your original routine is that if there was no keypress then the value of b0 wouldn't change so my code would think that the 0 key is constantly pressed. I've modified your code slightly and now it should hopefully work.
Code:
serout C.1,N2400,(254,128,"Enter number:     ",254,142)
for b27 = 0 to 3
prc_X:
    readadc 2,b0
    	if b0 > 176 and b0 < 180 then : b1 = 0
    	elseif b0 > 121 and b0 < 125 then : b1 = 1
    	elseif b0 > 114 and b0 < 118 then : b1 = 2
    	elseif b0 > 104 and b0 < 108 then : b1 = 3
    	elseif b0 > 148 and b0 < 152 then : b1 = 4
    	elseif b0 > 143 and b0 < 147 then : b1 = 5
    	elseif b0 > 137 and b0 < 141 then : b1 = 6
    	elseif b0 > 166 and b0 < 170 then : b1 = 7
    	elseif b0 > 162 and b0 < 166 then : b1 = 8
    	elseif b0 > 159 and b0 < 163 then : b1 = 9
    	elseif b0 > 179 and b0 < 183 then : b1 = 10
      elseif b0 > 174 and b0 < 178 then : b1 = 11
    	elseif b0 > 159 and b0 < 163 then : b1 = 12
    	elseif b0 > 159 and b0 < 163 then : b1 = 13
    	elseif b0 > 159 and b0 < 163 then : b1 = 14
    	else : b1 = 15
        do : readadc 2,b0 : loop until b0 < 30      'Loop until key is released, change constant if necessary
    	end if
    if b1 < 10 then
        bptr = 20 + b27            'Store numbers in variables b20-23
        @bptr = b1
        serout C.1,N2400,(#b1)
    end if
next b27
w0 = b20 * 10 + b21 * 10 + b22 * 10 + b23
pause w0
However I do recommend that you put prc_X as a separate subroutine with a return at the end so that you can reuse it throughout the program but get the existing code working first before you try this.
 

bfgstew

Senior Member
Thanks for that Nick, I am on nights at the moment so no real chance of having a 'play' with it, but will post results later this week.

Many thanks for your patience and input, greatly appreciated.

Stewart
 

bfgstew

Senior Member
As will be having several variable pause times in the main programme, I would need to run the above code to generate each pause variable, starting with w0, then w1, w2,w3 and so on, then in the main programme have it read so:

pause w0
high B.7
pause w1
low B.7
pause w2
high B.7
pause w3
low B.7

Cheers in advance.

Stewart
 

bfgstew

Senior Member
Well, I am having no luck at all with this code, it seems I am banging my head against a brick wall, but that is down to me and not fully understanding the dark art of programming!
I haven't given up on Nicks code, but I wanted to see if I could write to the OLED screen the pause times I wanted (P0 - P6) I can get the number for drops required but for the life of me I just cannot get anything for P0 - P6.
This is the code so far, P0 - P6 is not complete but gives an idea of what it should be, basically I need to be able to write 0001 to 9999 to each, and in time these need to alter the pause times on main1 - main4.
Have I, or am I doing something completely stupid?

Code:
init:
	pause 500            
            serout C.1, N2400, (254,1)
	pause 50
	serout C.1,N2400,( 254,128,"Drops-  P0-    ")      ;drop selection 0 is the variable, 1 to 4.                                          
	serout C.1,N2400,( 254,192,"P1-     P2-    ")      ;P0 &#8211; P6 is the pause time between drops
	serout C.1,N2400,( 254,148,"P3-     P4-    ")      ; 0000 is the variable, adjustable from1 to 9999ms
	serout C.1,N2400,( 254,212,"P5-     P6-    ")
	pause 500
		let dirsB = %11111111 
keypad:
    	readadc 2,b0
    	if b0 > 176 and b0 < 180 then : b1 = 0
    	elseif b0 > 121 and b0 < 125 then : b1 = 1
    	elseif b0 > 114 and b0 < 118 then : b1 = 2
    	elseif b0 > 104 and b0 < 108 then : b1 = 3
    	elseif b0 > 148 and b0 < 152 then : b1 = 4
    	elseif b0 > 143 and b0 < 147 then : b1 = 5
    	elseif b0 > 137 and b0 < 141 then : b1 = 6
    	elseif b0 > 166 and b0 < 170 then : b1 = 7
    	elseif b0 > 162 and b0 < 166 then : b1 = 8
    	elseif b0 > 159 and b0 < 163 then : b1 = 9
    	elseif b0 > 179 and b0 < 183 then : b1 = 10
    	elseif b0 > 174 and b0 < 178 then : b1 = 11
    	end if
drops:
	readadc 2,b1
        if b1 = 123 then serout C.1,N2400,(254,134,"1")
        endif
        if b1 = 123 then let pinsB = %00000001
        endif
        if b1 = 116 then serout C.1,N2400,(254,134,"2")
        endif
        if b1 = 116 then let pinsB = %00000011
        endif
        if b1 = 106 then serout C.1,N2400,(254,134,"3")
        endif
        if b1 = 106 then let pinsB = %00000111
        endif
        if b1 = 150 then serout C.1,N2400,(254,134,"4")
        end if
        if b1 = 150 then let pinsB = %00001111
        endif
       if b1 = 181 then gosub P0
       goto drops
P0:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,140,"0",254,141,"0",254,142,"0",254,143,"0")
	endif
	if b1 = 123 then serout C.1,N2400,(254,140,"1",254,141,"1",254,142,"1",254,143,"1")
	endif
	if b1 = 116 then serout C.1,N2400,(254,140,#2,254,141,#2,254,142,#2,254,143,#2)
	endif
	if b1 = 106 then serout C.1,N2400,(254,140,#3,254,141,#3,254,142,#3,254,143,#3)
	endif
	if b1 = 181 then gosub P1
	goto P0
P1:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,195,#0,254,196,#0,254,197,#0,254,198,#0)
	endif
	if b1 = 123 then serout C.1,N2400,(254,195,#1,254,196,#1,254,197,#1,254,198,#1)
	endif
	if b1 = 116 then serout C.1,N2400,(254,195,#2,254,196,#2,254,197,#2,254,198,#2)
	endif
	if b1 = 106 then serout C.1,N2400,(254,195,#3,254,196,#3,254,197,#3,254,198,#3)
	endif
	if b1 = 150 then serout C.1,N2400,(254,195,#4,254,196,#4,254,197,#4,254,198,#4)
	endif
	if b1 = 145 then serout C.1,N2400,(254,195,#5,254,196,#5,254,197,#5,254,198,#5)
	endif
	if b1 = 139 then serout C.1,N2400,(254,195,#6,254,196,#6,254,197,#6,254,198,#6)
	endif
	if b1 = 168 then serout C.1,N2400,(254,195,#7,254,196,#7,254,197,#7,254,198,#7)
	endif
	if b1 = 164 then serout C.1,N2400,(254,195,#8,254,196,#8,254,197,#8,254,198,#8)
	endif
	if b1 = 161 then serout C.1,N2400,(254,195,#9,254,196,#9,254,197,#9,254,198,#9)
	endif
	if b1 = 181 then gosub P2
	goto P1
P2:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,203,#0,254,204,#0,254,205,#0,254,206,#0)
	endif
	if b1 = 181 then gosub P3
	goto P2
P3:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,151,#0,254,152,#0,254,153,#0,254,154,#0)
	endif
	if b1 = 181 then gosub P4
	goto P3
P4:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,159,#0,254,160,#0,254,161,#0,254,162,#0)
	endif
	if b1 = 181 then gosub P5
	goto P4
P5:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,215,#0,254,216,#0,254,217,#0,254,218,#0)
	endif
	if b1 = 181 then gosub P6
	goto P5
P6:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,223,#0,254,224,#0,254,225,#0,254,226,#0)
	endif
	if b1 = 181 then gosub mainA
	goto P6
mainA:
	readadc 2,b1                               ;b1 is the start button to run programme
	if b1 = 175 then main4
	goto mainA
main1:                                                     ; 1 drop
	high B.7                 
	pause 500
	low B.7
	goto init
mainB:
	readadc 2,b1                               ;b1 is the start button to run programme
	if b1 = 175 then main2
	goto mainB
main2:                                                     ; 2 drops
	high B.7
	pause 500
	low B.7
	pause 500
	high B.7
	pause 500
	low B.7
	goto init
mainC:
	readadc 2,b1                              ;b1 is the start button to run programme
	if b1 = 175 then main3
	goto mainC
main3:          				   ;3 drops
	high B.7
	pause 500
	low B.7
	pause 500
	high B.7
	pause 500
	low B.7
	pause 500
	high B.7
	pause 500
	low B.7
	goto init
mainD:
	readadc 2,b1                              ;b1 is the start button to run programme
	if b1 = 175 then main4
	goto mainD	
main4:					    ;4 drops
	high B.7
	pause 500
	low B.7
	pause 500
	high B.7
	pause 500
	low B.7
	pause 500
	high B.7
	pause 500
	low B.7
	pause 500
	high B.7
	pause 500
	low B.7
	goto init
 

nick12ab

Senior Member
Lines like this: if b1 = 161 then serout C.1,N2400,(254,195,#9,254,196,#9,254,197,#9,254,198,#9) - you need a colon between 'then' and 'serout'.

Also this part:
Code:
P5:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,215,#0,254,216,#0,254,217,#0,254,218,#0)
	endif
	if b1 = 181 then gosub P6
	goto P5
P6:
	readadc 2,b1
	if b1 = 178 then serout C.1,N2400,(254,223,#0,254,224,#0,254,225,#0,254,226,#0)
	endif
	if b1 = 181 then gosub mainA
	goto P6
This is bound to lead to a stack error - use gotos instead of gosubs.
 

bfgstew

Senior Member
Thanks again for the help Nick, it's working now..........:)
Need to tidy up a bit and get it so I don't get a row of the same numbers on each line..............DOH.


Stewart
 

bfgstew

Senior Member
View attachment RESISTOR MATRIX.zip

Well I have been going at this on and off for over a week and have come to the conclusion that the keypad is the cause of my problems. With such tight tolerances I found certain button presses were causing it to skip and jump to different places. So I made my own matrix spreadsheet, please feel free to use it, alter it, slate it............... it has helped me, so far.
 

premelec

Senior Member
I'm not understanding your circuit with the key pad - I mentioned earlier a circuit I've used with 6 resistors that works well - I'll dig out the circuit... contact resistance of the keypads varies so large resistor values help to minimize contact R effects. I also made up a spreadsheet to try optimize the 6 resistors empirically... then did what you have to read actual ADC values...put those in my program.
 

premelec

Senior Member
My 3x4 6 R schematic...

KeyPad_3192.jpgI just noticed you said 4x4 keypad... mine's 3x4... anyhow attached picture is about the schematic... values read on READADC are about 6 to 7 points apart - original circuit had 10K termination but I changed to 33K for slightly better spread
 

bfgstew

Senior Member
Cheers for that Premelec, the 4 x 4 is a lot harder to get right hence the spreadsheet as it can be done instantly and results shown.
I am in two minds to go for the 4 x 3 matrix now as I think I can code out the use for up, down, left and right buttons, maybe do them on another project.
Thanks for the input.
Stewart
 

premelec

Senior Member
OK - you could add a 4 button cursor control pad and even use the same ADC input to discern it's existence and values... now you know the trouble it takes to get the job done!
 

bfgstew

Senior Member
Or even use a second ADC input just for the 4 cursor buttons, if that's possible as there are 7 available ADC inputs on the 18M2 ?

Cheers Prem, keep you posted.

Stewart.
 

bfgstew

Senior Member
Hiya Texy, wonderered where you had got to!!!!!

Well proof of the pudding is in the eating, and unfortunately, I didn't really listen to what people said and advised, so am paying the price now........that is a note to all noobies out there....LISTEN to these guys, they know their stuff.

But it has forced me into thinking a lot more about the project and am currently re planning the layout and project box so it does look the biz.

Stewart
 

premelec

Senior Member
You can use the same ADC input and buttons that select voltage values less than 90 [e.g. post 111 96 min] for the cursor... I found in my files a detailed spreadsheet from 'BCJ kiwi' early 2010 Forum - with more discussion - it may still be available to download... Have fun - and learn... :)
 

bfgstew

Senior Member
Right I have rebuilt my project into a nice box, new keypad and all is well, apart from the coding to get the variable pause times to show on the OLED and be read by the program. Nick gave me a snippet of code (which I am grateful) but it doesn't appear to work, well not with me it doesn't. I can manually change the pause times using programme editor and re-download it, that bits fine, I just cannot ge this bit to work and it is frustrating the life out of me.
The programme is simply 4 selections, either 1, 2, 3 or 4 - this selects how many drops you want, after you have selected what drop/drops you want, the screen then gives you the pause times for that selection (P1, is for 1 drop and gives 1 selection to choose a pause time for it, P2 gives 3 selections, P3 gives 5 selections and P4 gives 7 selections).
The coding may be a bit messy but at the moment I am trying to P1 to alter using the keypad and screen, the rest I can do later if I can get this bit to work. With the current code in P1 all I get on the screen is "Drops-1 P1- " and when I press # (which is assigned as the start/run button) is B.7 on (high) for 30 seconds, and then runs rest of code and returning to init: which is how it should.

Any help would be gratefully recieved, thanks in advance, yet again!

Stewart

Oh bu**er I can't upload coding as works comp won't allow it, will post it later this evening when I get home, sorry guys.
 

Aresby

New Member
Just a quick note about a power supply... Rather than having 2 supplies, one for the Picaxe and one for the solenoid, I was wondering if it will do the job of both?
As long as the solenoid doesn't introduce massive spikes on the power line (as it switches on and off) this will work and what I do all the time.

Just make sure the supply for each is adequately decoupled (eg smoothing capacitors, regulators [which you're using], decoupling capacitor near the PIC chip) so they don't affect each another.

If you have a 'scope you will able to monitor this; if not, just apply best practices as mentioned above.
 

bfgstew

Senior Member
As promised my coding.....................see post #148

Code:
#Picaxe 18M2 Water drop controller, 4 drops controlled via numeric keypad and serial OLED screen interface.
; Pause times are altered using the keypad and range from 1ms to 9999ms
; 4 drop selections can be made and these bring relevant screen to show and alter pause times to suit

init:
	pause 500            
            serout C.1, N2400, (254,1)
	pause 500
		let dirsB = %11111111 
keypad:
    	readadc 2,b0
    	if b0 > 185 and b0 < 187 then : b1 = 0
    	elseif b0 > 205 and b0 < 207 then : b1 = 1
    	elseif b0 > 171 and b0 < 173 then : b1 = 2
    	elseif b0 > 103 and b0 < 105 then : b1 = 3
    	elseif b0 > 235 and b0 < 237 then : b1 = 4
    	elseif b0 > 231 and b0 < 234 then : b1 = 5
    	elseif b0 > 229 and b0 < 231 then : b1 = 6
    	elseif b0 > 215 and b0 < 217 then : b1 = 7
    	elseif b0 > 194 and b0 < 196 then : b1 = 8
    	elseif b0 > 165 and b0 < 167 then : b1 = 9
    	elseif b0 > 210 and b0 < 212 then : b1 = 10
    	elseif b0 > 141 and b0 < 143 then : b1 = 11
    	end if
drops:
	serout C.1,N2400,(254,128,"Drops- ")
	pause 500
	serout C.1,N2400,(254,14,254,134)
	pause 500
drop:
	readadc 2,b1
	if b1 = 206 then:serout C.1,N2400,(254,134,"1")
	goto P1
	endif
	if b1 = 172 then:serout C.1,N2400,(254,134,"2")
	goto P2
	endif
	if b1 = 104 then:serout C.1,N2400,(254,134,"3")
	goto P3
	endif
	if b1 = 236 then:serout C.1,N2400,(254,134,"4")
	goto P4
	endif
	goto drop

P1:   serout C.1,N2400,(254,136,"P1-    ")    ;P1 is variable pause time between 0 and 9999ms
	pause 30
	for b27 = 0 to 3
	readadc 2,b0
    	if b0 > 185 and b0 < 187 then : b1 = 0
    	elseif b0 > 205 and b0 < 207 then : b1 = 1
    	elseif b0 > 171 and b0 < 173 then : b1 = 2
    	elseif b0 > 103 and b0 < 105 then : b1 = 3
    	elseif b0 > 235 and b0 < 237 then : b1 = 4
    	elseif b0 > 231 and b0 < 234 then : b1 = 5
    	elseif b0 > 229 and b0 < 231 then : b1 = 6
    	elseif b0 > 215 and b0 < 217 then : b1 = 7
    	elseif b0 > 194 and b0 < 196 then : b1 = 8
    	elseif b0 > 165 and b0 < 167 then : b1 = 9
    	do:readadc 2,b0:loop until b0<100
    	end if
	if b1 < 10 then
        bptr = 20 + b27            'Store numbers in variables b20-23
        @bptr = b1
        serout C.1,N2400,(254,139,#b1)
    	end if
	next b27
	w0 = b20 * 10 + b21 * 10 + b22 * 10 + b23
	pause w0
	goto mainA
P2:
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	pause 30
	goto PP2
P3:
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	serout C.1,N2400,(254,148,"P4-     P5-    ")
	pause 30
	goto PP3
P4:
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	serout C.1,N2400,(254,148,"P4-     P5-    ")
	serout C.1,N2400,(254,212,"P6-     P7-    ")
	pause 30
	goto PP4
PP2:
	goto mainB
PP3:
	goto mainC
PP4:
	goto mainD
mainA:
	readadc 2,b1                               ;b1 is the start button to run programme
	if b1 = 142 then main1
	pause 100
	goto mainA
main1:                                                     ; 1 drop
	high B.7                 
	pause w0
	low B.7
	goto init
mainB:
	readadc 2,b1                               ;b15 is the start button to run programme
	if b1 = 142 then main2
	goto mainB
main2:                                 ; 2 drops
	high B.7
	pause 1000
	low B.7
	pause 1000
	high B.7
	pause 1000
	low B.7
	goto init
mainC:
	readadc 2,b1                               ;b15 is the start button to run programme
	if b1 = 142 then main3
	goto mainC
main3:                                  ; 3 drops
	high B.7
	pause 1000
	low B.7
	pause 1000
	high B.7
	pause 1000
	low B.7
	pause 1000
	high B.7
	pause 1000
	low B.7
	goto init
mainD:
	readadc 2,b1                               ;b15 is the start button to run programme
	if b1 = 142 then main4
	goto mainD	
main4:                                   ; 4 drops
	high B.7
	pause 1000
	low B.7
	pause 1000
	high B.7
	pause 1000
	low B.7
	pause 1000
	high B.7
	pause 1000
	low B.7
	pause 1000
	high B.7
	pause 1000
	low B.7
	goto init
 

Aresby

New Member
Sorry, the lack of comments in your program have prevented me understanding what you are doing at each stage. Neither did I fully understand the description of the problem above.

However, you could help yourself by tidying up the code. Here are some suggestions:

  1. Indent the code properly. This applies to each "IF/ ENDIF", "DO LOOP"
  2. Don't put more than one statement on one line, it makes it difficult to follow the code
  3. Use properly named symbols rather than b1, b2 etc, so that the code is self-documenting
  4. Put a comment above each logic block of code so we know what its purpose is
  5. Call a subroutine where you do repetitive actions such as "high B.7 / pause 1000 / low B.7" several times in your code.
  6. Avoid the use of "GOTO" wherever possible. Its use makes following the logic of your code difficult. Create a separate subroutine for each part (eg P1, P2, P3) and use a GOSUB instead.
  7. Your main program will then consist of several GOSUBs inside a loop. This is much easier to debug.
That way you will see the wood for the trees and the you may see the problem yourself. At the very least it will make it easier to debug for others too.

Please take this suggestion in the spirit that it is intended (I coach people to code as part of my job so the above is the first step I would encourage you to do to resolve your issue. It's all very well to say "the code's a bit messy and I'll sort it out later" but in my experience people don't do that once it starts working. Neither do they document it after the fact.)

When you've done all that and still not found the solution yourself, highlight where you think it is going wrong (or where it stops doing things right) so others can focus on that part.
 

bfgstew

Senior Member
Thanks Aresby, I will try my best, but this is my first attempt at coding and it has become a bit daunting to say the least.
I will take heed of your suggestions and thank you for your honest and constructive comment.

Stewart
 

bfgstew

Senior Member
Ok, I have tried to tidy the code up a bit and make it easier to understand, I hope.

The conundrum still is getting the pause values of P1 to P7 inputted so they show on the OLED screen and changed in main1 to main4, I have put 'pause 1000' in just as a value to test the code but I need these to become variables, somehow?????

Code:
;#Picaxe 18M2 Water drop controller, 4 drops controlled via numeric 
;keypad and serial OLED screen interface.
;Pause times are altered using the keypad and range from 1ms to 9999ms
;4 drop selections can be made and these bring relevant screen to show and 
;alter pause times to suit

symbol key = b1
symbol solenoid = B.7

init:            
	serout C.1, N2400, (254,1)	;initialize OLED
	pause 30
	serout C.1,N2400,(254,128,"Drops- ")	;1st screen display
	pause 30
		 		
keypad:						; read keypad values into b1
    	readadc 2,b0				
    		if b0 > 185 and b0 < 187 then : b1 = 0
    			elseif b0 > 205 and b0 < 207 then : b1 = 1
    			elseif b0 > 171 and b0 < 173 then : b1 = 2
    			elseif b0 > 103 and b0 < 105 then : b1 = 3
    			elseif b0 > 235 and b0 < 237 then : b1 = 4
    			elseif b0 > 231 and b0 < 234 then : b1 = 5
    			elseif b0 > 229 and b0 < 231 then : b1 = 6
    			elseif b0 > 215 and b0 < 217 then : b1 = 7
    			elseif b0 > 194 and b0 < 196 then : b1 = 8
    			elseif b0 > 165 and b0 < 167 then : b1 = 9
    			elseif b0 > 210 and b0 < 212 then : b1 = 10
    			elseif b0 > 141 and b0 < 143 then : b1 = 11
    		end if
	readadc 2,b1						
		if key = 206 then:serout C.1,N2400,(254,134,"1"); if 1 is keyed in, jump to P1
		pause 30						      
		goto P1
	endif
		if key = 172 then:serout C.1,N2400,(254,134,"2");if 2 is keyed in, jump to P2
		pause 30
		goto P2
	endif
		if key = 104 then:serout C.1,N2400,(254,134,"3");if 3 is keyed in, jump to P3
		pause 30
		 goto P3
	endif
		if key = 236 then:serout C.1,N2400,(254,134,"4");if 4 is keyed in, jump to P4
		pause 30
		goto P4
	endif
	gosub keypad

P1: 	;P1 is variable pause time between 0 and 9999ms for the pause time in main1  
	serout C.1,N2400,(254,136,"P1-    ")   
	pause 30
	gosub mainA

P2:				;P2 is the variable times for the 3 pause times in main2
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	pause 30
	gosub mainB
P3:				;P3 is the variable times for the 5 pause times in main3							
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	serout C.1,N2400,(254,148,"P4-     P5-    ")
	pause 30
	gosub mainC
P4:				;P4 is the variable times for the 7 pause times in main4
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	serout C.1,N2400,(254,148,"P4-     P5-    ")
	serout C.1,N2400,(254,212,"P6-     P7-    ")
	pause 30
	gosub mainD

mainA:
	readadc 2,b1                     ;b1 is the start button to run programme
		if key = 142 then main1
	gosub mainA
main1:                                 ;Gives 1 drop from solenoid
	high solenoid                 
	pause 1000
	low solenoid
	gosub init
mainB:
	readadc 2,b1                     ;b1 is the start button to run programme
	if key = 142 then main2
	gosub mainB
main2:                                 ;Gives 2 drops from solenoid
	high solenoid
	pause 1000
	low solenoid
	pause 1000
	high solenoid
	pause 1000
	low solenoid
	gosub init
mainC:
	readadc 2,b1                      ;b1 is the start button to run programme
	if key = 142 then main3
	gosub mainC
main3:                                  ;Gives 3 drops from solenoid
	high solenoid
	pause 1000
	low solenoid
	pause 1000
	high solenoid
	pause 1000
	low solenoid
	pause 1000
	high solenoid
	pause 1000
	low solenoid
	gosub init
mainD:
	readadc 2,b1                       ;b1 is the start button to run programme
	if key = 142 then main4
	gosub mainD	
main4:                                   ;Gives 4 drops from solenoid
	high solenoid
	pause 1000
	low solenoid
	pause 1000
	high solenoid
	pause 1000
	low solenoid
	pause 1000
	high solenoid
	pause 1000
	low solenoid
	pause 1000
	high solenoid
	pause 1000
	low solenoid
	gosub init
 

Aresby

New Member
At the risk of sounding patronising you've made good progress with tidying up your code (although there are still too many statements on one line!).

If getting the pause to be variable is your only concern then you could do something like this:

Code:
s[FONT=courier new]ymbol dropDelay = w10    ; use a word variable as we want values > 255
dropDelay = 1000          ; default delay value[/FONT]
[now read the key pad for a variable that you pass into variable dropDelay, assuming you want the operator to select this in real-time.]

Then simply substitute your currently hard-coded pause for the variable:
Code:
pause dropDelay
If you're now thinking "how do I read the key pad number to get the pause value" you can scan this forum for the answer or Google (plenty out there). I notice in your code you seem to be using some sort of analog to digital converter to read an existing keypad which is slightly unusual. The most common method to get a key press is to digitally scan rows and columns of the keypad sequentially to find where a value exists, indicating a key press.

Try the forum search first, then Google. You'll find specific answers like this:

https://docs.google.com/viewer?a=v&q=cache:SVSkPm4-NhcJ:moodle.schoolnet.lk/mod/resource/view.php?inpopup=true&id=906+picaxe+keypad+scanning&hl=en&gl=uk&pid=bl&srcid=ADGEESizVUASJnaOCOSvq-CrwpM1SWAt6ZNxTNh-pnwoW-dxnZsH2o_d5He0DFWt3fDVRfVmEiP7PPPxDC931lQtk33FZxi5oaF6flPyaYr7MdwtbkrqOP963sKHPMwbbdnJV45wmFOo&sig=AHIEtbTVFXWQEw5jUzqrDRRGruZ4qTxJBQ
 

bfgstew

Senior Member
Thank you Aresby, I am getting somewhere now.

Code:
;#Picaxe 18M2 Water drop controller, 4 drops controlled via numeric 
;keypad and serial OLED screen interface.
;Pause times are altered using the keypad and range from 1ms to 9999ms
;4 drop selections can be made and these bring relevant screen to show and 
;alter pause times to suit

symbol key = b1
symbol solenoid = B.7
symbol dropDelay1 = w7    ; use a word variable as we want values > 255
dropDelay1 = 1000          ; default delay value
symbol dropDelay2 = w8    ; use a word variable as we want values > 255
dropDelay2 = 1000          ; default delay value
symbol dropDelay3 = w9    ; use a word variable as we want values > 255
dropDelay3 = 1000          ; default delay value
symbol dropDelay4 = w10    ; use a word variable as we want values > 255
dropDelay4 = 1000          ; default delay value
symbol dropDelay5 = w11    ; use a word variable as we want values > 255
dropDelay5 = 1000          ; default delay value
symbol dropDelay6 = w12    ; use a word variable as we want values > 255
dropDelay6 = 1000          ; default delay value
symbol dropDelay7 = w13    ; use a word variable as we want values > 255
dropDelay7 = 1000          ; default delay value
init: 
	pause 500           
	serout C.1,N2400,(254,1)	;initialize OLED
	pause 500
	serout C.1,N2400,(254,128,"Drops- ")	;1st screen display
	pause 30
		 		
keypad:						; read keypad values into b1
    	readadc 2,b0				
    		if b0 > 185 and b0 < 187 then : b1 = 0
    			elseif b0 > 205 and b0 < 207 then : b1 = 1
    			elseif b0 > 171 and b0 < 173 then : b1 = 2
    			elseif b0 > 103 and b0 < 105 then : b1 = 3
    			elseif b0 > 235 and b0 < 237 then : b1 = 4
    			elseif b0 > 231 and b0 < 234 then : b1 = 5
    			elseif b0 > 229 and b0 < 231 then : b1 = 6
    			elseif b0 > 215 and b0 < 217 then : b1 = 7
    			elseif b0 > 194 and b0 < 196 then : b1 = 8
    			elseif b0 > 165 and b0 < 167 then : b1 = 9
    			elseif b0 > 210 and b0 < 212 then : b1 = 10
    			elseif b0 > 141 and b0 < 143 then : b1 = 11
    		end if
	readadc 2,b1						
		if key = 206 then:serout C.1,N2400,(254,134,"1"); if 1 is keyed in, jump to P1
		pause 30						      
		goto P1
	endif
		if key = 172 then:serout C.1,N2400,(254,134,"2");if 2 is keyed in, jump to P2
		pause 30
		goto P2
	endif
		if key = 104 then:serout C.1,N2400,(254,134,"3");if 3 is keyed in, jump to P3
		pause 30
		 goto P3
	endif
		if key = 236 then:serout C.1,N2400,(254,134,"4");if 4 is keyed in, jump to P4
		pause 30
		goto P4
	endif
	gosub keypad

P1: 	;P1 sends this message to the OLED screen ready to recieve pause value.  
	serout C.1,N2400,(254,136,"P1-    ")   
	pause 30
	gosub PP1
PP1:  ;PP1 shows the pause time for the pause time used in main1  
	serout C.1,N2400,(254,139,#w7)
	pause 30
	goto mainA

P2:	;P2 sends this message to the OLED screen ready to recieve pause value.
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	pause 30
	gosub PP2
PP2:  ;PP2 shows the pause times for the 3 pause times used in main2
	serout C.1,N2400,(254,139,#w7)
	serout C.1,N2400,(254,195,#w8,254,203,#w9)
	pause 30
	goto mainB
P3:	;P3 sends this message to the OLED screen ready to recieve pause value.										
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	serout C.1,N2400,(254,148,"P4-     P5-    ")
	pause 30
	gosub PP3
PP3:  ;PP3 shows the pause times for the 5 pause times used in main3
	serout C.1,N2400,(254,139,#w7)
	serout C.1,N2400,(254,195,#w8,254,203,#w9)
	serout C.1,N2400,(254,151,#w10,254,159,#w11)
	pause 30
	goto mainC
P4:	;P4 sends this message to the OLED screen ready to recieve pause value.			
	serout C.1,N2400,(254,136,"P1-    ")
	serout C.1,N2400,(254,192,"P2-     P3-    ")
	serout C.1,N2400,(254,148,"P4-     P5-    ")
	serout C.1,N2400,(254,212,"P6-     P7-    ")
	pause 30
	gosub PP4
PP4:  ;PP4 shows the pause times for the 7 pause times used in main4
	serout C.1,N2400,(254,139,#w7)
	serout C.1,N2400,(254,195,#w8,254,203,#w9)
	serout C.1,N2400,(254,151,#w10,254,159,#w11)
	serout C.1,N2400,(254,215,#w12,254,223,#w13)
	pause 30
	goto mainD

mainA:
	readadc 2,b1                     ;b1 is the start button to run programme
		if key = 142 then main1
	gosub mainA
main1:                                 ;Gives 1 drop from solenoid
	high solenoid                 
	pause dropdelay1
	low solenoid
	gosub init
mainB:
	readadc 2,b1                     ;b1 is the start button to run programme
	if key = 142 then main2
	gosub mainB
main2:                                 ;Gives 2 drops from solenoid
	high solenoid
	pause dropdelay1
	low solenoid
	pause dropdelay2
	high solenoid
	pause dropdelay3
	low solenoid
	gosub init
mainC:
	readadc 2,b1                      ;b1 is the start button to run programme
	if key = 142 then main3
	gosub mainC
main3:                                  ;Gives 3 drops from solenoid
	high solenoid
	pause dropdelay1
	low solenoid
	pause dropdelay2
	high solenoid
	pause dropdelay3
	low solenoid
	pause dropdelay4
	high solenoid
	pause dropdelay5
	low solenoid
	gosub init
mainD:
	readadc 2,b1                       ;b1 is the start button to run programme
	if key = 142 then main4
	gosub mainD	
main4:                                   ;Gives 4 drops from solenoid
	high solenoid
	pause dropdelay1
	low solenoid
	pause dropdelay2
	high solenoid
	pause dropdelay3
	low solenoid
	pause dropdelay4
	high solenoid
	pause dropdelay5
	low solenoid
	pause dropdelay6
	high solenoid
	pause dropdelay7
	low solenoid
	gosub init
With the tweaks to my coding I now get the variable values displayed on screen correctly, albeit the default value (1000). Now I just need to be able to alter them once they are displayed (PP1 - PP4). I am using a 4 x 3 keypad with resistor matrix connected to pin C.2 using the readadc function to get the keypad reading. What coding would be needed to, once the value is displayed on the screen, to physically change it so it overwrites the 'default value', shows the 'new value'?
Sorry if I have been asking the same question but this has been somewhat of a steep learning curve and am struggling to reach the summit.
Thanks for your patience and guidance.
Stewart
 

Aresby

New Member
... I am using a 4 x 3 keypad with resistor matrix connected to pin C.2 using the readadc function to get the keypad reading. What coding would be needed to, once the value is displayed on the screen, to physically change it so it overwrites the 'default value', shows the 'new value'? ...
A steep learning curve it may be but it is worth it when you finally "get it"!

My suggestion for you is as follows:

1. Start a new mini project simply to learn how to read a keypad press into a variable.
2. Don't put this code into your main program until it works.
3. When you do add it to your main program add it in as a subroutine so you just call the routine like this:
Code:
'Read key press into variable b30. Only return here once key has been pressed.
Gosub GetKeyValue
This will then return the key the user pressed into the variable.

Rather than reinvent the wheel let me direct you to an external site that covers reading such a keypad:
http://smendes.com/el31p/KeypadLock.pdf

and
http://blog.southall-online.com/2010/09/28/interfacing-the-picaxe-to-a-4×3-matrix-keypad-revisited/

If this is not suitable just Google for "PICAXE keypad example" or something similar - there are dozens of examples out there of varying complexity. There's doubtless examples on this forum too (here, for example: http://www.picaxeforum.co.uk/showthread.php?20869-Keypad-help although this thread may be a bit confusing.

PICAXE (RevEd) themselves do a Keypad Lock which demonstrates the coding you could adapt too:
http://www.picaxe.com/docs/chi008.pdf

I do strongly recommend you just deal with this aspect in isolation from your main program. Get this bit working and then join it into your main program.

Play with the code. Don't just slavishly copy other programmers' works or you will never understand why you do stuff in your program!
 
Last edited:

bfgstew

Senior Member
Play with the code. Don't just slavishly copy other programmers' works or you will never understand why you do stuff in your program!
Don't intend to Aresby, just need a nudge in the right direction...................:)

Thanks again for your input.

Stewart
 

bfgstew

Senior Member
Ok, I give up, how can you change a variable (w7 - w13) using the keypad and ADC function. I have w7 to w13 as a default value of 1000 pause time, all I need is to be able to alter that value from 0001 to 9999, using the OLED and keypad I have trawled google and nothing!
I really am struggling with this last part of the code and would greatly appreciate a bigger nudge in the right direction please.

Thanks once again in advance.

Stewart
 

Aresby

New Member
Ok, I give up ... I have trawled google and nothing!
Ok Stew, I'll give you some pointers (regrettably I can't give you my code because my keypad routine is written in assembler).

I can only guess how you're reading the keypad using ADC - not the usual approach and one to be avoided unless you're an expert. To succeed here you need to understand how a keypad is wired up in a matrix form. Every single keypad is wired up the same way, whether it's your phone or TV remote!

The way to read a keypad (I assume it's a standard 4x3 unit, 0-9 plus * and #) is to connect all 7 wires to 7 separate pins on the PICAXE chip.

Four of those pins (the rows) are OUTPUT pins (eg B0 through B3), the other 3 (the columns) are INPUT pins (eg C0 through C2).

You set each of the OUTPUT row pins high, one at a time; only one row is HIGH at a time.

Between setting each one high you check which (if any) of the INPUT pins have gone high.

This will give you a UNIQUE button key press.

The input value on the 3 INPUT pins will be 000 if no key is pressed, and another value if a key was pressed. For example it will read 100 if key 1 was pressed (and you've wired up the keypad in the convention manner) whilst row 1 was set HIGH.

Once you know which key was pressed, your code logic will simple set the appropriate word variable to whatever value you want. To accept more than one key press to get a 4 figure value your code will be slightly more involved but if you look at the examples I linked you to they all do this as part of the key-lock program.

I can only recommend that you read the material to which I previously pointed you at, create a mini-project to read the keypad and then implement your newly found knowledge into the bigger program. At the moment you're getting bogged down and frustrated because you're not working on a logical part of the project, the keypad reader.

Regrettably, (for you, not me) I'm off on holiday for the best part of 3 weeks when I'll have no access to the PICAXE forum (not if I want to prevent instant divorce, anyway) so I'm hoping someone else may be able to respond here in my absence.

Good luck, and try not to get frustrated at your perceived lack of progress - eventually it will work (as do all projects), especially with the help of forum members who have done this sort of thing many times.

If you haven't resolved it in 3 weeks' time, I'll be back!
 
Top