PDA

View Full Version : 18F4431 Quaduature Encoder



Rleonard
- 19th February 2007, 18:38
I am not able to set up
the Quaduature Encoder Interface
for a MicroChip 18F4431.
Any help with the set up code
would be appreciated.

Thank you in advance.

Richard

HenrikOlsson
- 19th February 2007, 21:14
Hi,
This works for me on 18F2431, should be the same. Don't forget to set the QEA, QEB & QEI pins to inputs.


QEICON = %00010100 'Setup QEI, 4X mode, reset on indexpulse.

PosHigh var BYTE
PosLow var BYTE
PosTemp var BYTE

Position var WORD 'Motor position in encoder counts.

Main:
Gosub GetPosition
HSEROUT [#Position,13,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 low byte. This
'is prevented by reading the high 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 = POSCNTH 'Get high byte again

If PosHigh - 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


/Henrik Olsson.

Rleonard
- 19th February 2007, 21:50
Henrik,
Thank you for the code sample

Rleonard
- 19th February 2007, 22:50
Henrik,
The problem was that I did not set
the ANSEL0 register to digital i/o.

Great tip on counter overflow.
I will definately incorporate.

Thank You again.
Richard

Bruce
- 19th February 2007, 23:32
Isn't that an awesome controller? The motion feedback module with pulse width & frequency measurement is really handy.

Note: On the 28-pin version, forget using RE3 as an input. I tried, and submitted a support ticket to Microchip. Here's what I received back;

RE3 pin in PIC18F2331/2431 has been removed as a digital input. Hence, pin no. 1 of PIC18F2331/2431 can be used for MCLR/ Vpp only.

This change will be notified in a datasheet's (DS39616B.pdf) future update.

HenrikOlsson
- 20th February 2007, 06:26
Hi Bruce,
Thank you for info regarding RE3/MCLR as input.

It sure is a cool device. Using Darrel's interupt routines I managed to get motor controller for my robot working, with PID filter and all. Very fun project.

However.....I never managed to get QEI module going in velocity mode. I made a few attempts to begin with but could never quite figure it out so I went for my own velocity calcs (newPos-oldPos). Any pointers?

Thanks!
/Henrik Olsson.

Bruce
- 20th February 2007, 14:02
Hi Henrik,

I haven't messed with QEI yet, but if I do get something going, I'll port it from C to PBP and post it here.

My primary interest in this one was the new high-speed A/D, and motion feedback module for background pulse & freq measurements.

HenrikOlsson
- 20th February 2007, 15:22
Bruce,
I see. Thanks anyway!

/Henrik Olsson.

hell_pk
- 31st July 2007, 05:52
Hi!
i got hold of Microchip PICDEm MC LV board with 3-phase BLDC motor.It has a CD that conatins source code in assembly. I was wondering if someone has done same thing in pic basic i.e used power PWM module of 18F4431.I tried according to application note but to no avail. Here is my code.could someone point me out in right direction.some code snipet would be appreciated.
thanks

while true
PTCON0=00000000 'page 8,step 1
PTPERL=$37 'a guess
PTPERH=$01
PWMCON0=01001111 'step 3
PWMCON1=00000001 'step 4
DTCON=00000000 ' a guess
OVDCOND=00000000 'step 6
OVDCONS=00000000
FLTCONFIG=00000000
'POVD=00000000
'SEVTCMP=$0000
'step 8
SEVTCMPL=$00
SEVTCMPH=$00
PDC0L=$00
PDC0H=$00
PDC1L=$00
PDC1H=$00
PDC2L=$00
PDC2H=$00
PDC3L=$00
PDC3H=$00


TRISC.0=1
PTCON1=10000000 'or PTCON1.7=1
wend

hell_pk
- 1st August 2007, 08:07
Hi!
i got hold of Microchip PICDEm MC LV board with 3-phase BLDC motor.It has a CD that conatins source code in assembly. I was wondering if someone has done same thing in pic basic i.e used power PWM module of 18F4431.I tried according to application note but to no avail. Here is my code.could someone point me out in right direction.some code snipet would be appreciated.
thanks

while true
PTCON0=00000000 'page 8,step 1
PTPERL=$37 'a guess
PTPERH=$01
PWMCON0=01001111 'step 3
PWMCON1=00000001 'step 4
DTCON=00000000 ' a guess
OVDCOND=00000000 'step 6
OVDCONS=00000000
FLTCONFIG=00000000
'POVD=00000000
'SEVTCMP=$0000
'step 8
SEVTCMPL=$00
SEVTCMPH=$00
PDC0L=$00
PDC0H=$00
PDC1L=$00
PDC1H=$00
PDC2L=$00
PDC2H=$00
PDC3L=$00
PDC3H=$00


TRISC.0=1
PTCON1=10000000 'or PTCON1.7=1
wend

Rleonard
- 1st August 2007, 14:43
I wish I could help but I am using the 18F4431 in a completely
different manner.
Richard

Bruce
- 1st August 2007, 18:49
I don't have the 18F4431 or Microchip motor control board, but this works
on the 18F2431. It outputs PWM on RB0,RB1,RB2,RB3,RB4 and RB5 with a
varying duty cycle. Ramps up, then down.

It should be at least enough to get you started.


DEFINE OSC 20

Duty VAR WORD
PORTB = $FF
TRISB = 0

PTCON0=$00 'page 8,step 1
PTPERL=$A0 ' $01A0 = 12kHz
PTPERH=$01
PWMCON0=%01011110 'would be %01011111 for the 18F4431
PWMCON1=%00000001 'step 4
DTCON=$00
;OVDCOND=$00 'step 6 ; May want to un-comment these based on your PIC & board.
;OVDCONS=$00
;FLTCONFIG=%10110011
;POVD=00000000
;SEVTCMP=$0000
;step 8
SEVTCMPL=$00
SEVTCMPH=$00
PDC0L=$00
PDC0H=$00
PDC1L=$00
PDC1H=$00
PDC2L=$00
PDC2H=$00
;PDC3L=$FF ; un-comment for 18F4431
;PDC3H=$00
PTCON1=%10000000

Main:
FOR Duty = 50 TO $500 STEP 4
ASM
bsf PWMCON1,UDIS ;Disable the PWM buffer update
MOVFF _Duty,PDC0L
MOVFF _Duty+1,PDC0H
MOVFF _Duty,PDC1L
MOVFF _Duty+1,PDC1H
MOVFF _Duty,PDC2L
MOVFF _Duty+1,PDC2H
;MOVFF _Duty,PDC3L ;un-comment for 18F4431
;MOVFF _Duty+1,PDC3H
bcf PWMCON1,UDIS ;Enable the PWM buffer update
ENDASM
PAUSE 50
NEXT Duty
FOR Duty = $500 TO 50 STEP-4
ASM
bsf PWMCON1,UDIS ;Disable the PWM buffer update
MOVFF _Duty,PDC0L
MOVFF _Duty+1,PDC0H
MOVFF _Duty,PDC1L
MOVFF _Duty+1,PDC1H
MOVFF _Duty,PDC2L
MOVFF _Duty+1,PDC2H
;MOVFF _Duty,PDC3L ;un-comment for 18F4431
;MOVFF _Duty+1,PDC3H
bcf PWMCON1,UDIS ;Enable the PWM buffer update
ENDASM
PAUSE 50
NEXT Duty
GOTO Main

END
This is just a slight modification to what you posted before. To work with the
18F2431. I haven't done much beyond this with the PCPWM module. Not yet
at least..;o}

