Receiver channels 1, 3 and 5 are input all on to the CCP capture pin. Although this is only 3 pins, RC channels 2 and 4 can be determined by measureing the time between 1 and 3, and 3 and 5, giving you a 5 channels decoded. To keep these receiver lines from grounding each other out, diodes were added.
Four ouputs are left for servos. The code only uses about 22% of the space in the PIC12F683, so there is a bit more space to make some cool devices. Using this slow 8mhz chip, it can perform about 80,000 insctructions each RC frame. This should be plenty for some lower and higher math on the servo variables.
PWM Code
by scalerobotics
And for a PIC18F2431 series:
The 18F2431 makes it slightly easier to perform servo PWM because it's PCPWM module can go down to 19 htz while maintaining fast OSC rates, unlike other PIC chips HPWM. Here is an example of using the PCPWM to output 3 servo signals. This specific example senses the pulses (up to 5 channels) by using the CCP1 capture pin. To get 5 channels into one pin for PW capture, channels 1, 3 and 5 are input using small signal diodes. Then, since this drops the signal down to under 3 volts, I used two 2n3904 transistors. One to boost up the voltage, and the other one to invert the signal back to normal. (It was all I had lying around). Somehow, you will need to boost your signal after the diodes for the CCP1 capture to sense the incoming pulses.
Note: Because the PCPWM was used, this will not work on any chip outside of the 18F2431 family.
;This only works on a 18F2431 family device with Power Control PWM (PCPWM) ;By Scale Robotics Inc. ; The input signal should look something like this:- ; ; |<------------------ 1 frame (~20mS) -------------->| ; |<1~2mS> ; ______ ______ ______ ______ ; _______| |______| |______| |________________| |____ ; gap ch1 ch2 ch3 ch4 ch5 sync gap ch1 etc define OSC 40 asm __CONFIG _CONFIG1H, _OSC_HSPLL_1H __CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H __CONFIG _CONFIG4L, _LVP_OFF_4L endasm clear ADCON0 = %00000000 ADCON1 = %00000000 portb=0 trisb = %11000000 trisc = %00000110 trisa = %00000000 DTCON = %00000101 'dead time for complimentary ouputs PTCON0 = %00001101 '1:1 postscale, Fosc/4 1:64 prescale, Sincle Shot mode PTPERL = 255 ' PTPERH = 251 PWMCON0 =%01010000 'PWM[5:0] ouputs enabled PWMCON1 = 1 'updates enabled, overrides sync w/timebase PTCON1 = %10000000 'PWM timebase is on, counts up FLTCONFIG = %00000010 'disable fault A, cycle by cycle mode CCP1CON = %00000101 'Capture mode; every rising edge duty1 var word 'width of outgoing pulse1 duty2 var word 'duty values 625 to 1250 = 1 to 2 ms pulse (Center at 625) duty3 var word risetime1 var word 'Rise Time for incoming pulse1 risetime2 var word risetime3 var word falltime1 var word 'falltime for incoming pulse1 falltime2 var word falltime3 var word pulsewidth1 var word 'pulse width for incoming pulse1 pulsewidth2 var word pulsewidth3 var word pulsewidth4 var word pulsewidth5 var word pulseNumber var byte pulseNumber = 1 'tells which pulse we are reading CCP1CON.0 = 1 timerone var word timerone = 60315 ; INCLUDE "DT_INTS-18.bas" ; Base Interrupt System ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler TMR5_INT, _PulseOut, ASM, yes INT_Handler CCP1_INT, _PulseMeasure, ASM, yes INT_Handler TMR0_INT, _TimeOut, ASM, yes endm INT_CREATE ; Creates the interrupt processor ENDASM T1CON = %00110001 ;Timer1 used by CCP1 capture T5CON = $01 ;used as pulseout timer T0CON = %11000111 ; Prescaler = 8, TMR1ON @ INT_ENABLE TMR5_INT ; Enable Timer 1 Interrupts @ INT_ENABLE CCP1_INT ; Enable Capture Compare for pulse width measurement @ INT_ENABLE TMR0_INT ; deadtime (sync gap) indicator for lull between pulses Main: pause 10 'do something to these values if you want to filter, center, etc 'Below we are just passing values through duty1 = pulsewidth1 >>1 'send channel 1 out PCPWM on PortB.1 duty2 = pulsewidth3 >>1 'send channel 3 out PCPWM on PortB.3 duty3 = pulsewidth5 >>1 'send channel 5 out PCPWM on PortB.4 GOTO Main '---[TMR5_INT - interrupt handler]------------------------------------------ PulseOut: 'set up pulse width values for pulseout and reset single shot bit TMR5L = timerone.byte0 TMR5H = timerone.byte1 PDC0L = duty1.lowbyte PDC0H = duty1.highbyte PDC1L = duty2.lowbyte PDC1H = duty2.highbyte PDC2L = duty3.lowbyte PDC2H = duty3.highbyte PTCON1.7=1 'resets single shot PTEN bit @ INT_RETURN '---[CCP1_INT - interrupt handler]------------------------------------------ PulseMeasure: if CCP1CON.0 = 1 then ; Check CCP1M0 for rising edge watch select case pulseNumber case 1 TMR0L = 0 'reset timeout timer0 TMR0H = 0 risetime1.lowbyte = CCPR1L risetime1.highbyte = CCPR1H case 2 TMR0L = 0 'reset timeout timer0 TMR0H = 0 risetime2.lowbyte = CCPR1L risetime2.highbyte = CCPR1H case 3 TMR0L = 0 'reset timeout timer0 TMR0H = 0 risetime3.lowbyte = CCPR1L risetime3.highbyte = CCPR1H End select @ BCF CCP1CON, CCP1M0 ; Now capture the trailing edge Else 'check for falling edge time @ BSF CCP1CON, CCP1M0 ; Re-set for trailing edge capture select case pulsenumber case 1 falltime1.lowbyte = CCPR1L falltime1.highbyte = CCPR1H pulsewidth1 = falltime1 - risetime1 case 2 falltime2.lowbyte = CCPR1L falltime2.highbyte = CCPR1H pulsewidth2 = risetime2 - falltime1 pulsewidth3 = falltime2 - risetime2 case 3 falltime3.lowbyte = CCPR1L falltime3.highbyte = CCPR1H pulsewidth4 = risetime3 - falltime2 pulsewidth5 = falltime3 - risetime3 end select pulsenumber = pulsenumber + 1 'get ready for next channel endif @ INT_RETURN '---[TMR0_INT - interrupt handler]------------------------------------------ TimeOut: pulsenumber = 1 'if pause between pulse in exceeds about 7 ms, get ready 'to receive pulse 1 (senses dead time between pulse bursts) @ INT_RETURN
Re: Help with Pololu DRV8711 Stepper Motor Driver
OK - Problem solved. I went to Pololu and got help from their tech folks and they helped me figure this out. In a nutshell, it had to do with how I was creating the CTRL and TORQUE registers and...
Atom058 - 25th May 2025, 19:08