PDA

View Full Version : PMDC SERVO MOTOR WITH quadrature encoder DRIVE ?



phoenix_1
- 26th August 2009, 18:44
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

mackrackit
- 29th August 2009, 14:41
Here are some threads talking about how to work with the encoder.
http://www.picbasic.co.uk/forum/showthread.php?t=778&highlight=rotary+encoder
http://www.picbasic.co.uk/forum/showthread.php?t=1552
http://www.picbasic.co.uk/forum/showthread.php?t=9700

As far as stopping goes...
Does the motor have a built in brake for holding? It can be stopped by shorting the leads but how fast it stops that way depens on the speed it is running when the leads are shorted.

phoenix_1
- 29th August 2009, 20:13
I was probe to stop motor and all work good.
But now I have another problem:
All examples from forum for read quadrature encoder with A and B outputs
at 5V are confused for my head, I was probe PBP examples but is to slow
and I think that for read quadrature encoder is needed ASM or some INT rutine becouse when motor work on ~ 3000 rpm rutine must be ultra speed
and background proces....
My head is like baloon ... :p

phoenix_1
- 30th August 2009, 21:19
All other info about my probe is now in PicBasicPro FORUM in:
Probe to read quadrature encoder with DT_INT need help
After my success I will post all here on FORUM.
If any help and good idea pls write.
Many thanks to all good peoples here!
Best regards Robert :p

HenrikOlsson
- 31st August 2009, 06:08
I recommend you take a look at the 18F2431 series PIC. It has a motion feedback module built in that can be set up to keep track of an incremental encoder. It also has a lot of other goodies specifically targeted at motor control applications.

/Henrik.

phoenix_1
- 31st August 2009, 08:32
I recommend you take a look at the 18F2431 series PIC. It has a motion feedback module built in that can be set up to keep track of an incremental encoder. It also has a lot of other goodies specifically targeted at motor control applications.

/Henrik.

I was buy today 18F4431 and will move to it.
At moment I looking for examples for it.
Thanks and regards Robert :)

HenrikOlsson
- 31st August 2009, 21:20
Hi,
This is cut and pasted from a larger program I have and this digested version is not tested so take it for what it is please. It's written for the 18F2431 so double check the pin assignments for the QEI module.



DEFINE HSER_RCSTA 90h 'USART receive status init.
DEFINE HSER_TXSTA 24h 'USART transmit status init.
DEFINE HSER_BAUD 57600 'Baudrate is 57600.

ANSEL0 = 0 'All inputs as digital

PortA = 0
PortB = 0
PortC = 0

TRISA = %11000 'QEI pins as inputs.
TRISB = %00000000
TRISC = %10000000 'USART RX pin as input.

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.

CLEAR

