PMDC SERVO MOTOR WITH quadrature encoder DRIVE ?
Did any idea how to command PMDC SERVO MOTOR with quadrature encoder and after end of way stop in moment with no more movement ?
I need idea or sample of pulse diagram fro drive and stop conditions.
I dont need pbp source that part I will write...
Simple if I drive motor with PWM how to stop motor in moment and break it
electrical with no more movement to next move command ?
Maybe simultan change left right direction as break ???
I will use H bridge.
Regards and sorry for bad english.
Robert
hard way to finish of idea of own uhu wuth friends from these forum
Here is success probe with count encoder from 0 to 2000 for one turn of shaft of motor.
Code:
' Pic 18F4431 @ 20MHz true XTAL
define osc 20
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 64 ' 19200 Baud @ 20MHz, 0.16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
ADCON0=0 'Turn of ADC
ANSEL0=0 'Make Port A inputs Digital
PortA = 0
PortB = 0
PortC = 0
TRISA = %011100 'QEI pins as inputs.
TRISB = %00000000
TRISC = %10000000 'USART RX pin as input.
QEICON=%11001100
DFLTCON = %00111000 ' enable error filter for all capture inputs
MAXCNTL = %11001111 'lowbyte = 207
MAXCNTH = %00000111 'highbyte = 7 but after math: highbyte * 256 = 1792 + 207 = 1999
'QEICON = %00010100 'Setup QEI, 4X mode, reset on index.
PosLow VAR BYTE 'Storage for the low byte of encoder count
PosHigh VAR BYTE 'Storage for the high byte of encoder count
PosTemp VAR BYTE 'Temporary storage for low byte of encder count
Position VAR WORD 'Actual encoder position, 16bit word.
POSCNTL = 0 ' clear lowbyte of counter for start
POSCNTH = 0 ' clear highbyte of counter for start
CLEAR
Main:
Gosub GetPosition
HSEROUT [dec position]
Pause 100
Goto Main
GetPosition:
'Since the position counter isn't double buffered we can get to situations
'where the lowbyte overflows between readings of the high and the low byte. This
'is prevented by reading the low byte two times and compare the two readings.
'If they are the same then we're fine, if not re-read the registers.
PosHigh = POSCNTH 'Get high byte of counter
PosLow = POSCNTL 'Get low byte of counter
PosTemp = POSCNTL 'Get low byte again
If PosLow - PosTemp = 0 then Goto Done 'Compare, if equal we're done.
PosHigh = POSCNTH 'If not, get values again.
PosLow = POSCNTL
Done:
Position = POSHIGH * 256 + PosLow 'Put high and lowbyte together.
RETURN
END
Will continue...
Robert:)
3 Attachment(s)
Little more probe from me...
Now little about PMDC breaking.
1.H-bridge drive of PMDC:
Attachment 3630
2.Slow DINAMIC break by short with same polarity of power supply.
Bad idea for fast servo PID control.
Attachment 3631
3.Fast RECUPERATIVE break good for PID control but must use high frequency of PWM.
The best is ~ 15-20KHZ.
Work for me good , but you need good DIODE in H-bridge for EMS breaking.
Attachment 3632
Thank's and regard's Robert :)
New question is start for next stage of project
Now I am probe on many ways to do next but I cant to image how.
1. I was setup count for QEI with friends from these forum to count from 0 - 12500 - becous my motor have gear 6.25:1 and 6.25*2000 = 12500(reding of one turn of motor shaft with 500 lines encoder) give me full 360' of output shaft range.That work extra.
Next : If I want to move for example 1mm on my mechanic I need one turn of output shaft that give me easi to control position of count from CW 0-12500 or CCW 12500 to 0.That is all in 16bit counter.
But what if I need to move more then 16bit counter ?
OK I can use PBPL and define 32bit variable - I was probe and it work 100%.
I can easy set to se if X VAR LONG number 25000000 that give me 25000000/12500 = 2000mm - inpresive!
But how I can my software variable defined as LONG from 0 - 25000000 to increment or decrement from hardware COUNT buffer wich count in circle from 0-12500 and vice verse ?
Is any idea becouse all what I was probe give me garbage of result.
Regards Robert :mad::confused:
Final test and end of these thread from me
Maybe someone will be optimise code maybe not.
Here is my last test and all my problems wos on my wrong seting of 18F4431
and wrong calc for position counter.
These code only mowe motor CW but I was tested also CCW and is ok.
My best regards to all
/Robert
Code:
@ __CONFIG _CONFIG1H, _OSC_HSPLL_1H
@ __CONFIG _CONFIG2H, _WDTEN_ON_2H & _WDPS_512_2H
@ __CONFIG _CONFIG2L, _BOREN_OFF_2L & _PWRTEN_ON_2L
@ __CONFIG _CONFIG3H, _MCLRE_ON_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L
clear
define OSC 40 ;define osc speed 10MHz x 4 PLL = 40 MHz
ADCON0= %00000000
ANSEL0= %00000000
ANSEL1= %00000000
TRISA = %00011110
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
LATA = %00000000
LATB = %00000000
LATC = %00000000
LATD = %00000000
LATE = %00000000
duty var word 'duty variable for PWM CCP1
PosLow VAR BYTE ; Temp variable for Position calc.
PosHigh VAR BYTE ; Temp variable for Position calc.
PosTemp VAR BYTE ; Temp variable for Position calc.
position var word ; Position counter final variable from QEI module
direction var bit ; Direction bit for motor CW or CCW
setpoint var word ; Setpoint of position variable
preset_TMR1 var word ; Timer1 prescaler variable
include "PID.pbp" ; Include Henrik PID rutine
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
;----[High Priority Interrupts]-----------------------------------------------
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _pidloop, PBP, yes
endm
INT_CREATE
ENDASM
CCP1CON = %00001111
T2CON = %00000100
T1CON = %10000101
QEICON = %10001000
DFLTCON = %00111010
POSCNTH=0 ; set initial counter for encoder, H bit
POSCNTL=0 ; set initial counter for encoder, L bit
setpoint = 0 ; set initial for Setpoint
duty = 512 ; set initial for PWM 512 = motor no move
direction = pid_Out.15
pid_Kp =$0140
pid_Ki =$0020
pid_Kd =$0003
pid_Ti = 8
pid_I_Clamp = 1
pid_Out_Clamp = 511
preset_TMR1 = 65043
TMR1L = preset_TMR1.byte0
TMR1H = preset_TMR1.byte1
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
Main: ; main loop
IF PORTA.1 = 0 then setpoint = setpoint + 1 ; Increment setpoint from taster on RA1
select case setpoint ; Circular count for Setpoint condition
case is >= 65534 ; Circular count for Setpoint condition
setpoint = 0 ; reset setpoint
POSCNTH=0 ; set counter for encoder, H bit ; reset QEI counter high byte
POSCNTL=0 ; set counter for encoder, L bit ; reset QEI counter low byte
end select ; End of Circular count for Setpoint condition
pid_Error = setpoint - position ; Calculate PID error for PID rutine
gosub pid ; go to PID rutine
select case direction ; condition determine PWM for locked antiphase
case 0 ; condition determine PWM for locked antiphase
Duty = abs(512-pid_out) ; condition determine PWM for locked antiphase
case 1 ; condition determine PWM for locked antiphase
Duty = 512 + pid_Out ; condition determine PWM for locked antiphase
end select ; End condition determine PWM for locked antiphase
@ INT_DISABLE TMR1_INT ; Prevent disable Timer1 interupt
CCPR1L = duty>>2 ; MSB of duty cycle value
CCP1CON=%00001111 | (duty<<5) ; set PWM mode and store the
@ INT_ENABLE TMR1_INT ; Enable Timer1 interupt
goto Main ; do main loop
pidloop: ; Interrupt for fast reading QEI and calc position
PosHigh = POSCNTH ; reading QEI and calc position
PosLow = POSCNTL ; reading QEI and calc position
PosTemp = POSCNTL ; reading QEI and calc position
If PosLow - PosTemp = 0 then Goto Done ; reading QEI and calc position
PosHigh = POSCNTH ; reading QEI and calc position
PosLow = POSCNTL ; Done reading QEI and calc position
Done: ; Final QEI calc position
Position = 256 * POSHIGH + PosLow ; Final QEI calc position
TMR1L = preset_TMR1.byte0 ; reset Timer1 to preset
TMR1H = preset_TMR1.byte1 ; reset Timer1 to preset
@ INT_RETURN ; return from Timer1 interrupt
end
New video of my PID DC servo
http://www.youtube.com/watch?v=NFAegIl2e_c
Sorry comment is in my language - Serbian.
Regards to all
/Robert