HTH

BigWumpus
- 1st August 2007, 22:59
I'm using the 18F2431 too.
And I begun with the PICDEm MC LV board...

It's a great uC ! (UART, I2C, fast AD, 3-times PWM...)
I use it as a PI(D)-Controller for a BLDC-Motor.
And I use it for his fast AD-Converters in a CR-Tuning-Box.

The Quadrature-Encoder isn't very strange ... the whole business with this chip is to use the right timers for the right tasks and use the right prescalers !!

;-)

Bruce
- 1st August 2007, 23:37
Yeah this one is a nifty series PIC for sure. Sampling 4 x A/D inputs at once is
a very handy feature.

See this post http://www.picbasic.co.uk/forum/showthread.php?t=6768

I just received a few samples of the new USB 18F2553. 12-bit A/D on this
one is nice, but the 18F2431 is still my favorite. Now, if I can just find more
time to play with it..;o}

hell_pk
- 2nd August 2007, 07:04
Thanks a lot Bruce.
I just want to get started with PPWM and then build my own code for brushless DC motor control.
Thanks for your code although its in assembly.i will figure it out.

Bruce
- 2nd August 2007, 11:59
Here's the BASIC equivalent commands to the right of the assembly version.


FOR Duty = 50 TO $500 STEP 4
ASM
bsf PWMCON1,UDIS ; PWMCON1.1 = 1
MOVFF _Duty,PDC0L ; PDCOL = Duty.LowByte
MOVFF _Duty+1,PDC0H ; PDC0H = Duty.HighByte
MOVFF _Duty,PDC1L ; PDC1L = Duty.LowByte
MOVFF _Duty+1,PDC1H ; PDC1H = Duty.HighByte
MOVFF _Duty,PDC2L ; PDC2L = Duty.LowByte
MOVFF _Duty+1,PDC2H ; PDC2H = Duty.HighByte
;MOVFF _Duty,PDC3L ; PDC3L = Duty.LowByte
;MOVFF _Duty+1,PDC3H ; PDC3H = Duty.HighByte
bcf PWMCON1,UDIS ; PWMCON1.1 = 0
ENDASM
PAUSE 50
NEXT Duty
bsf PWMCON1,UDIS just sets bit 1 in PWMCON1. bcf PWMCON1,UDIS then
clears the UDIS bit.

MOVFF is move file to file.

MOVFF _Duty,PDC0L moves the low byte of Duty into file register PDC0L.

MOVFF _Duty+1, PDC0H moves the high byte of Duty into file register PDC0H.

Placing the underscore before the _Duty variable allows you to access the
variable declared in BASIC with assembler.

So the BASIC version would look like this;


FOR Duty = 50 TO $500 STEP 4
PWMCON1.1 = 1
PDC0L = Duty.LowByte
PDC0H = Duty.HighByte
PDC1L = Duty.LowByte
PDC1H = Duty.HighByte
PDC2L = Duty.LowByte
PDC2L = Duty.HighByte
PDC3L = Duty.LowByte
PDC3H = Duty.HighByte
PWMCON1.1 = 0
PAUSE 50
NEXT Duty

FOR Duty = $500 TO 50 STEP-4
PWMCON1.1 = 1
PDC0L = Duty.LowByte
PDC0H = Duty.HighByte
PDC1L = Duty.LowByte
PDC1H = Duty.HighByte
PDC2L = Duty.LowByte
PDC2L = Duty.HighByte
PDC3L = Duty.LowByte
PDC3H = Duty.HighByte
PWMCON1.1 = 0
PAUSE 50
NEXT Duty

NatureTech
- 8th August 2007, 17:21
Bruce,

That's a super start to a beginner like me.

But,i gotta some problem with the PWM Period value.I mean how to find the values for .. say...a PIC18F4431 running at OSC 20 , wish to set base period 19.5KHZ.How to find this using equation 17-1 ( i use this equ since it's free running mode here).Apart from that , how to calculate the min & max value of dutycycle?.Dohh...it's really bothering me no matter how many times i try it.

Could you guide me how to do this.I am a bit confused.The rest seems yeeha as it's taught in "863 MTR" from Microchip.


Regards.

NatureTech
- 9th August 2007, 13:54
Anyone..know how to do it?.

Bruce
- 9th August 2007, 14:22
(PTPER+1) x PTMRPS
TPWM = ------------------
Fosc/4

Equation 17-1 assumes you know the value in PTPER.

TPWM is the period of the PWM frequency.
PTPER is the value loaded into the PWM period register.
PTMRPS is the PWM timer prescaler. 1, 4, 16 or 64.

1/19,500 = 0.000051282. This is the period for a PWM frequency (TPWM) of 19.5kHz.

At 20MHz the instruction cycle time = 1/5MHz = 200nS.

To find the value to load into PTPER, divide the PWM period by the instruction cycle time.

0.000051282/0.0000002 = 256.410. Subtract 1 for 255.

If you load 255 into the period register, it will generate a PWM frequency of around 19.5kHz.

PTPERL=$FF ' low byte = $FF
PTPERH=$00 ' high byte = $00

Assuming a 20MHz osc, 1:1 prescaler, Fosc/4 = 5Mhz, so plug this into equation 17-1.

TPWM = (255+1) * prescaler
-------------------
Fosc/4

TPWM = 256/5MHz = 0.0000512.
Frequency = 1/TPWM so 1/0.0000512 = 19.531kHz.

The period register is 12-bits wide, so the minimum period for a given oscillator speed = the
instruction cycle time * ($0FFF+1) * the prescaler.

I.E. at 40MHz the instruction cycle time = 1/10Mhz = 100nS.

100ns * $1000 = 0.0004096. 1/0.0004096 = 2.441kHz.

At 10MHz 1/2.5Mhz = 400nS. 400nS * $1000 = 0.0016384.

1/0.0016384 = 610Hz, etc, etc..

You can see from Table 17-1 how the PWM timer prescaler affects the PWM frequency.
I.E. 2.441kHz/64 = 38Hz, etc,..

Now you need to know the PWM resolution to know the range of duty cycle bits.

Note: Resolution is the number of bits you have to control the duty cycle. Not the PWM
frequency.

For PWM resolution use the equation below. Equation 17-3 'as shown in the data sheet'
doesn't produce the same figures for PWM resolution shown in Table 17-2.

log(Fosc/Fpwm)
Resolution = ------------------
log(2)

At 20MHz, with a PWM frequency of 19.5kHz;

log(20MHz/19.5kHz) 3.010995384
Resolution = ------------------ = ----------- = 10.003
.301 .301

So we 10-bit resolution. The value loaded into duty cycle registers would range from 0 to
1023 or $00 to $03FF.

512 loaded into the duty registers should give ~50% duty at 19.5kHz.

There's a lot more to the PCPWM module than this, but it should help you get
started. I haven't played much with this particular feature.

NatureTech
- 10th August 2007, 08:48
Hi Bruce,

Sorry if i pester you a lot.Well,it drive me crazy to know about it.This should be more than enough for me to get started.Yes.You are right.This is part of it and not complete yet.But anyhow,it's clear enough for me to understand.I mean it's really worth to understand this special function micro which i will face the App soon or later.

Thanks a lot.

gokulrred
- 25th September 2011, 03:13
hi all...
i am starter for PIC 18F4431......
i want to interface a encoder to that...
what are the things i need to take care?

how to do?
is it like a plug and play?(i hope no)

cncmachineguy
- 25th September 2011, 04:03
First is the same thing that should be first for every new pic, can you blink a led? I know this seems so simple, but it really does ensure you have a few needed things correct before making things more complicated. After 10+ years, I still blink LEDs the first time I use a new pic.

Charles Linquis
- 25th September 2011, 04:23
I use the "Hello World" out the serial port test. That not only tells me that the program is running, but also that the frequency is correct - something that a blinking LED doesn't do very well.

Archangel
- 28th September 2011, 01:58
First is the same thing that should be first for every new pic, can you blink a led? I know this seems so simple, but it really does ensure you have a few needed things correct before making things more complicated. After 10+ years, I still blink LEDs the first time I use a new pic.While Bert's statement might sound like just so much talk to some I vouch for his opinion especially if you are moving to 18F chips for the first few times, I had an amazingly difficult time just getting this chip to blink the LED, owing to programmer issues, config issues . . . . ( I Know, men do not HAVE ISSUES, but PICs some times do :D).

boroko
- 9th June 2012, 12:25
HI All,
This explanation has been the best one that I have found concerning the use of the PCPWM. That said, there still seems to be a bit of mystery surrounding it's use, at least to me. I mapped out the formulas in Excel, but I am still having trouble getting my head around the details. I'm trying to make a generic H-bridge for low frequencies and keep running into the wall. An 18F1330 with two pots, a switch, and the FETs with drivers. One Pot is for Frequency, the other is for Duty. The switch controls if the output is pulsed DC or cycles both ways. I'm not understanding the interaction of the frequency to the Duty. I can control the Freq just fine, but it makes a mess of the duty. Currently, the application needs it to run from 3 Hz to 100Hz with control from low power to high power (~5%-95% duty). I can see that there is a dependency with the PWM resolution, but I'm not sure how to manage it. I can get the PTPER values within 0-4096, but the resolution gets out of range. I'm thinking I need to find some way to scale the Duty to the PTPER values, and adjust accordingly, but I haven't managed to make it click. Any suggestions?
'************************************************* ***************
'* Name : PCPWM_1330_H-bridge84.BAS *
'* Author : Mark Rokus *
'* Notice : Copyright (c) 2012 Controlled Surroundings Inc. *
'* : All Rights Reserved *
'* Date : 6/9/2012 *
'* Version : 1.0 *
'* Notes : 18F1330 to drive H bridge: *
'* : (2)L6378 drivers to (4) FDP22N50N N-FETs *
'* used PCPWM_1330_H-bridge5 to test Hardware on separate FETS
'* New rewrite using ints
'* moved switch to RB3, rewire drivers complementary
'* NOTE: Int not working, Not going into AC
'* Freq and Duty not correct
'************************************************* ***************
' 18F1330
' ---------------------u----------------------
' Freq -1|RA0/AN0/INT0 RB3/INT3/CMP1|18- Switch
' Duty -2|RA1/AN1/INT1 RB2/INT2/CMP2|17- Pad
' Pad -3|RA4/TOCKI/AN2 RA7/OSC1/CLKI|16- Pad
' Vpp -4|RA5/MCLR/vpp RA6/OSC2/CLKO/AN3|15- Pad
' Gnd -5|-- VSS VDD++|14- 5 vdc
' Tx -6|RA2/TX/CK RB7/PGD/PWM5|13- PGD
' Rx -7|RA3/RX/DT RB6/PGC/PWM4|12- PGC
' Pad -8|RB0/PWM0 RB5/PWM3|11- Q1/Q4 PWM
' Pad -9|RB1/PWM1 RB4/PWM2|10- Q2/Q3 PWM
' |___________________________________________|

#CONFIG
CONFIG OSC = INTIO2 ;Internal oscillator, port function on RA6 and RA7
#ENDCONFIG
DEFINE OSC 4 ' Actually @ 2MHz
OSCCON = %11011100 ' INTOSC primary, 2MHz
'****** Hardware Serial Setup ***************
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 8 ' 57600 Baud @ 2MHz, -3.55%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
'***************************************
TRISA = %00000011 ' PortA : outputs except RA.0/RA.1= AN
TRISB = %00001000 ' all outputs ex: RB.3 switch i/p
INTCON = 0 '
INTCON2 = 0
CMCON = 0 ' Comparators off
clear
'**** Analog setup ****
ADCON1 = %00001100 ' AN0,AN1 Analog: VDD ref. RA4 & RA6 DIO
ADCON2 = %10010001 ' Right justified, 8 Tad, Fosc/8
'***** PWM Setup ? ********************
PTCON0 = %00001110 ' 1:1 post, Fosc/256 (1:64) pre, UpDown(...00 free)
PTCON1 = %11000000 ' PWM Time Base timer on, Count Down
PWMCON0 = %00110111 ' 0-3 PWM, complementary
PWMCON1 = 1 ' 1:1 postscale, updates enabled, overrides sync
DTCON = 0 ' zero dead-time
PTCON1 = %10000000 ' PWM time base is ON, counts up
FLTCONFIG = 0 ' disable fault A
OVDCONS = %00000000 '
'::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::
' Variable definition
'::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::
PORTB = 0 ' clear port latch
Fraw var word ' Raw reading for Frequency
Freq var word ' Frequency of PWM
Draw var word ' Raw reading for Duty
Duty Var Word ' Duty of PWM
Sw var PORTB.3 ' switch input for AC or Positive only
'************************************************
Start:
hserout ["1330_H-bridge83",13,10]
pause 500
'*************************************
PosOnly:
If sw = 0 then ac ' mode check
ADCON0 = %00000011 ' Start conversion on AN0
WHILE ADCON0.1=1 ' Wait for it to complete
WEND
Fraw.HighByte = ADRESH ' get result from AN0
Fraw.LowByte = ADRESL '
ADCON0 = %00000111 ' Start conversion on AN1
WHILE ADCON0.1=1 ' Wait for it to complete
WEND
Draw.HighByte = ADRESH ' get result from AN1
Draw.LowByte = ADRESL '
Freq = (Fraw) max 3 '
Duty = (Draw*3) max 1 '
PTPERH = Freq.highbyte 'load timer: Freq low byte
PTPERL = Freq.lowbyte ' Freq low byte
PDC1H = Duty.HighByte ' PWM duty on Out1
PDC1L = Duty.LowByte
OVDCOND = %00001000 ' enable PWM3 OUT1 (Q1/Q4 on RB5)
hserout ["Duty ",dec duty," PosFreq ",dec Freq]
goto PosOnly ' Loop
'************************************************* **************************
AC: ' sequence for generating Alternating pulses
PosAlt: 'drive Positive pulse on bridge
If sw = 1 then posonly ' mode check
PIR3.4 = 0 ' reset PWM Int flag
while PIR3.4 = 0
OVDCOND = %00001000 ' enable PWM3 OUT1 (Q1/Q4 on RB5)
ADCON0 = %00000011 ' Start conversion on AN1
WHILE ADCON0.1=1 ' Wait for it to complete
WEND
Fraw.HighByte = ADRESH ' get result from AN0
Fraw.LowByte = ADRESL '
Freq = Fraw max 3 '
PTPERH = Freq.highbyte 'load timer: Freq low byte
PTPERL = Freq.lowbyte ' Freq low byte
wend ' one cycle until Int
NegAlt: ' drive Negative pulse on bridge
PIR3.4 = 0 ' reset PWM Int flag
while PIR3.4 = 0
OVDCOND = %00000100 ' enable PWM1 OUT2 (Q2/Q3 on RB4)
ADCON0 = %00000111 ' Start conversion on AN0
WHILE ADCON0.1=1 ' Wait for it to complete
WEND
Draw.HighByte = ADRESH ' get result from AN1
Draw.LowByte = ADRESL '
Duty = (Draw) max 1 '
PDC1H = Duty.HighByte ' PWM duty on Out1
PDC1L = Duty.LowByte
wend ' one cycle until Int
hserout ["Duty ",dec duty," ACFreq ",dec Freq]
goto AC ' Loop
end

So I guess the question is: Can anyone explain the relationship between PTPER and PDCx in this dynamic environment in a way that I'm not seeing?
Thanks
Bo

HenrikOlsson
- 10th June 2012, 11:10
Hi,
Basically, when you change the frequency (which you do when you change the PTPER) you also change the resolution. So, if you set the duty cycle to 50% at one frequency and then change the frequency the actual dutycyle will also change.

Basically the module is counter and two comparators. When the counter starts at 0 the output is set, when it "hits" the value of the first comparator the outputs is cleared and when the counter "hits" the value of the second compartor the PWM cycle starts over. In this case the value "in" the first comparator is your PDCx (duty)and the value in the second comparator is your PTPER (period) registers.

If the counter was an 8 bit counter and you had your second comparator (PTPER) set to 255 then there would be 256 "steps" to one PWM period. If you then set the value "in" the first compartor (PDC) to 127 you'll get a 50% dutycycle because the output will be set when the counter starts at 0 and cleared when it reaches 127, the counter will then continue to 255 and start over at which point the output is again set and so on.

Now, if you change the value of the second comparator (PTPER) to say 180 there's no longer 256 "steps" to one PWM period, the counter will start over when it "hits" 180 instead of 255 - the PWM period is shorter, PWM frequency is higher. So if you keep the value "in" the first comparator (PDC) unchanged (127) the dutycycle will no longer be 50% because the output will be "on" from 0 to 127 and then off from 127 to 180 at which point the cycle starts over.

The PWM module is more complec than this, as you've noticed, but the above is a basic explanation of the interaction between PWM period and PWM dutycycle.

/Henrik.

boroko
- 10th June 2012, 12:35
Thanks for the explanation Henrik.
The more we pound on this and post the results, the better we can get a handle on it.
That concept started to peek through the fog eventually. The fact that my frequency and duty had to be changeable made it a bit more confusing for me.

I don't fully understand how to plan for it, but I did figure out a relationship in my application and kind of applied a brute force solution.

What I ended up with was this:

'* Working: 1.2Hz to 101Hz, .2% - 97% Duty
'************************************************* ***************
' 18F1330
' ---------------------u----------------------
' Freq -1|RA0/AN0/INT0 RB3/INT3/CMP1|18- Switch
' Duty -2|RA1/AN1/INT1 RB2/INT2/CMP2|17- Pad
' Pad -3|RA4/TOCKI/AN2 RA7/OSC1/CLKI|16- Pad
' Vpp -4|RA5/MCLR/vpp RA6/OSC2/CLKO/AN3|15- Pad
' Gnd -5|-- VSS VDD++|14- 5 vdc
' Tx -6|RA2/TX/CK RB7/PGD/PWM5|13- PGD
' Rx -7|RA3/RX/DT RB6/PGC/PWM4|12- PGC
' Pad -8|RB0/PWM0 RB5/PWM3|11- Q1/Q4 PWM
' Pad -9|RB1/PWM1 RB4/PWM2|10- Q2/Q3 PWM
' |___________________________________________|

#CONFIG
CONFIG OSC = INTIO2 ;Internal oscillator, port function on RA6 and RA7
#ENDCONFIG
DEFINE OSC 4 ' Actually @ 2MHz
OSCCON = %11011100 ' INTOSC primary, 2MHz
'****** Hardware Serial Setup ***************
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 8 ' 57600 Baud @ 2MHz, -3.55%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
'***************************************
TRISA = %00000011 ' PortA : outputs except RA.0/RA.1= AN
TRISB = %00001000 ' all outputs ex: RB.3 switch i/p
INTCON = 0 '
INTCON2 = 0
CMCON = 0 ' Comparators off
clear
'**** Analog setup ****************************
ADCON1 = %00001100 ' AN0,AN1 Analog: VDD ref. RA4 & RA6 DIO
ADCON2 = %10000000 ' Right justified, 0 Tad, Fosc/2
'***** PWM Setup *******************************
PTCON0 = %00001110 ' 1:1 post, Fosc/256 (1:64) pre, UpDown(...00 free)
PTCON1 = %11000000 ' PWM Time Base timer on, Count Down
PWMCON1 = 1 ' 1:1 postscale, updates enabled, overrides sync
DTCON = 0 ' zero dead-time
PTCON1 = %10000000 ' PWM time base is ON, counts up
FLTCONFIG = 0 ' disable fault A
OVDCONS = %00000000 '
'***** Variable definition **********************
PORTB = 0 ' clear port latch
Fraw var word ' Raw reading for Frequency
Freq var word ' Frequency of PWM
Draw var word ' Raw reading for Duty
Duty Var LONG
Sw var PORTB.3 ' switch input for AC or Positive only
'************************************************
Start:
hserout ["1330_H-bridge85",13,10]
pause 500
'************************************************
Main:
If sw = 0 then ' mode check
PWMCON0 = %00110111 ' 0-3 PWM, independant
OVDCOND = %00001000 ' enable only PWM3 OUT1 (Q1/Q4 on RB5)
else
PWMCON0 = %00110000 ' 0-3 PWM, complementary
endif
ADCON0 = %00000011 ' Start conversion on AN0
WHILE ADCON0.1=1 ' Wait for it to complete
WEND
Fraw.HighByte = ADRESH ' get result from AN0
Fraw.LowByte = ADRESL '
ADCON0 = %00000111 ' Start conversion on AN1
WHILE ADCON0.1=1 ' Wait for it to complete
WEND
Draw.HighByte = ADRESH ' get result from AN1
Draw.LowByte = ADRESL '
Freq = (Fraw *3) max 38 '
draw = draw +1
Duty=((freq*Draw)/261) +1
PTPERH = Freq.highbyte 'load timer: Freq low byte
PTPERL = Freq.lowbyte ' Freq low byte
PDC1H = Duty.HighByte ' PWM duty
PDC1L = Duty.LowByte
hserout ["D",dec duty,"F",dec Freq]
goto Main ' Loop
end

Like I said, I'm going to have to study my own work just to understand it better, but at least it works like it is suppose to. Yay! That was a few weeks of hair pulling!. Beat your head long enough against the wall, and sometimes you find a door.:smile:

Thanks
Bo

dmta34
- 6th June 2013, 15:10
Hi all,

Does some one by any chance have a C code on this QEI module?

Thanks !!!!!!!!!!!!

Archangel
- 7th June 2013, 08:32
This is NOT a " C " forum, it is M E Labs PBASIC.