Main:
Gosub GetPosition
HSEROUT ["QEI Count: " , #Position, 10]
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


Again, no guarantees but I hope it serves as a starting point for you.

/Henrik.

mackrackit
- 31st August 2009, 22:07
Hi Henrik,

I started playing with the 4431 DIP version and wonder if you have ran into this with the one you are using. Maybe it is a 4331 problem, maybe whole series.

When using a 4Mhz resonator and have the config set for HSPLL and DEFINE OSC 16 all works well.

If I replace the 4Mhz with a 10 Mhz and try DEFINE OSC 40 everything goes erratic.
The PIC runs but even a simple "blinky" will blink randomly.

Here is the very simple code and configs I was playing with to set the OSC.


@ __CONFIG _CONFIG1H, _OSC_HSPLL_1H
@ __CONFIG _CONFIG2H, _WDTEN_ON_2H & _WDPS_512_2H
@ __CONFIG _CONFIG2L, _BOREN_OFF_2L & _PWRTEN_ON_2L
@ __CONFIG _CONFIG3H, _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L

DEFINE OSC 16

START:HIGH PORTD.1:PAUSE 500
LOW PORTD.1:PAUSE 500:GOTO START

phoenix_1
- 31st August 2009, 22:21
My first step to make led blink and probe with these code:


define osc 20

ADCON1 = 7
led1 var porta.0
led2 var porta.1
high led1
low led2
pause 1000
loop:
toggle led1
pause 500
toggle led2
pause 500
goto loop


And led wor blink...:rolleyes:
Now we will learn other fuses and options on 18F4431..
But I still mean we must be WIZARD to get all we need..
There is 400 pages of datasheet.
All what I want to make is UHU type of PMDC control to interface it to MACH3 software for CNC.
Idea come from original UHU controller from Uli Hubert from Germany.
He use ATTINY2313 and make full stf WOW.
Can you image these :
He put in that little chip quadrature encoder full measure of his speed , direction and velocity reading ,
capture coming pulse from PC wich is from 1-5 uS, PID control , RS232 terminal , 20KHz PWM , current measure , and motor control ...ETC.
Then with 18F4431 must be much easy to do that.
His UHU controller is maybe the best in world and I was test it like finished module on my friend CNC wich work 2 years without error 10h/day .

Regards Robert

phoenix_1
- 31st August 2009, 22:58
Hi,
This is cut and pasted from a larger program I have and this digested version is not tested so take it for what it is please. It's written for the 18F2431 so double check the pin assignments for the QEI module.



DEFINE HSER_RCSTA 90h 'USART receive status init.
DEFINE HSER_TXSTA 24h 'USART transmit status init.
DEFINE HSER_BAUD 57600 'Baudrate is 57600.

ANSEL0 = 0 'All inputs as digital

PortA = 0
PortB = 0
PortC = 0

TRISA = %11000 'QEI pins as inputs.
TRISB = %00000000
TRISC = %10000000 'USART RX pin as input.

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.

CLEAR

Main:
Gosub GetPosition
HSEROUT ["QEI Count: " , #Position, 10]
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


Again, no guarantees but I hope it serves as a starting point for you.

/Henrik.

What if my ENCODER have only A and B output's and dont have INDEX pin ?
Can I use it ???

HenrikOlsson
- 1st September 2009, 06:20
Dave,
I've never used the PLL on this series of PIC's I've run it on 4Mhz and 20Mhz "straight" though without problems, x-tals though, not resonators. Please keep as posted if/when you find the culprit.

Robert,
Yes the UHU-servo chip is impressive - I have a couple of them on 160V/25A drives (the HP-UHU) and they perform very well indeed. I've been meaning to play with replacing the UHU chip with a 18F2431 to gain some performance, mostly in the encoder count frequency. I've found the max encoder count frequency on the UHU-chip to be ~130kHz. Haven't got around to that yet though....

You can use the encoder without index, the difference would be that the count doesn't automatically reset each each rev of the motor - something you probably don't want it to do anyway. Read up on the operation of the QEI module and QEICON register - you can set it up to operate in a few different ways.

/Henrik.

phoenix_1
- 1st September 2009, 07:38
Hi Henrik,
Yes I will measure a couple of encoder today to find if there INDEX pin.
Maybe with some logic chip from CD40XX serie I can provide INDEX pulses if there isn't INDEX pin ?

Regards and thanks for replay to all.
Robert :)

phoenix_1
- 1st September 2009, 08:50
Hi mackrackit and Henrik,
My PIC is 18F4431
I have success with 20MHz XTAL and define osc 20 , fuse HS.
I found motor with encoder with INDEX pin and little modific Hanrik code.
Result is 16 bit counter but I must find calculation becouse my encoder is 500 pulse per full rev of motor shaft.
Henrik you was give me good way for start with 18F4431..thanks man again.

mackrackit
- 1st September 2009, 09:00
Hi mackrackit,
My PIC is 18F4431
I have success with 20MHz XTAL and define osc 20 , fuse HS.
Mine works fine with 20Mhz HS also. It is when I try to run at 40Mhz HSPLL the problem starts. Maybe I have some bad 10s that are running a bit fast???
I have some new 10Mhz on order, find out then.

HenrikOlsson
- 1st September 2009, 11:28
Hi,
Again, you don't have to use the index channel, it'll work fine without it. If you set up the QEI module to reset on index (as in my example) and the encoder doesn't have an index channel the counter will simply roll over from $FFFF to $0000 or from $0000 to $FFFF depending on direction. Carefully read the section of the datasheet, play with it a bit and read the datasheet again, you'll figure it out ;-)

/Henrik.

phoenix_1
- 1st September 2009, 20:31
Hi Henrik,

I started playing with the 4431 DIP version and wonder if you have ran into this with the one you are using. Maybe it is a 4331 problem, maybe whole series.

When using a 4Mhz resonator and have the config set for HSPLL and DEFINE OSC 16 all works well.

