Results 1 to 3 of 3

Thread: Controlling and application with both IR and a rotary encoder

  1. #1
    Senior Member
    Join Date
    Jan 1970
    Location
    Cambridge, UK
    Posts
    400

    Default Controlling an application with both IR and a rotary encoder

    This is code I developed to re-engineer the user input to my amplifier. The idea is that control is either by an amp mounted rotary encoder, or by a infra red remote.

    The issue with this is that the IR input routines are blocking so must be run on a separate picaxe and that the encoder debounce routines can be difficult.

    The IR input is handled by an 08M2 (08M should work with minor mods)

    Code:
    #picaxe 08M2
    setfreq M8
    symbol last=b1
    symbol repcount=b2
    symbol pauselength=w2
    main:
    irin c.3,b0
    if b0<9 then 
    	b0=b0+49 'convert to an ascci number
    	gosub rep
    	sertxd (b0)
    	b0=255
    endif
    if b0=9 then
    	b0=48 'convert to an ascci number
    	gosub rep
    	sertxd (b0)
    	b0=255
    endif
    if b0>15 and b0<29 then
          b0=b0+49 ' convert to capital A to M
          if b0="C" then: b0=">" :endif
          if b0="D" then: b0="<" :endif
    	gosub rep
          sertxd (b0)
    	b0=255
    endif
    if b0>50 and b0<57 then
          b0=b0+27 ' convert to capital N to S
    	gosub rep
          sertxd (b0)
    	b0=255
    endif
    if b0>75 and b0<83 then
          b0=b0+8 ' convert to capital T to Z
    	gosub rep
          sertxd (b0)
    	b0=255
    endif
    if b0>115 and b0<118 then
          b0=b0-45 ' convert to capital G and H
    	gosub rep
          sertxd (b0)
    	b0=255
    endif
    if b0=37 then
    	gosub rep
          sertxd ("P")' convert to capital P
    	b0=255
    endif
    if b0=101 then
    	gosub rep
          sertxd ("R")' convert to capital R
    	b0=255
    endif
    if b0=96 then
    	gosub rep
          sertxd ("X")' convert to capital X
    	b0=255
    endif
    if b0=35 then
    	gosub rep
          sertxd ("Y")' convert to capital Y
    	b0=255
    endif
    if b0=99 then
    	gosub rep
          sertxd ("C")' convert to C
    	b0=255
    endif
    if b0=40 then
    	gosub rep
          sertxd ("D")' convert to D
    	b0=255
    endif
    'sertxd (b0,last,cr,lf)
    pauselength=repcount*repcount * 2
    pauselength=500-pauselength
    pause pauselength
    goto main
    
    rep:
    	if b0<>last then 
    		repcount=0
    	else
    		repcount=repcount + 1 max 15
    	endif
    	last=b0
    return
    This just reads the codes off the input and recodes them to standard ascii characters which it sends out on the serial output. I'm using my standard Sony TV remote to control the amplifier. The code includes an "acceleration" algorithm to separate individual button pushes but also allow continuous presses for scrolling up and down the volume.

    The main processor listens to the serial port but also handles the encoder totally at the interrupt level. My original routines for this http://www.picaxeforum.co.uk/showthr...nterrupt-issue were blocking whilst the encoder completed a cycle but this would have caused inputs from the IR to be delayed if the encoder was left in a mid cycle state rather than at the detent (easy to do) so I have recoded them to exit all interrupts immediately but still only report the user event on cycle completion. The interrupt routine feeds the encoder output into the hardware serial buffer so that the main code only has one place to look for data and doesn't care where it arrives from.

    Code:
    #picaxe 28X2
    setfreq m8
    symbol resetenc=bit0
    symbol switchison = bit2
    symbol rotatedleft=bit3
    symbol rotatedright=bit4
    symbol scratch=b1
    symbol switched = b2
    '
    'Connections
    ' Encoder switch pulled high and connected to A.1 
    ' Encoder output1 pulled high and connected to A.2 
    ' Encoder output2 pulled high and connected to A.3 
    '
    '
    symbol interruptmask = %00001110 ' allow interrupts on a.3,a.2, a.1
    symbol rotated =       %00000110
    symbol clicked       = %00000001 ' mask to test for c.1 high
    '
    symbol true=1
    symbol false=0
    '
    hsersetup B9600_8,1
    dirsa=0
    ptr=0
    switchison=false
    rotatedright=false
    rotatedleft=false
    resetenc=true
    setint OR 0,interruptmask,A
    do
    	do while ptr<>hserptr
    		b10=@ptrinc
    		sertxd (b10) 'Do required control actions here
    	loop
    	'do required background actions here
    loop
    
    
    interrupt:
    	switched=pinsa & interruptmask >> 1'look at just the three inputs
    	on switched goto I0,I1,I2,I3,I4,I5,I6,I7 'whatever the cause set the next interrupt to look for a reverse
    I0:
    	setint OR 14,interruptmask,A 
    goto proc
    I1:
    	setint OR 12,interruptmask,A 
    goto proc
    I2:
    	setint OR 10,interruptmask,A 
    goto proc
    I3:
    	setint OR 8,interruptmask,A 
    goto proc
    I4:
    	setint OR 6,interruptmask,A 
    goto proc
    I5:
    	setint OR 4,interruptmask,A 
    goto proc
    I6:
    	setint OR 2,interruptmask,A 
    goto proc
    I7:
    	setint OR 0,interruptmask,A 
    proc:
    	scratch=switched & clicked
    	if scratch=0 then
    		switchison=true
    	else
    		if switchison=true then 
    			put hserptr,"A"
    			hserptr=hserptr+1  & $03FF
    			switchison=false
    		endif
    	endif	
    '
    	scratch=switched & rotated >>1
    	on scratch goto R0,R1,R2,R3
    R0:
    	if rotatedleft=true then
    		put hserptr,"<"
    		hserptr=hserptr+1  & $03FF
    		rotatedleft=false
    	endif
    	if rotatedright=true then
    		put hserptr,">"
    		hserptr=hserptr+1  & $03FF
    		rotatedright=false
    	endif
    	return
    R1:
    	if resetenc=true then
    		rotatedleft=true
    		rotatedright=false
    		resetenc=false
    	endif
    	return
    R2:
    	if resetenc=true then
    		rotatedright=true
    		rotatedleft=false
    		resetenc=false
    	endif
    	return
    R3:
    	rotatedleft=false
    	rotatedright=true
    	resetenc=true
    return
    Last edited by matherp; 04-03-2012 at 16:14.

  2. #2
    Senior Member
    Join Date
    May 2011
    Location
    Atlanta, GA
    Posts
    773
    Blog Entries
    24

    Default

    Brilliant. Tossing a second PICAXE at a problem is a good way to deal with blocking commands. Future versions of PICAXE firmware really, really need to deal with this entire 'blocking' command / single thread issue. It gets pretty ugly when any serious use of the chips are considered. Perhaps PIC will become capable enough to allow RevEd to install a thread-sequencer in firmware where a thread can be launched with what a priority, a quality-of-service (QOS) identifier. In this scenario, queuing would be FIFO for all similar QOS threads, but priority threads would take priority for the single core. When Microchip Technology releases a two-core PIC (cheaply) this issue somewhat goes away.

    - Ray

  3. #3
    Senior Member
    Join Date
    Jan 1970
    Location
    Perth, Western Australia
    Posts
    3,375

    Default

    For a dual-core 'chip', the 16M (and, by inference the 16M2) has been discussed before. Just mount 2 x 8-pin PICAXEs in a 16-pin DIL socket.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •