How does PICkit 2 Logic Tool work?
As I said, the wheels go round, but...
The wheels are not going round and round in the pattern I expected. In particular they only go backwards. The code claims to sweep from 20% to 80% cuty cycle.
SOOO, can I use my USB connection and PICkit 2 Logic and Analyze Tool to see what is actually happening?
Ken
Thank you for your analysis
Thanks gang.
I came to much the same conclusion myself. I have been trying to figure out what exactly this PWM code does so that I can modify it meet the RC specs. The comments in the program are fairly clear. My first attempts have not worked but I am optimistic.
Interesting how rusty my brain has become.
Ken
Yes, that is certainly true, but
Yes, DC motors need the polarity changed to change direction. I was led to believe that there is something magical in this electronic speed control that made it work differently. Thank you for reminding me to question assumptions.
Ken
Maybe I need to use my dtdp switches
If the electronic speed control does not reverse polarity as a function of pulse size, then I will need to use the technique Fritsl used in his wall hugging robot.
http://letsmakerobots.com/node/928
(which seems no longer available)
He cross wired the motor with multiple DPDT relay switches controlled by his PIC. I was going to copy that idea, but then I started believing the story of the magical ESC.
1 Attachment(s)
Here's a snip from FATUBA FAQ page.
FATUBA manufactured the radio receiver in my RC car. It is the output of that box that I am trying to emulate coming out of my 16F887. They say here that reversing direction is done by controlling the PWM pulse size above or below 1.5ms. That is what I have been doing - I thought.
Attached is a quote from Electronic Control for DC Motors Using Discrete Bridge Circuits. It seems to say that my ESC should accept servo type PWM signals.
Quote:
Is the output signal digital?
Output signals are ANALOG. Receivers vary by design on how they RECEIVE and ENCODE signals. But all deliver very similar output pulse signals, which is used to drive the servo to the desired location. This output pulse ranges from 1000uS to 2000uS, with 1500uS typically being center.
Is the output signal an on/off signal or does it have an internal regulator?
The output signal for each channel is a pulsed signal. The pulse width (commonly 1000uS to 2000uS) is determined by the corresponding channel of the transmitter. When activated by one of the proportional channels (such as elevator, aileron, throttle, rudder, or knob control) the pulse width will vary. This controls the servo movement. Most servos will be centered when the pulse is at 1500uS. Channels that are controlled by a switch (such as the gear channel) will operate the pulse width from two set values such as 1100uS when in one position and 1900uS when set to the other position to activate servo movement.
What signal does the receiver emit to differentiate forward or backward movement?
Direction of movement is determined by the direction in which the respective pulse is shifted off of center (neutral). Center being 1500uS, if the pulse is shifted above 1500uS, the direction of travel is one direction. If the pulse is shifted below 1500uS, the direction of travel is in the opposite direction.
Yes, we are all in agreement except..
Thank you all for your help. I posted those quotes because they back up what you have been saying and what I thought I coded.
Trouble is my PIC code only makes my car wheels go backwards and stop. I have not been able to create a PWM stream that drives the wheels forward. I know the ESC works because the wheels go fine under radio control.
Oscilloscope, here I come.
Ken
I think I should take a different tack
I am realizing that using PAUSE can not work if my PIC is meant to do some thinking between pulses. I just discovered
http://darreltaylor.com/DT_INTS-14/SPWM.html
He is using interrupts. That is what I was hoping to do in the first place. I'll see if I can figure out what he is saying.
Meanwhile, would you be willing to take pictures of the pulses that my code is making if I posted the code?
Ken
This drives the wheels very fast backwards.
Scalerobotics:
This snippet has the capabiltiy to increment the pulse size a little bit at a time.
With this code the car starts out driving very fast backwards, then after five to ten seconds it stops, but never starts up forward.
My theory is that the (PAUSE 20) is what is causing the 50 pulses per second, Is that correct?
Code:
duty VAR WORD ' Duty cycle value (CCPR1L:CCP1CON<5:4>)
range VAR word
segment var word
TRISC.2 = 0 ' Set PORTC.2 (CCP1) to output
CCP1CON = %00001100 ' Set CCP1 to PWM
T2CON = %00000101 ' Turn on Timer2, Prescale=4
' Use formula to determine PR2 value for a 1KHz signal,
' 4MHz clock, and prescale=4. (4E6/(4*4*1E3))-1=249
' PR2 = 249 ' Set PR2 to get 1KHz out
' PR2 = 499 ' Set PR2 to get 2KHz out
' Use formula to determine CCPR1L:CCP1CON<5:4> value for
' ends of range 20% to 80%. (249+1)*4*0.2=200 (20% value)
' (249+1)*4*0.8=800 (80% value)
' duty = 200 ' Set duty cycle to 20%
range = 25
duty = 1650 ' Set duty cycle to 1.65msec
segment = 0
mainloop: CCP1CON.4 = duty.0 ' Store duty to registers as
CCP1CON.5 = duty.1 ' a 10-bit word
CCPR1L = DUTY >> 2
Pause 20 ' Pause 1/50 of second
duty = duty + 2 ' Increase duty cycle
IF (duty < (1650 + segment + range)) Then mainloop ' Do it again unless 2 msec
duty = duty + 2 ' Reset to 20% duty cycle
segment = segment + range
PAUSE 2000 'Pause 2 seconds
GoTo mainloop ' Do it forever
PAUSE has no effect it would seem
Thank you soooo much. What a great tool..
Two things for me to consider.
1. PAUSE seems to not have the affect I expected.
2. The PR2 constant must mean something to PBP, but I can not figure out what.
Lastly, which version of oscilloscope software do you use? Is it freeware or did it cost money. If so, how much?
Ken
Why is the pulse width jumping all over?
I had earlier success in getting a servo pulse width to be smooth on a Pic18F2520. But I am now trying to make DT_INTS servo pulse width for a PIC12F683. I have it sweeping from about .95ms to 1.9 ms, but it is not smooth at all. In fact, on the scope, it sometimes switches direction (starts to get wider instead of narrower for a fraction of a second). It is pretty darn ugly in fact.
Any ideas what I might have done (or not done) to cause this?
PIC12f683
Code:
</i></font><b>DEFINE </b>OSC 8
<b>INCLUDE </b><font color="#FF0000">"DT_INTS-14.bas" </font><font color="#000080"><i>;interrupt routines
</i></font><b>INCLUDE </b><font color="#FF0000">"sub16.inc" </font><font color="#000080"><i>; subtract 16 bit macro
</i></font><b>DEFINE </b>DEBUG_REG GPIO
<b>DEFINE </b>DEBUG_BIT 0
<b>DEFINE </b>DEBUGIN_BIT 1
<b>DEFINE </b>DEBUG_BAUD 38400
<b>DEFINE </b>DEBUG_MODE 0
INTCON = %10101000 <font color="#000080"><i>'internal oscillator
</i></font>OSCCON = %01110000 <font color="#000080"><i>'set for 8mhz internal
</i></font>CMCON0 = 7 <font color="#000080"><i>'TURN COMPARITORS OFF
</i></font>TRISIO = %010000 <font color="#000080"><i>'Set GSIO 4 INPUT, others to OUTPUT
</i></font>OPTION_REG = %11000010
T1CON = %01000001
T2CON = %01001110
servo <b>VAR </b>GPIO.2
servo = 0
pulse <b>VAR BYTE
</b>pulse = 0
bittest <b>VAR BIT
ASM
</b><font color="#008000">INT_LIST macro </font><font color="#000080"><i>; IntSource, Label, Type, ResetFlag?
</i></font><font color="#008000">INT_Handler TMR0_INT, PulseOut, ASM, yes
INT_Handler TMR2_INT, period, ASM, yes
INT_Handler TMR1_INT, test, ASM, yes
endm
INT_CREATE </font><font color="#000080"><i>; Creates the interrupt processor
</i></font><font color="#008000">INT_ENABLE TMR0_INT </font><font color="#000080"><i>; Enable pulseout interrupts
</i></font><font color="#008000">INT_ENABLE TMR2_INT </font><font color="#000080"><i>; enable period interrupt (20ms)
</i></font><font color="#008000">INT_ENABLE TMR1_INT </font><font color="#000080"><i>; enable interrupt to increment pulse width (test)
</i></font><b>ENDASM
</b>Main:
nop
<b>GOTO </b>Main
<font color="#000080"><i>'---[TMR0_INT - interrupt handler]------------------------------------------
</i></font><b>ASM
</b><font color="#008000">PulseOut
btfsc _bittest </font><font color="#000080"><i>;test status of bittest bit
</i></font><font color="#008000">goto $+7 </font><font color="#000080"><i>;if high skip 7 lines
</i></font><font color="#008000">bcf OPTION_REG,5 </font><font color="#000080"><i>;stop timer
</i></font><font color="#008000">movf _pulse,w </font><font color="#000080"><i>;load TMR0 with value of pulse variable
</i></font><font color="#008000">movwf TMR0
bsf _bittest </font><font color="#000080"><i>;set bittest bit, indicating we are on second half
</i></font><font color="#008000">bsf OPTION_REG,5 </font><font color="#000080"><i>;start timer again for second interrupt
</i></font><font color="#008000">goto $+3 </font><font color="#000080"><i>;skip to return from interrupt
</i></font><font color="#008000">bcf OPTION_REG,5 </font><font color="#000080"><i>;stop timer
</i></font><font color="#008000">bcf _servo </font><font color="#000080"><i>;bring servo pin low for end of pulse width
</i></font><font color="#008000">INT_RETURN
</font><b>ENDASM
</b><font color="#000080"><i>'---[TMR2_INT - interrupt handler]------------------------------------------
</i></font><b>ASM
</b><font color="#008000">period
bsf _servo </font><font color="#000080"><i>;set servo pin high (begin pulse width)
</i></font><font color="#008000">movlw d'0' </font><font color="#000080"><i>;set timer0 to 0 (full length of timer)
</i></font><font color="#008000">movwf TMR0
bsf OPTION_REG,5 </font><font color="#000080"><i>;start timer0, now PulseOut interrupt will occur
</i></font><font color="#008000">bcf _bittest </font><font color="#000080"><i>;clear bittest bit
</i></font><font color="#008000">INT_RETURN
</font><b>ENDASM
</b><font color="#000080"><i>'---[TMR1_INT - interrupt handler]------------------------------------------
</i></font><b>ASM
</b><font color="#008000">test
incf _pulse
INT_RETURN
</font><b>ENDASM
</b></code></pre><!--EndFragment--></body>
</html>
12f683 servo pass through
Here is some code that will measure an RC receiver pulse width coming in on GPIO.2, perform a little math on the value, and put out the wave form out on GPIO.1, using DT Interrupts.
It's on a little 12F683 and was written for 8mhz internal. Looks pretty good on the scope. I need to test it on a motor controller though. But time for bed.....
Code:
<html>
<head></head>
<body><!--StartFragment--><pre><code><font color="#000080"><i>
</i></font><b>DEFINE </b>OSC 8
<b>INCLUDE </b><font color="#FF0000">"DT_INTS-14.bas"</font><font color="#000080"><i>;interrupt routines
</i></font><b>INCLUDE </b><font color="#FF0000">"sub16.inc" </font><font color="#000080"><i>; subtract 16 bit macro
</i></font><b>DEFINE </b>DEBUG_REG GPIO
<b>DEFINE </b>DEBUG_BIT 0
<b>DEFINE </b>DEBUGIN_BIT 1
<b>DEFINE </b>DEBUG_BAUD 38400
<b>DEFINE </b>DEBUG_MODE 0
INTCON = %10101000 <font color="#000080"><i>'
</i></font>OSCCON = %01110000 <font color="#000080"><i>'set for 8mhz internal
</i></font>CMCON0 = 7 <font color="#000080"><i>'TURN COMPARITORS OFF
</i></font>ANSEL = %00000000 <font color="#000080"><i>'Set A/D OFF
</i></font>ADCON0 = %00000000 <font color="#000080"><i>'Analog converter OFF
</i></font>TRISIO = %010100 <font color="#000080"><i>'Set GSIO 4 and 2 to INPUT, others to OUTPUT
</i></font>OPTION_REG = %11000010
T1CON = %00110001
T2CON = %01001110
CCP1CON = %00000101
risetime <b>VAR WORD </b><font color="#000080"><i>;used for pulse width measure start of pw
</i></font>falltime <b>VAR WORD </b><font color="#000080"><i>;time at end of pulse width
</i></font>falltime_l <b>VAR </b>falltime.Byte0
falltime_h <b>VAR </b>falltime.Byte1
risetime_l <b>VAR </b>risetime.Byte0
risetime_h <b>VAR </b>risetime.Byte1
pulsewidth <b>VAR WORD
</b>pulsewidth_l <b>VAR </b>pulsewidth.Byte0
pulsewidth_h <b>VAR </b>pulsewidth.Byte1
ServoOut <b>VAR </b>GPIO.1
ServoOut = 0
pulse <b>VAR BYTE
</b>TMR0 = 0
pulse = 255
bittest <b>VAR BIT
ASM
</b><font color="#008000">INT_LIST macro </font><font color="#000080"><i>; IntSource, Label, Type, ResetFlag?
</i></font><font color="#008000">INT_Handler TMR0_INT, PulseOut, ASM, yes
INT_Handler TMR2_INT, period, ASM, yes
INT_Handler CCP1_INT, PWMeasure, ASM, yes
endm
INT_CREATE </font><font color="#000080"><i>; Creates the interrupt processor
</i></font><font color="#008000">INT_ENABLE TMR0_INT </font><font color="#000080"><i>; Enable pulseout interrupts
</i></font><font color="#008000">INT_ENABLE TMR2_INT </font><font color="#000080"><i>; enable period interrupt (20ms)
</i></font><font color="#008000">INT_ENABLE CCP1_INT </font><font color="#000080"><i>; enable interrupt to increment pulse width (test)
</i></font><b>ENDASM
PAUSE </b>200
Main:
<b>PAUSE </b>20
<font color="#000080"><i>;debug dec pulsewidth," ",10,13
</i></font>pulse = ((pulsewidth * 8)/10)-167 <font color="#000080"><i>;scale to fit into a byte
</i></font>pulse = 255 - pulse <font color="#000080"><i>;reverse the stick
</i></font><b>GOTO </b>Main
<font color="#000080"><i>'---[TMR0_INT - interrupt handler]------------------------------------------
</i></font><b>ASM
</b><font color="#008000">PulseOut
btfsc _bittest </font><font color="#000080"><i>;test status of bittest bit
</i></font><font color="#008000">goto $+7 </font><font color="#000080"><i>;if high skip 7 lines
</i></font><font color="#008000">bcf INTCON,5 </font><font color="#000080"><i>;stop timer
</i></font><font color="#008000">movf _pulse,w </font><font color="#000080"><i>;load TMR0 with value of pulse variable
</i></font><font color="#008000">movwf TMR0
bsf _bittest </font><font color="#000080"><i>;set bittest bit, indicating we are on second half
</i></font><font color="#008000">bsf INTCON,5 </font><font color="#000080"><i>;start timer again for second interrupt
</i></font><font color="#008000">goto $+3 </font><font color="#000080"><i>;skip to return from interrupt
</i></font><font color="#008000">bcf INTCON,5 </font><font color="#000080"><i>;stop timer
</i></font><font color="#008000">bcf _ServoOut </font><font color="#000080"><i>;bring ServoOut pin low for end of pulse width
</i></font><font color="#008000">INT_RETURN
</font><b>ENDASM
</b><font color="#000080"><i>'---[TMR2_INT - interrupt handler]------------------------------------------
</i></font><b>ASM
</b><font color="#008000">period
movlw d'72' </font><font color="#000080"><i>;fine tune timer2 period
</i></font><font color="#008000">movwf TMR2
bcf INTCON,2 </font><font color="#000080"><i>;clear timer flag if set
</i></font><font color="#008000">movlw d'17' </font><font color="#000080"><i>;set timer0 first 1ms time base
</i></font><font color="#008000">movwf TMR0
bsf INTCON,5 </font><font color="#000080"><i>;enable timer0 interrupt
</i></font><font color="#008000">bsf _ServoOut </font><font color="#000080"><i>;set ServoOut pin high (begin pulse width)
</i></font><font color="#008000">bcf _bittest
INT_RETURN
</font><b>ENDASM
</b><font color="#000080"><i>'---[CCP1_INT - interrupt handler]------------------------------------------
</i></font><b>ASM
</b><font color="#008000">PWMeasure
BTFSS CCP1CON, CCP1M0 </font><font color="#000080"><i>; Check for falling edge watch
</i></font><font color="#008000">GOTO FALL_EDGE </font><font color="#000080"><i>; Go pick up the falling edge
</i></font><font color="#008000">MOVF CCPR1L,W </font><font color="#000080"><i>; else store leading edge value
</i></font><font color="#008000">MOVWF _risetime_l </font><font color="#000080"><i>; into 16 bit word risetime
</i></font><font color="#008000">MOVF CCPR1H,W
MOVWF _risetime_h
BCF CCP1CON, CCP1M0 </font><font color="#000080"><i>; Now capture the trailing edge
</i></font><font color="#008000">GOTO ISR_2 </font><font color="#000080"><i>; Exit the interrupt service routine
</i></font><font color="#008000">FALL_EDGE:
BSF CCP1CON, CCP1M0 </font><font color="#000080"><i>; Re-set for trailing edge capture
</i></font><font color="#008000">MOVF CCPR1L,W </font><font color="#000080"><i>; Store the captured value into
</i></font><font color="#008000">MOVWF _falltime_l </font><font color="#000080"><i>; falltime_l and ...
</i></font><font color="#008000">MOVF CCPR1H,W
MOVWF _falltime_h </font><font color="#000080"><i>; ... falltime_h
;
; 16 bit subtract
; falltime = falltime - risetime
;
</i></font><font color="#008000">SUB16 _falltime, _risetime </font><font color="#000080"><i>;do 16 bit subtraction to find width
</i></font><font color="#008000">movf _falltime_l,w
movwf _pulsewidth_l
movf _falltime_h,w
movwf _pulsewidth_h
ISR_2
INT_RETURN
</font><b>ENDASM
</b></code></pre><!--EndFragment--></body>
</html>