If I replace the 4Mhz with a 10 Mhz and try DEFINE OSC 40 everything goes erratic.
The PIC runs but even a simple "blinky" will blink randomly.

Here is the very simple code and configs I was playing with to set the OSC.


@ __CONFIG _CONFIG1H, _OSC_HSPLL_1H
@ __CONFIG _CONFIG2H, _WDTEN_ON_2H & _WDPS_512_2H
@ __CONFIG _CONFIG2L, _BOREN_OFF_2L & _PWRTEN_ON_2L
@ __CONFIG _CONFIG3H, _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L

DEFINE OSC 16

START:HIGH PORTD.1:PAUSE 500
LOW PORTD.1:PAUSE 500:GOTO START
Maybe you need to set manuel 4 nibbles of config manuel :



bit 7 IESO: Internal External Switchover bit
1 = Internal External Switchover mode enabled
0 = Internal External Switchover mode disabled
bit 6 FCMEN: Fail-Safe Clock Monitor Enable bit
1 = Fail-Safe Clock Monitor enabled
0 = Fail-Safe Clock Monitor disabled
bit 5-4 Unimplemented: Read as ‘0’
bit 3-0 FOSC<3:0>: Oscillator Selection bits
11xx = External RC oscillator, CLKO function on RA6
1001 = Internal oscillator block, CLKO function on RA6 and port function on RA7
1000 = Internal oscillator block, port function on RA6 and port function on RA7
0111 = External RC oscillator, port function on RA6
0110 = HS oscillator, PLL enabled (clock frequency = 4 x FOSC1)
0101 = EC oscillator, port function on RA6
0100 = EC oscillator, CLKO function on RA6
0010 = HS oscillator
0001 = XT oscillator
0000 = LP oscillator

and probe ?

phoenix_1
- 1st September 2009, 20:40
Hi,
Again, you don't have to use the index channel, it'll work fine without it. If you set up the QEI module to reset on index (as in my example) and the encoder doesn't have an index channel the counter will simply roll over from $FFFF to $0000 or from $0000 to $FFFF depending on direction. Carefully read the section of the datasheet, play with it a bit and read the datasheet again, you'll figure it out ;-)

/Henrik.
Yes I was read that part a couple of time and again and again...
How I see that full 18F4431 is extra MCU and most of you must do is to set
tons of nibbles on config registers but!
If you do that right you will have pleasure to use many finished hardware periferials without to much programing...inside 18F4431 is so many good things...

Regards Robert:rolleyes:

phoenix_1
- 3rd September 2009, 06:50
Here is success probe with count encoder from 0 to 2000 for one turn of shaft of motor.


' 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:)

phoenix_1
- 5th September 2009, 22:51
Now little about PMDC breaking.
1.H-bridge drive of PMDC:
3630
2.Slow DINAMIC break by short with same polarity of power supply.
Bad idea for fast servo PID control.
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.
3632
Thank's and regard's Robert :)

mackrackit
- 8th September 2009, 03:48
Hi,
Again, you don't have to use the index channel, it'll work fine without it. If you set up the QEI module to reset on index (as in my example) and the encoder doesn't have an index channel the counter will simply roll over from $FFFF to $0000 or from $0000 to $FFFF depending on direction. Carefully read the section of the datasheet, play with it a bit and read the datasheet again, you'll figure it out ;-)

/Henrik.

Hi Henrik,
I do not have an encoder to play with but I might some day :)
Reading through all of this I am not seeing how the count will go up or down depending on the direction.

Would you mind enlightening me?

HenrikOlsson
- 8th September 2009, 06:31
Hi,
The encoder outputs channels which has a 90° phase shift between them.

The QEI-module can be set to 2X or 4X mode (X4 is the most common) but the easiest to understand is the 1X mode....

Simply, if the B channel is high on the rising edge of the A channel then you count up, if the B channel is low on the rising edge of the A channel then you count down. In 2X mode you "trig" on the rising edge of both channels (giving you a resolution of 2X the line count of the encoder) and it 4X mode you trig on the rising AND falling edge of BOTH channels (giving you a resolution of 4X the line count of the encoder).

If you look up incremental or quadrature encoder on Wikipedia you'll find more details.

/Henrik.

mackrackit
- 8th September 2009, 13:36
Thanks Henrik,

I understand now.

phoenix_1
- 8th September 2009, 16:46
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:

