PIC 16F84A FREQ 8 OSCILLATOR CRYSTAL BYTE xin,yin,zin,fstart,xcnt,ycnt,zcnt,init,xcent BYTE ycent,zcent,AUXup,AUXdn,yhi,ylo,xhi,xlo,yoff,xoff *__CONFIG H'3FFE' '---------------------------------------------------------------------------------------------------- ' Written by Ted Callahan 10-Feb-04 Rev A ' This routine implements a basic skid-steer mixer with input from a digital proportional RC receiver. ' Tested with a Futaba 7ch receiver. Inputs are RB0, RB1, RB2. RB2 is an aux input. Interrupt RB0 is used ' to sense a frame. As RB0 rises, a pulse count of each input begins. The count loop requires ' ~55us for each pass at 8mhz clock. Input of 1ms pulse=~18, 1.5ms=~27, 2ms=~36. The routine senses ' stick center for each input at power up so all sticks should be neutralized (trim center) ' INPUTS: RB0(6)-Xin Servo 1 (aileron), RB1(7)-Yin Servo 2 (elevator), RB2(8)-Zin Servo 3 (rudder) from receiver ' OUTPUTS: RB3(9)-LF, RB4(10)-LR, RB5(11)-RF, RB6(12)-RR, RA0(17)-AUX Right, RA1(18)-AUX Left ' RB7 (13) is pulled low to light an ON status LED if desired. '---------------------------------------------------------------------------------------------------- main : 'set the watchdog timer to time out after 576ms *BSF STATUS, RP0 *MOVLW B'11011101' *MOVWF OPTION_REG *CLRWDT *MOVLW b'11011101' *MOVWF OPTION_REG *BCF STATUS, RP0 SetPort A, %10000 SetPort B, %00000111 xcnt=0 ycnt=0 zcnt=0 xin=0 yin=0 zin=0 AUXup=0 AUXdn=0 fstart=0 PinLow A, 0 PinLow A, 1 PinLow A, 2 PinLow B, 7 PinLow B, 6 PinLow B, 5 PinLow B, 4 PinLow B, 3 'init is a flag for grabbing stick centers on power up init=1 Interrupt_Enable Interrupt_Ext 1, rising intwait : 'wait for a frame start interrupt (fstart=1) IF fstart<>1 THEN GOTO intwait END IF 'if no interrupt occurs within 576ms the watchdog timer will reset and turn everything off 'otherwise, clear the timer at this point *CLRWDT 'a frame has now started (fstart=1) cntloop : PinRd B, 0, xin PinRd B, 1, yin PinRd B, 2, zin IF xin=1 THEN xcnt=xcnt+1 END IF IF yin=1 THEN ycnt=ycnt+1 END IF IF zin=1 THEN zcnt=zcnt+1 END IF IF fstart=1 THEN GOTO cntloop END IF 'frame has ended (fstart=0) 'if init=1 then store the center positions and recount IF init=1 THEN 'if the centers are way out of nominal (~1.5ms or ~27) then adjust to nominal 1.5ms IF xcnt>24 & xcnt<30 THEN xcent=xcnt ELSE xcent=27 END IF IF ycnt>24 & ycnt<30 THEN ycent=ycnt ELSE ycent=27 END IF IF zcnt>24 & zcnt<30 THEN zcent=zcnt ELSE zcent=27 END IF init=0 xcnt=0 ycnt=0 zcnt=0 GOTO intwait END IF 'turn off the interrupt to allow time to process the counts Interrupt_Disable 'process the counts from here yhi=0 ylo=0 xhi=0 xlo=0 yoff=0 xoff=0 'decode the stick positions based on the counts IF ycent+22>ycnt & ycnt>ycent+4 THEN ylo=1 END IF IF ycent+4>=ycnt & ycnt>=ycent-4 THEN yoff=1 END IF IF ycent-22xcnt & xcnt>xcent+4 THEN xhi=1 END IF IF xcent+4>=xcnt & xcnt>=xcent-4 THEN xoff=1 END IF IF xcent-22zcnt & zcnt>zcent+4 THEN PinHigh A, 0 END IF IF zcent+4>zcnt&zcnt>zcent-4 THEN PinLow A, 0 PinLow A, 1 END IF IF zcent-2240 THEN 'no z signal received PinLow A, 0 PinLow A, 1 END IF 'now switch the X&Y output pins on and off based on the stick decoding IF xcnt<5 | ycnt<5 THEN 'no signal has been received from one or both channels so turn everything off PinLow B, 3 PinLow B, 4 PinLow B, 5 PinLow B, 6 GOTO recycle END IF IF xoff=1 & yoff=1 THEN 'STOP PinLow B, 3 PinLow B, 4 PinLow B, 5 PinLow B, 6 END IF IF yhi=1 & xoff=1 THEN 'FORWARD PinLow B, 4 PinLow B, 6 PinHigh B, 5 PinHigh B, 3 END IF IF ylo=1 & xoff=1 THEN 'BACKWARD PinLow B, 3 PinLow B, 5 PinHigh B, 4 PinHigh B, 6 END IF IF xhi=1 & yoff=1 THEN 'RIGHT SPIN PinLow B, 4 PinLow B, 5 PinHigh B, 3 PinHigh B, 6 END IF IF xlo=1 & yoff=1 THEN 'LEFT SPIN PinLow B, 3 PinLow B, 6 PinHigh B, 4 PinHigh B, 5 END IF IF xlo=1 & yhi=1 THEN 'LEFT FORWARD PinLow B, 3 PinLow B, 4 PinLow B, 6 PinHigh B, 5 END IF IF yhi=1 & xhi=1 THEN 'RIGHT FORWARD PinLow B, 4 PinLow B, 5 PinLow B, 6 PinHigh B, 3 END IF IF xlo=1 & ylo=1 THEN 'LEFT BACKWARD PinLow B, 3 PinLow B, 4 PinLow B, 5 PinHigh B, 6 END IF IF xhi=1 & ylo=1 THEN 'RIGHT BACKWARD PinLow B, 3 PinLow B, 5 PinLow B, 6 PinHigh B, 4 END IF recycle : 'zero counters, turn the interrupt on, and go back and wait for the start of a new frame fstart=0 xcnt=0 ycnt=0 zcnt=0 xin=0 yin=0 zin=0 'start the process over again Interrupt_Enable GOTO intwait ' IR_Ext_Begin 'frame start interrupt routine IF fstart=0 THEN 'a frame has started fstart=1 ELSE fstart=0 END IF IR_Ext_End