Linear scale on 20 x 4 oled

bfgstew

Senior Member
OK Nick got me in the right direction with character mapping, but now the code is a scource of trouble.

I am after having a linear scale along the bottom of my 20 X 4 OLED, using a 10K pot and readadc on A.1
Each block on the screen is made up of 5 segments, so in total there are 100 segments, this unfortunately gives a sum of 2.5 per segment as variable is 0 - 255, so 255 / 100 = 2.5 Picaxe doesn't do fractions, so how can I get over this small hurdle?
The code I have been working on, gives me the blocks on the bottom row, but not how I want it. I would like to have it so when the pot is rotated to the right, the scale goes along the screen, rotate pot to the left, scale goes back along the screen.

The code so far - I have only worked on 4 blocks as the code looks like it will be faily lengthy, unless some kind soul can show an easier way?

Code:
#slot3

; picaxe 28x2

symbol SOUND_ON = C.0
symbol CAMERA = C.1
symbol FLASH = C.2
symbol SOUND_IN = A.3
symbol LIGHT_ON = C.4
symbol PG_ON = C.5
symbol TIMER_LED = C.6
symbol READY_LED = C.7
symbol LIGHT_IN = A.0
symbol PG_IN = A.1
symbol SOLENOID = A.2
symbol COL2 = pinB.0
symbol ROW1 = B.1
symbol COL1 = pinB.2
symbol ROW4 = B.3
symbol COL3 = pinB.4 
symbol ROW3 = B.5
symbol ROW2 = B.6
symbol DROPS_LED = B.7

 
	serout C.3, N2400, (254,1)
	pause 50
	high PG_ON
	do
	readadc A.1,b3
	if b3 <= 3 then 
	 serout C.3, N2400,(254,212)
	serout C.3, N2400, (0) endif  
	if b3 =< 5 then 
	 serout C.3, N2400,(254,212)
	serout C.3, N2400, (1) endif
	if b3 =< 7 then 
	 serout C.3, N2400,(254,212)
	serout C.3, N2400, (2) endif
	if b3 =< 10 then 
	 serout C.3, N2400,(254,212)
 	serout C.3, N2400, (3) endif
	if b3 =< 12 then 
	 serout C.3, N2400,(254,212)
	serout C.3, N2400, (4) endif
	if b3 =< 15 then 
	 serout C.3, N2400,(254,212)
	serout C.3, N2400, (4)
	serout C.3, N2400,(254,213)
	serout C.3, N2400, (0) endif
	if b3 =< 18 then 
	serout C.3, N2400,(254,212)
	serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	serout C.3, N2400, (1) endif
	if b3 =< 20 then 
	serout C.3, N2400,(254,212)
	serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	serout C.3, N2400, (2) endif
	if b3 =< 23 then 
	serout C.3, N2400,(254,212)
	serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	serout C.3, N2400, (3) endif
	if b3 =< 25 then 
	serout C.3, N2400,(254,212)
	serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4) endif
	if b3 =< 27 then 
	 serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (0) endif
	if b3 =< 30 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (1) endif
	if b3 =< 33 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
 	 serout C.3, N2400, (2) endif
	if b3 =< 35 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
 	serout C.3, N2400,(254,214)
	 serout C.3, N2400, (3) endif
	if b3 =< 38 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
 	serout C.3, N2400,(254,214)
 	 serout C.3, N2400, (4) endif
	if b3 =< 40 then 
	 serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,215)
	 serout C.3, N2400, (0) endif
	if b3 =< 42 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (4)
 	serout C.3, N2400,(254,215)
	 serout C.3, N2400, (1) endif
	if b3 =< 45 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (4)
 	serout C.3, N2400,(254,215)
	 serout C.3, N2400, (2) endif
	if b3 =< 47 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,215)
	 serout C.3, N2400, (3) endif
	if b3 =< 50 then 
	serout C.3, N2400,(254,212)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,213)
	 serout C.3, N2400, (4)
	 serout C.3, N2400,(254,214)
	 serout C.3, N2400, (4)
 	serout C.3, N2400,(254,215)
	 serout C.3, N2400, (4) endif
										 ; CGRAM addressing for segments and block
serout C.3, N2400, (254, 64, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (0)
serout C.3, N2400, (254, 72, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (1)
serout C.3, N2400, (254, 80, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (2)
serout C.3, N2400, (254, 88, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (3)
serout C.3, N2400, (254, 96, 63, 63, 63, 63, 63, 63, 63, 63) ; whole block = (4)
loop
 
Last edited:

bfgstew

Senior Member
I couldn't get anywhere with the previous code so did some more trawling of the forum and found this code snippet from Hippy, it works great in simulation, but I am struggling to get it to work on my hardware. I have added my bits (pin assignments and character mapping), how do I get them to go on screen (serout C.3,N2400,(254,212) is the place I need the bar to start.
Any help would be gratefully received, thanks.
Stewart

Code:
;picaxe 28x2
#slot3
symbol SOUND_ON = C.0 ; sound input mode on
symbol CAMERA = C.1   ; camera output
symbol FLASH = C.2    ; flash output
symbol SOUND_IN = A.3 ; sound input
symbol LIGHT_ON = C.4 ; LDR mode on
symbol PG_ON = C.5    ; Photogate mode on
symbol TIMER_LED = C.6; timer mode on
symbol READY_LED = C.7; system ready led
symbol LIGHT_IN = A.0 ; LDR input
symbol PG_IN = A.1    ; Photogate input
symbol SOLENOID = A.2 ; Solenoid output
symbol COL2 = pinB.0  ; keypad matrix
symbol ROW1 = B.1     ; keypad matrix
symbol COL1 = pinB.2  ; keypad matrix
symbol ROW4 = B.3     ; keypad matrix
symbol COL3 = pinB.4  ; keypad matrix
symbol ROW3 = B.5     ; keypad matrix
symbol ROW2 = B.6     ; keypad matrix
symbol DROPS_LED = B.7; solenoid mode on


Symbol CHARS     = 20 ' 20 character display

Symbol adc       = b3
Symbol pixelsOn  = b4
Symbol charsOn   = b5
Symbol charsToDo = b6
high c.5
Do
  ReadAdc A.1, adc
  SerTxd( #adc, 9 )
  pixelsOn = CHARS * 5 - 1 * adc / 255 + 1
  charsOn = pixelsOn / 5
  pixelsOn = pixelsOn // 5
  charsToDo = CHARS - charsOn
  Do While charsOn > 0
    SerTxd( "#" )
    charsOn = charsOn - 1
  Loop
  If pixelsOn <> 0 Then
    SerTxd( #pixelsOn )
    charsToDo = charsToDo - 1
  End If
  Do While charsToDo > 0  
    SerTxd( "_" )
    charsToDo = charsToDo - 1
  Loop
  SerTxd( CR, LF )
  Pause 500
Loop

serout C.3, N2400, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)										 ; CGRAM addressing for segments and block
serout C.3, N2400, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
serout C.3, N2400, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
serout C.3, N2400, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
serout C.3, N2400, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
serout C.3, N2400, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
 

bfgstew

Senior Member
So far all I can get is the first 'block' coming up with blank,1,2,3,4 or a complete block, depending on the pot position, also it is blinking.
So at least the pot is being 'read', how do I get it to display segments of the block instead of numbers and to progress along when the pot is turned?

Code:
;picaxe 28x2
#slot3
symbol SOUND_ON = C.0 ; sound input mode on
symbol CAMERA = C.1   ; camera output
symbol FLASH = C.2    ; flash output
symbol SOUND_IN = A.3 ; sound input
symbol LIGHT_ON = C.4 ; LDR mode on
symbol PG_ON = C.5    ; Photogate mode on
symbol TIMER_LED = C.6; timer mode on
symbol READY_LED = C.7; system ready led
symbol LIGHT_IN = A.0 ; LDR input
symbol PG_IN = A.1    ; Photogate input
symbol SOLENOID = A.2 ; Solenoid output
symbol COL2 = pinB.0  ; keypad matrix
symbol ROW1 = B.1     ; keypad matrix
symbol COL1 = pinB.2  ; keypad matrix
symbol ROW4 = B.3     ; keypad matrix
symbol COL3 = pinB.4  ; keypad matrix
symbol ROW3 = B.5     ; keypad matrix
symbol ROW2 = B.6     ; keypad matrix
symbol DROPS_LED = B.7; solenoid mode on


Symbol CHARS     = 20 ' 20 character display

Symbol adc       = b3
Symbol pixelsOn  = b4
Symbol charsOn   = b5
Symbol charsToDo = b6
Serout C.3,N2400,(254,1)
high C.5              
Do
  ReadAdc A.1, adc
  pixelsOn = CHARS * 5 - 1 * adc / 255 + 1
  charsOn = pixelsOn / 5
  pixelsOn = pixelsOn // 5
  charsToDo = CHARS - charsOn
  Do While charsOn > 0
    Serout C.3,N2400,(254,212,5)
    charsOn = charsOn - 1
  Loop
  If pixelsOn <> 0 Then
    Serout C.3,N2400,(254,212,#b4)
    charsToDo = charsToDo - 1
  End If
  Do While charsToDo > 0  
    Serout C.3,N2400,(254,212,0)
    charsToDo = charsToDo - 1
  Loop
   Loop
 


										 ; CGRAM addressing for segments and block
serout C.3, N2400, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)	 
serout C.3, N2400, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
serout C.3, N2400, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
serout C.3, N2400, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
serout C.3, N2400, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
serout C.3, N2400, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
Code adjusted to how I thought it should be.........................:confused:
 

nick12ab

Senior Member
I couldn't get anywhere with the previous code so did some more trawling of the forum and found this code snippet from Hippy
Was that code snippet really Hippy's, with the serout commands that set the CGRAM positioned after the loop where it will never execute?

I tried the code you last posted, and it didn't work. I decided not to bother save the code and fix it, but make my own version instead. CHange the symbol definitions to match your configuration.
Code:
#picaxe 28x2
#no_data
symbol lcdpin = C.3
symbol adcpin = C.2
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol lcdsize = 16
main:
	pause 10
	serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)	 
	serout lcdpin, N2400_8, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
	serout lcdpin, N2400_8, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
	serout lcdpin, N2400_8, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
	serout lcdpin, N2400_8, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
	serout lcdpin, N2400_8, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
	do
		readadc adcpin,readvar
		length = lcdsize * 5 - 1 * readvar / 255 + 1
		serout lcdpin,N2400_8,(254,128,#length," ",254,192)
		charactercounter = lcdsize
		do
			if length => 5 then
				serout lcdpin,N2400_8,(13)
				length = length - 5
				dec charactercounter
			else
				exit
			end if
		loop
		readvar = length + 8
		serout lcdpin,N2400_8,(readvar)
		for loopcounter = 0 to charactercounter
			serout lcdpin,N2400_8,(32)
		next
	loop
Here's a modified version which I decided to do because the original looked a bit strange because it isn't actually properly linear due to the gap between each character which is about one pixel wide. This version addresses that.
Code:
#picaxe 28x2
#no_data
symbol lcdpin = C.3
symbol adcpin = C.2
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol lcdsize = 16
main:
	pause 10
	serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)	 
	serout lcdpin, N2400_8, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
	serout lcdpin, N2400_8, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
	serout lcdpin, N2400_8, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
	serout lcdpin, N2400_8, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
	serout lcdpin, N2400_8, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
	do
		readadc adcpin,readvar
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		serout lcdpin,N2400_8,(254,128,#length," ",254,192)
		charactercounter = lcdsize
		do
			if length => 6 then
				serout lcdpin,N2400_8,(13)
				length = length - 6
			elseif length = 5 then
				serout lcdpin,N2400_8,(13)
				length = length - 5
			else
				exit
			end if
			dec charactercounter
		loop
		readvar = length + 8
		serout lcdpin,N2400_8,(readvar)
		for loopcounter = 0 to charactercounter
			serout lcdpin,N2400_8,(32)
		next
	loop
 

nick12ab

Senior Member
Or if you want something a bit more fancy...
Code:
#picaxe 18m2
#no_data
symbol lcdpin = C.3
symbol adcpin = C.2
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol endposition = b8

symbol lcdsize = 14

	setfreq m8
	pause 200
	serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 53, 32, 32, 32, 32)		'8
	serout lcdpin, N2400_8, (254, 72, 32, 48, 48, 53, 48, 48, 32, 32)		'9
	serout lcdpin, N2400_8, (254, 80, 32, 52, 52, 53, 52, 52, 32, 32)		'10
	serout lcdpin, N2400_8, (254, 88, 32, 53, 53, 53, 53, 53, 32, 32)		'11
	serout lcdpin, N2400_8, (254, 96, 34, 39, 47, 49, 47, 39, 34, 32)		'12
	serout lcdpin, N2400_8, (254, 104, 40, 60, 58, 49, 58, 60, 40, 32)	'13
	endposition = lcdsize + 193
main:
	do
		readadc adcpin,readvar
		length = lcdsize * 3 - 1 * readvar / 255 + 1
		serout lcdpin,N2400_8,(254,128,#length," ",254,endposition,13,254,192,12)
		charactercounter = lcdsize
		do
			dec charactercounter
			if length > 3 then
				serout lcdpin,N2400_8,(11)
				length = length - 3
			else
				exit
			end if
		loop
		readvar = length + 8
		serout lcdpin,N2400_8,(readvar)
looplabel:
		if charactercounter > 0 then
			serout lcdpin,N2400_8,(8)
			dec charactercounter
		else
			goto main
		end if
		goto looplabel
	loop
lcdsize has to be two less than the actual number of characters on the LCD line.

Also in the previous examples, you need to increase the pause at the start of the program, otherwise the CGRAM won't be set properly on a 'cold boot'.
 

bfgstew

Senior Member
Thanks Nick, tried the code in #6 and after a few tweaks it works. Only tried indoors in artificial light, will see how it reacts in daylight very soon.
Will have a look at the code in #7 see how that looks as well.

Many thanks for your kindness and time in helping me out, much appreciated.

Stewart
 

nick12ab

Senior Member
What was Hippy's actual code? If my code is original enough, then I'll post it in the finished projects area.
 

hippy

Technical Support
Staff member
So far all I can get is the first 'block' coming up with blank,1,2,3,4 or a complete block, depending on the pot position
Because you are using 254,212 in every output command to the LCD, all 20 characters which form the bar graph are forced into the first character position.
 

bfgstew

Senior Member
Knew it was a mistake on my part Hippy, to be honest I didn't quite understand the code and how it flowed so it was a bit of a stab in the dark to get it to work.....................'stands in corner with dunces cap on'
 

hippy

Technical Support
Staff member
Assuming the CGRAM charcters have been initialised, the code should be something like (untested) ....

Code:
Do
  ReadAdc A.1, adc
  SerOut lcdpin, N2400_8, ( 254, 212 )
  pixelsOn = CHARS * 5 - 1 * adc / 255 + 1
  charsOn = pixelsOn / 5
  pixelsOn = pixelsOn // 5
  charsToDo = CHARS - charsOn
  Do While charsOn > 0
    SerOut lcdpin, N2400_8, ( 5 )
    charsOn = charsOn - 1
  Loop
  If pixelsOn <> 0 Then
    SerOut lcdpin, N2400_8, ( pixelsOn )
    charsToDo = charsToDo - 1
  End If
  Do While charsToDo > 0  
    SerOut lcdpin, N2400_8, ( 0 )
    charsToDo = charsToDo - 1
  Loop
  Pause 500
Loop
 

bfgstew

Senior Member
Quality piece of work Nick, I like the 'unique' version, very effective.
Once again, a BIG thank you.
 

bfgstew

Senior Member
Ok, I need help again!!!!!! ................'Groan, not again', I can hear you all say!

The bargraph is superb, thanks to Nick and Hippy for that.
Now, the intention of it is to show, via a pot, a linear scale of the input seen by the Picaxe of a photogate (3 P/T's in a frame), now if the pot is turned to the left a low input is seen and to the right a higher input. Now I need to trigger the opto when a certain 'level' is seen, ideally I would like to have a 25% of the input value to be the trigger threshold, so when a high input is seen a higher drop is needed, and a lower input a lower drop is needed (basically its to act as a sensitivity pot/scale).
I have added the variable - triggerthreshold into the code, and a sertxd command to see what value I am geting, but ti always seems to end up at zero and not allow me to come out of th eloop and onto the trigger sub.
Any ideas please?

Code:
#slot2

;#PICAXE 28X2 photogate
 
symbol SOUND_ON = C.0
symbol CAMERA = C.1
symbol FLASH = C.2
symbol SOUND_IN = A.3
symbol LIGHT_ON = C.4
symbol PG_ON = C.5
symbol TIMER_LED = C.6
symbol READY_LED = C.7
symbol LIGHT_IN = A.0
symbol PG_IN = A.1
symbol SOLENOID = A.2
symbol COL2 = pinB.0
symbol ROW1 = B.1
symbol COL1 = pinB.2
symbol ROW4 = B.3
symbol COL3 = pinB.4 
symbol ROW3 = B.5
symbol ROW2 = B.6
symbol DROPS_LED = B.7

symbol key_pos = b0        ; VARIABLES CONFIGURATION
symbol key_value = b1
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol triggerthreshold = b8
symbol trigger = b9
symbol lcdsize = 20


INIT:
		serout C.3,N2400,(254,1)
	pause 500
	serout C.3,N2400,(254,128,"SET SENS BY TURNING")
	serout C.3,N2400,(254,192,"POT TO DESIRED POS")
	serout C.3,N2400,(254,148,"RIGHT LOW, LEFT HIGH")
	serout C.3,N2400,(254,212,"")
	do
	gosub GKP
	loop until key_value = 12
	
SETTING:
		serout C.3,N2400,(254,1)
	pause 50
	high C.5
	pause 50
	serout C.3, N2400, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)	 
	serout C.3, N2400, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
	serout C.3, N2400, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
	serout C.3, N2400, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
	serout C.3, N2400, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
	serout C.3, N2400, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
	do
		readadc A.1,readvar
		
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		serout C.3,N2400,(254,192,#readvar,254,148,#length," ",254,212)
		charactercounter = lcdsize
		do
			if length => 6 then
				serout C.3,N2400,(13)
				length = length - 6
			elseif length = 5 then
				serout C.3,N2400,(13)
				length = length - 5
			else
				exit
			end if
			dec charactercounter
		loop
		let triggerthreshold = readvar
		triggerthreshold = triggerthreshold / 100 * 75
		sertxd(#triggerthreshold,cr,lf)
	if readvar = triggerthreshold then goto main6	
		readvar = length + 8
		serout C.3,N2400,(readvar)
		for loopcounter = 0 to charactercounter
			serout C.3,N2400,(32)
		
		next 

	serout C.3,N2400,(254,128,"WAITING FOR TRIGGER")

	loop

main6:
	                   high camera : high flash : high READY_LED
	                    pause 100
	                    

	                     low camera : low flash
	                     low READY_LED
	                     low PG_ON
	    	        goto Init
	    	        
GKP:
 	 Do
    		Gosub GTKP			' Wait until no key pressed
  			Loop Until key_value = 0
 	 Do
   		 Gosub GTKP			' Wait until key pressed
  			Loop Until key_value <> 0
  			If key_value = 11 Then
    			key_value = 0
  		End If
  	Return		
GTKP:	;Keypad scan coding
		key_pos = 0
		key_value = 0
	 	High ROW1 : gosub ScanCol : low ROW1
	 	High ROW2 : gosub ScanCol : low ROW2
	 	High ROW3 : gosub ScanCol : low ROW3 
	 	High ROW4 : gosub ScanCol : low ROW4
	 	Return	 	
	 	ScanCol:
	 		if COL1 = 1 then : key_value = key_pos + 1 : endif
	 		if COL2 = 1 then : key_value = key_pos + 2 : endif
	 		if COL3 = 1 then : key_value = key_pos + 3 : endif
	 		key_pos = key_pos + 3   
   		return
 

bfgstew

Senior Member
Thanks Hippy for that, will give it a go when I can find the bloomin' download cable, seems to have sprouted legs and done a runner! Last thing I needed...................:mad:
 

bfgstew

Senior Member
Thinking about this, the problem may be that as I am reading the adc value into readvar, then getting triggerthreshold to = readvar, that will then either increase or decrease as the readvar does as it is the same thing? So what ever value I put in triggerthreshold it will always go down (or up) = to the formula given wether it is / 100 * 75 or * 75 / 100. Does this make sense? Ideally the triggerthreshold value needs to be a constant rather than a copy of a variable.
 

bfgstew

Senior Member
Ok I am beggining to give up on this one, so any help would be really helpful..........................please!

The code for the bargraph kindly done by Nick is brilliant, but I cannot get my trigger value to work.
Bargraph shows the value of the readadc into A.1 (readvar), (0 to 255).
What I need is to take a percentage of readvar, say 25% and use that as a trigger threshold, so if readvar is 200 the trigger threshold will be 150 and if readvar is 40 the trigger treshold will be 30, so in theory it acts as a sensitivity scale for the trigger threshold.
Now is there anyway of creating this, because I have hit a big brick wall on this and am well and truly stuck.
Code is as #15

Thanks in advance.

Stewart
 

Technical

Technical Support
Staff member
You must remember that PICAXE only use 'whole' integers. Therefore if you divide by 100 first, you will loose most of the resolution you want in the fractional part that is completely lost.
So / 100 * 75 is NOT the same as * 75 / 100, they don't give the same result with integer maths.

So to get a threshold value of 75% of a particularly number use * 75 / 100
 

bfgstew

Senior Member
I get that bit and using the sertxd command I can see the correct value in PE. The bit that is the sticking point is that when readvar reduces via a 10K pot so does triggerthreshold as it is the same value, but when I break the IR beam, readvar reduces again, so does triggerthreshold so I never get readvar to equal triggerthreshold and so trigger my camera.
Think of it as 2 lines, readvar goes from 0 to 255, this is variable as it reads from 10K pot
triggerthreshold goes from 0 to 190 this I need to keep as a line from 0 to 190 in relation to readvar, but not change when readvar does, so when beam is broken, readvar will drop below this line and cause a trigger.
 

westaust55

Moderator
FOr the trigger value you cannot base that on the "current" READADC value as you have the problem you are experiencing with the trigger level floating with the measure value.
Try setting up a separate READADC to record a value relative to a background level and use that to set the trigger level.
If the background level can vary over time, then maybe consider taking several reading from time to time and average those to define a new trigger value.

I/we do not know what the "background" level is and how variable that is to determine the ideal method of determining a trigger level. Needs more clear information about the applciation from your side first.
 

bfgstew

Senior Member
Ok this is the application - http://www.picaxeforum.co.uk/showthread.php?20577-Water-drop-controller/page27&highlight=water+drop, basically it is a photogate, anything passing through should trigger my camera. Reading the input value on A.1 using readadc, to go lower than the trigger threshold value, then trigger the opto connected to the camera.
It will run in daylight so ambient light will effect readadc value, it will also run in darkness but will be at a steady level due to just receiving light from the IR led's.
Ideally if I can get this to work, is to have the ability to trigger anything from a small fly/moth to a bird.
 

Paix

Senior Member
Save me reading too much of the 27 pages of your thread that ceased back in July. What are the the inside dimensions of your photogate please, are we talking 10cm, 50cm or 150cm square?

You mention background IR interence, so how about a fast pulse train and missing pulse detection, or just rectifying, filtering and then applying the signal to your ADC, would this not prove to be more reliable with less interference from background IR?

Good to know a few more details are coming to light. It makes the guessing so much easier. I will read your other thread (maybe) when I get back in later.
 

bfgstew

Senior Member
The photogate is 6" x 4" at the moment, I am hoping to build a bigger one in the future, I just want to get this one working first!
 

Paix

Senior Member
I have a slightly better idea of your opus now Stewart. after 9 months it must be about to be born :)

I think that your quest to get the most out of everything might do you a disservice here. I'm sure that you can find another use for that spare pin and maybe consider using a second PICAXE for the photogate function, as I'm sure that you are likely to compromise the rest of the edifice if you insist on shoe horning it in. it probably isn't impossible, but maybe a tad unwise.

My understanding is that the photogate's function is to to act as a trigger when something passes though it, large or small. So the bird won't be a chicken then at 6" x 4".

As has been said earlier, in the other thread, you really need to use modulated IR which at the receiver can be filtered and the envelope recovered to detect the volume/beam break, due to insects, water droplets or even small birds . . . Further I believe that a single detector and probably a single emitter is required to maintain the clarity of the pulse train, possibly with path reflection to achieve coverage.

I have to confess that I think that this aspect of your project is not trivial. I would go with the modulated IR LED and single sensor on a tight beam break/interference basis and treat advances as a separate project. Good luck with your endeavours and top marks for pursuing and sticking with your project since February.
 

bfgstew

Senior Member
Thanks Paix,

Been at it on and off since Feb but not devoted a great deal of time to it but I will not let it beat me, this project will work, just must stop adding stuff on to it...............LOL
I have some other IR units that I may have a trial with, see how that fairs.
 

bfgstew

Senior Member
Ok, looked at 'modulated IR' and presume this involves using PWM? Now how can I get the P/T's to 'look' for this, what sort of hardware/circuit would I need to take this to the next step?

PT%20SCHEMATIC.jpg

This is the circuit at the moment.

Edit the 20 X 2 to 28 X 2 and readadc onto A.1
 
Last edited:

hippy

Technical Support
Staff member
The bit that is the sticking point is that when readvar reduces via a 10K pot so does triggerthreshold as it is the same value, but when I break the IR beam, readvar reduces again, so does triggerthreshold so I never get readvar to equal triggerthreshold and so trigger my camera.
Is the problem not simply that you are setting the threshold after the instantaneous ambient reading when you ought to be using some prior ( or averaged ) reading of the ambient ?

Basically; is the level now below 75% of what it is ? The answer will always be no. Is the level below 75% of what it was you can determine.
 

eclectic

Moderator
And now for something completely different. ;-)

This is NOT meant as definitive, but
as a simple circuit to play with.

AXE091 board / 20M2 (could be any other modern PICAXE).

IR LED connected to pin B.1 at 40kHz pwmout.

TSOP receiver connected to pin C.1

It sits and waits until the "beam" is broken.

Code:
#picaxe 20M2
; AXE091 board

;B.1 connected to IR LED
;C.1 connected to TSOP IR receiver

setfreq M32 ; for fastest response
pwmout B.1, 199, 400 ;40kHz pwmout

Setint %00000010, %00000010  ; interrupt on pin C.1 high

main:

 sertxd (".","") ;waiting

goto main

Interrupt:

sertxd ("Zap",cr, lf)

pause 100

; vary pause to enable shutter to function
; and beastie to fly away

Setint %00000010, %00000010  ; re-enable interrupt on pin C.1 high

return
And Stewart, something else to think about......

It's a controlled enclosed situation, and you're a sensible grown-up,
so how about a cheap LASER pencil as the transmitter?

A quick Internet search shows some very sophisticated amateur units.

And, Forum search
BPW34

e
 

Paix

Senior Member
Some while ago I picked up in Poundland an orange and black coloured (for identification) laser level. The red beam shone through a glass rod to make the light output a flat blade shape. It might be of use with multiple reflections to give you the photogate coverage that you seek.
 

bfgstew

Senior Member
Is the problem not simply that you are setting the threshold after the instantaneous ambient reading when you ought to be using some prior ( or averaged ) reading of the ambient ?
No, because ambient light doesn't effect it that much, and even in the dark the problem exists..
I shall try to explain - switch on, adjust pot to high or low , bargraph shows actual reading on screen also via serout and sertxd, so there is no confusion of what is being seen and read.
Put an object through the photogate you can see the value drop, works fine, no problem. The problem is trying to get a workable sensitivity scale value into triggerthreshold and when readvar drops below it to set the trigger off. Now I am saying a 25% bandwidth drop between readvar and triggerthreshold just as a simple math figure but it could be any value. So if readvar is 100, then triggerthreshold will be 75, and if readvar is 10, then triggerthreshold will be 7, and if readvar is 255, then triggerthreshold will be 191. This gives a reasonable spread across the range so, if I am after a large moth or other prey, I don't want tiny insects triggering it, so set at the higher value, conversly if I want to catch small prey, a lower setting would be used so they can set the trigger off easily.
So the question is, how to set a value for triggerthreshold that is not influenced by anything but is able to be in relation to the readvar variable?
eg - if readvar = 100 then triggerthreshold = 75 this will be incorrect because as an object passes through the photogate, the value in readvar drops and so does triggerthreshold because of the last statement, if the last statement can be written so that triggerthreshold is not effected by what happens to readvar we would have the right result.
I hope this makes sense and thanks for the help given.

Stewart
 

bfgstew

Senior Member
E
Thanks for the pointer to the AXE091, not even seen it and would be an invaluable tool for me, albeit on the expensive side, so may have to save my pennies up first.
The laser idea has been floating around in my head for a while but never really took it to heart until now and again may prove to be a potent tool, especially for a larger 'gate' so shall have a go at making a working model on the 091.
Thanks also for the PWM code, I have read the manual on it, but a bit advanced for me at the moment, still when I get the 091 and my DPscope built I shall be armed to the teeth with technology on my side and shall defeat any problem in my way!!!!!!!
 

bfgstew

Senior Member
I may have answer for this problem, albeit not ideal, but how about if I input a triggerthreshold value manually?


Off to have a go at coding this.................:rolleyes:
 

Paix

Senior Member
Do you realise just how many chocolate bars it takes for a reliable manual adjustment mechanism to work properly?

My, the AXE091 seems to be a bit of a Rolls Royce job. I get by with the AXE029 and because I use it with 08M/M2 chips, which it wasn't designed for as well as 18M2, I just waste three strips at the head of my breadboard and patch the Gnd, Tx and Rx leads to where I want them on the chips - sorry Technical, but Green for ground, white for TX and red for RX is just fine for me and it fits the 18M2 as designed so I'm a happy chappie. Doubtless I will eventually accumulate some of the standard add on fixtures that make life simple, but gradually as I need them.

But I am not in the position of having to provide others with the peripheral items to make their projects work with the minimum fuss in a reasonably tight timescale.

Horses for courses and my steed is either Rocinante or Sancho Panza's donkey.

Personally I favour Eclectic's idea with the laser, but the red level one from £Poundland and modulate it. Receive it with a photodiode, couple the signal with a capacitor to block DC and process the received signal via a rectifier and capacitor (envelope detector). You can adjust the sensitivity by adding a resistor to modify the CR time of the detector which could then be presented to the interrupt pin as suggested by e. You could even make the resistor a pot and put a knob on cut from the nozzle and cap of a toothpaste tube, for street cred - get a child or a sibling(birthday present) to use the Basics 25p toothpaste quickly so that you can harvest your instrument knob. More money saved towards an AXE001 or half a chocolate bar :)
Photo Detector.jpg
 
Last edited:

bfgstew

Senior Member
I love chocolate bars........................................:p

I agree the AXE091 is a bit OTT and would prefer if they had smaller kits, but, why not, if it helps development, and aids design, I am all for it.

I agree with the laser idea and will utilize it at some stage, but I want to get this part working, how I want it to. I do not like giving up, unless I get a point blanker off someone saying so. This will work, I am confident, then I shall move on to the next step.

Like the idea of the toothpaste tube cap! Brush the dog's teeth so it looks rabid and can have the cap then, saves me 75p........................:cool:

Cheers for the schematic Paix, will breadboard it on the AXE091 when it comes...........LOL
 

bfgstew

Senior Member
OK, so near, yet so far.

Added a few lines to the coding and I am just about there, the problem is, that with the insertion of the 'gosub TT' routine the bargraph doesn't move, I understand that because the routine has taken it out of the loop, how can I have it so the bargraph still moves and also have the 'gosub TT' routine in?
Added the variable readvar1 to show the threashold value of readvar (readvar1 = readvar * 75 / 100), this is displayed on screen as 'COPY' then with the 'gosub TT' routine you add the value 'COPY' into 'THREASHOLD' then it's set and ready for a trigger.
This does work albeit for the bargraph not moving until the gosub TT routine has returned.

Code:
#slot2
#freqm4
;#PICAXE 28X2 photogate
 
symbol SOUND_ON = C.0
symbol CAMERA = C.1
symbol FLASH = C.2
symbol SOUND_IN = A.3
symbol LIGHT_ON = C.4
symbol PG_ON = C.5
symbol TIMER_LED = C.6
symbol READY_LED = C.7
symbol LIGHT_IN = A.0
symbol PG_IN = A.1
symbol SOLENOID = A.2
symbol COL2 = pinB.0
symbol ROW1 = B.1
symbol COL1 = pinB.2
symbol ROW4 = B.3
symbol COL3 = pinB.4 
symbol ROW3 = B.5
symbol ROW2 = B.6
symbol DROPS_LED = B.7

symbol key_pos = b0        ; VARIABLES CONFIGURATION
symbol key_value = b1
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol readvar1 = b8
symbol triggerthreashold = b10
symbol lcdsize = 20
setfreq em16


INIT:

let b10 = 0
let b0 = 0
let b1 = 0
let b4 = 0
let b5 = 0
let b6 = 0
let b7 = 0
		serout C.3,N2400_16,(254,1)
	pause 30
	serout C.3,N2400_16,(254,128,"TURN POT TO DESIRED")
	serout C.3,N2400_16,(254,192,"POSITION, THEN ENTER")
	serout C.3,N2400_16,(254,148,"THE 'COPY' VALUE INTO")
	serout C.3,N2400_16,(254,212,"THREASHOLD THEN HIT #")
	pause 3000
	serout C.3,N2400_16,(254,1)
	pause 30
	serout C.3,N2400_16,(254,128,"THE LOWER THE NUMBER")
	serout C.3,N2400_16,(254,192,"THE HIGHER THE SENS")
	serout C.3,N2400_16,(254,148,"THE HIGHER THE NUMBER")
	serout C.3,N2400_16,(254,212,"THE LOWER THE SENS")
	do
	gosub GKP
	loop until key_value = 12

	
SETTING:
		serout C.3,N2400_16,(254,1)
	pause 50
	high C.5
	pause 50
	serout C.3, N2400_16, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)	 
	serout C.3, N2400_16, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
	serout C.3, N2400_16, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
	serout C.3, N2400_16, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
	serout C.3, N2400_16, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
	serout C.3, N2400_16, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
	do
		readadc A.1,readvar
	
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		readvar1 = readvar * 75 / 100
			serout C.3,N2400_16,(254,128,"    SENSITIVITY")
		serout C.3,N2400_16,(254,192,#triggerthreashold," ","THREASHOLD",254,148,#readvar1," ","COPY",254,158,#readvar," ","ACTUAL",254,212)
		charactercounter = lcdsize
		do
			if length => 6 then
				serout C.3,N2400_16,(13)
				length = length - 6
			elseif length = 5 then
				serout C.3,N2400_16,(13)
				length = length - 5
			else
				exit
			end if
			dec charactercounter 
		loop 
		
		if readvar <= triggerthreashold then goto main6

		readvar = length + 8
		serout C.3,N2400_16,(readvar)
		for loopcounter = 0 to charactercounter
		if triggerthreashold = 0 then gosub TT7
			serout C.3,N2400_16,(32)
		
		next
	
	loop
		

main6:
				 high READY_LED
	                   high camera : high flash
	                    pause 100
	                    

	                     low camera : low flash
	                     low READY_LED
	                     low PG_ON
	    	        goto Init
	    	        
GKP:
 	 Do
    		Gosub GTKP			' Wait until no key pressed
  			Loop Until key_value = 0
 	 Do
   		 Gosub GTKP			' Wait until key pressed
  			Loop Until key_value <> 0
  			If key_value = 11 Then
    			key_value = 0
  		End If
  	Return		
GTKP:	;Keypad scan coding
		key_pos = 0
		key_value = 0
	 	High ROW1 : gosub ScanCol : low ROW1
	 	High ROW2 : gosub ScanCol : low ROW2
	 	High ROW3 : gosub ScanCol : low ROW3 
	 	High ROW4 : gosub ScanCol : low ROW4
	 	Return	 	
	 	ScanCol:
	 		if COL1 = 1 then : key_value = key_pos + 1 : endif
	 		if COL2 = 1 then : key_value = key_pos + 2 : endif
	 		if COL3 = 1 then : key_value = key_pos + 3 : endif
	 		key_pos = key_pos + 3   
   		return	
   		

			
TT7: ;Coding to change the pause time via keypad
		
		
		For b33 = 1 to 4				
  			Gosub GKP
  			if key_value = 12 then return
  			endif 
  			pause 30	
  			b10 = b10 * 10 + b1
  			serout C.3,N2400_16,(254,192,#b10)
  			pause 30
  			next b33
 		Return
Sorry this is the gosub TT part.

Code:
if triggerthreashold = 0 then gosub TT7
 
Last edited:
Top