phoenix_1
- 10th September 2009, 20:17
OK now next step are steped.
I write calculation to increment in CW my variable defined as LONG to be incremented from position buffer
which go from 0-12500 and again and again..


' Pic 18F4431 @ 20MHz true XTAL
define osc 20
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_SPBRG 64
DEFINE HSER_CLROERR 1
ADCON0=0
ANSEL0=0

PortA = 0
PortB = 0
PortC = 0

TRISA = %011100
TRISB = %00000000
TRISC = %10000000

QEICON=%10011000
DFLTCON = %00111000
MAXCNTL = %11010100
MAXCNTH = %00110000
PosLow VAR BYTE
PosHigh VAR BYTE
PosTemp VAR BYTE
Position VAR WORD
y var LONG
x var BYTE
x = 0
y = 0
POSCNTL = 0
POSCNTH = 0
PIR3.2 = 0
CLEAR

Start:
Gosub GetPosition
y = (x * 12500) + position
HSEROUT [dec y]
Pause 10
Goto Start


GetPosition:
PosHigh = POSCNTH
PosLow = POSCNTL
PosTemp = POSCNTL
If PosLow - PosTemp = 0 then Goto Done
PosHigh = POSCNTH
PosLow = POSCNTL
Done:
Position = POSHIGH * 256 + PosLow
if PIR3.2 = 1 then x = x+ 1
PIR3.2 = 0
RETURN
END

Now I can count a long trip of mechanic of machine which is present in LONG variable in CW direction.
But I have new problem in my head all these days and it is next.
I have BIT which indicate direction of motor and it is in QEICON.5.
If QEICON.5 is 0 then we go CCW and if it is 1 then we go CW direction.
Now if we go CW and stop motor it wil be 1 all the time to next move
and if we go CCW it will be 0 and after we stop from CCW it will be 0 all time to next move..
Confuse how to make matematic to implement new formula for decrement LONG variable in CCW :
y = y - (12500-position) or similar becous in CCW position go from 12500-0 and again 12500-0....
If any idea or someone want to help THANKS.
Regards Robert :)

mackrackit
- 11th September 2009, 10:19
Maybe I am missing something but if you stop the motor and then restart it you know the direction?? Set the direction bit when you start the motor.

phoenix_1
- 12th September 2009, 12:58
Here is code which can measure and put to Y variable defined as LONG position of mechanic on machine to 32bit and count up and down.
I am not good programmer but code work good.



' 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=%10011000
DFLTCON = %00111000 ' enable error filter for all capture inputs
MAXCNTL = %11010100 'low set for maxcnt of 12500 becouse have gear 6.25:1
MAXCNTH = %00110000 'hig set for maxcnt of 12500 becouse have gear 6.25:1
'MAXCNTL = %00000001 'lowbyte = 207
'MAXCNTH = %00000000 '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.
y var long 'Total pulse count storage variable 32bit
x var byte 'Number of full shaft rotation of 360'
z var BIT 'Actual bit if any move of shaft to any direction
h var BIT 'direction bit 0 for left , 1 for right turn of encoder
z = 0
x = 0
y = 0
h = 0
POSCNTL = 0 ' clear lowbyte of counter for start
POSCNTH = 0 ' clear highbyte of counter for start
PIR3.2 = 0
CLEAR

Start:
Gosub GetPosition
y = (12500 * x) + position ' increment total counter
if z = 1 and h = 0 then y = y-(12500-position) ' dectement total counter
HSEROUT [DEC y] ' debug via rs232 @ 19200
Pause 100 'Wait....
Goto Start '...and do it again.


GetPosition:
z = 0
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
z = 1
Done:
Position = POSHIGH * 256 + PosLow 'Put high and lowbyte together.
h = QEICON.5 'QEICON.5 for right = 1 for left = 0
if PIR3.2 = 1 and h =1 then x = x+ 1
if x <> 0 and PIR3.2 = 1 and h =0 then x = x- 1
PIR3.2 = 0 'PIR3.2 maxcount transition down or up was detected
h = 0
RETURN
END

mackrackit
- 12th September 2009, 13:22
Here is code which can measure and put to Y variable defined as LONG position of mechanic on machine to 32bit and count up and down.
I am not good programmer but code work good.

What is a good programmer???
If it works as you want then it is good. ;)

Acetronics2
- 12th September 2009, 13:47
Hi, Dave

For HSPLL Osc ...

I just run a 12 Mhz XTAL on a 18F4420, PLL Engaged ... everything fine.

So, May be the XTAL ... or may be your board layout ( 40 Mhz is HF !!! ) or ... poor quality capacitors.

Alain

mackrackit
- 12th September 2009, 14:13
Hi, Dave

For HSPLL Osc ...

I just run a 12 Mhz XTAL on a 18F4420, PLL Engaged ... everything fine.

So, May be the XTAL ... or may be your board layout ( 40 Mhz is HF !!! ) or ... poor quality capacitors.

Alain
I am using a resonator so maybe that is off a bit on the specs.

All this is on a bread board so maybe the problem is there but I have 4550s running at 48Mhz on same type of boards. Using the PicKit2 for the power supply. Maybe more caps across VSS/VDD is needed.

I got busy with something else so I have not had time to play with it lately. Still sitting on the bench... waiting...

mackrackit
- 19th September 2009, 18:27
I started playing with the 4431 DIP version and wonder if you have ran into this with the one you are using. Maybe it is a 4331 problem, maybe whole series.

When using a 4Mhz resonator and have the config set for HSPLL and DEFINE OSC 16 all works well.

If I replace the 4Mhz with a 10 Mhz and try DEFINE OSC 40 everything goes erratic.
The PIC runs but even a simple "blinky" will blink randomly.

In my haste I made the stupid mistake of NOT having capacitors near the PIC across VDD/VSS. A friend pointed this out.

The PIC runs fine at 40Mhz.

phoenix_1
- 21st September 2009, 22:08
In my haste I made the stupid mistake of NOT having capacitors near the PIC across VDD/VSS. A friend pointed this out.

The PIC runs fine at 40Mhz.
You is the member of simple peoples TEAM... :-) like me.
Regards Robert :)

mackrackit
- 23rd September 2009, 09:58
Out of the many posts, this one attract my attention. I believe it is possible for anyone to participate.
Excellent ! I like it very much. :):(

We gotta have some fun while we bang our heads against the wall :)

phoenix_1
- 24th September 2009, 23:46
Out of the many posts, this one attract my attention. I believe it is possible for anyone to participate.
Excellent ! I like it very much. :):(

Yes I spend these days about 6-7 hour experimenting with PID rutine...
It is the most hard part to make PID to work.....
Soon I will post result of my expiriance...
For now regards and if any example from anyone pls post
Robert:)
P.S why simple when we can hard ..

phoenix_1
- 31st October 2009, 22:25
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



@ __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

HenrikOlsson
- 1st November 2009, 10:12
So, are you saying that it works now? No more "ticks" or "jumps", always smooth? What was the actual problem?

phoenix_1
- 1st November 2009, 14:45
So, are you saying that it works now? No more "ticks" or "jumps", always smooth? What was the actual problem?
To complicate calculation of position what I was make - no need for that!
I was buy "Running small motors with Pic by Harprit Singh Sandhu" in middle time and there is very good examples and sources about 18F4431 ans 16F876 - 877.After reading a couple of day's it was put me in righ direction.
That complicate calc of position was make big big proposition in interrupt and Pic was do error's .....
I must work more on that program but now it work pretty good.
Now I want remove part of reding key on RA1 and put a couple more interrupt's. One for RS232 , one for ADC reading and one for dir/step.

The best regards to all and you Henrik special.
Any suggest are welcome
/Robert

phoenix_1
- 1st November 2009, 21:56
So, are you saying that it works now? No more "ticks" or "jumps", always smooth? What was the actual problem?

Here is youtube video what I was upload
VIDEO of project (http://www.youtube.com/watch?v=x8T2YmPA7wY)
Motor move in pid control loop commanded by 16F877 which is central CPU for future Baloon printing machin which soon finished.
Machin move 8 baloon in cyrcle and print two color in same time on two printing platform controled with pneumatic via valves...etc.
On video motor only move at small distance on my desk but it was tested real and work very good.
My next project will be real PID controller to work with MACH3 software.

Thanks Henrik for PID and Darrel for DT instant interrupt and to all here.
/Robert

phoenix_1
- 22nd November 2009, 19:45
http://www.youtube.com/watch?v=NFAegIl2e_c
Sorry comment is in my language - Serbian.
Regards to all
/Robert