Archive: Programing PIC16f873 for PWM

Status
Not open for further replies.

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 8 2006, 05:40 AM
i have attached the circuit diagram please take a look and tell me if on the right track
[post=14769]Quoted post[/post]​
There are three things I'd like to suggest.
1) Check the datasheet carefully to see if pin 4(Vref -) can be left open. It might need to be connected to something.
2) Pin 8 is a second Vss pin and it should be connected to GND
3) It is generally a good idea to place a capacitor, with a value between .1 uF and 1 uF across pins 19 and 20. This is called a decoupling capacitor and it has two purposes. It is a path to GND for high frequency AC noise from the power supply and it provides some energy storage to prevent Vdd drop when the device is switching. You're not doing much output switching so this may not be critcal for a breadboard.
 

Thread Starter

damochi

Joined Feb 17, 2006
40
Originally posted by Papabravo@Mar 8 2006, 02:11 PM
There are three things I'd like to suggest.
1) Check the datasheet carefully to see if pin 4(Vref -) can be left open. It might need to be connected to something.
2) Pin 8 is a second Vss pin and it should be connected to GND
3) It is generally a good idea to place a capacitor, with a value between .1 uF and 1 uF across pins 19 and 20. This is called a decoupling capacitor and it has two purposes. It is a path to GND for high frequency AC noise from the power supply and it provides some energy storage to prevent Vdd drop when the device is switching. You're not doing much output switching so this may not be critcal for a breadboard.
[post=14777]Quoted post[/post]​
but pin 19 is Vss and i'm going to connect it to ground and i think Pin 20 Vdd is meant to go to 5V. but i'll try and stick the capacitor in between them but i dunno where to connect Pin 4 because it says Vref- and i havn't got a negative voltage i'm confused and also i read 8.3.3 and i don't understand how to do it at all. i never took MPLAB i dunno how to write
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 8 2006, 03:06 PM
but pin 19 is Vss and i'm going to connect it to ground and i think Pin 20 Vdd is meant to go to 5V. but i'll try and stick the capacitor in between them but i dunno where to connect Pin 4 because it says Vref- and i havn't got a negative voltage i'm confused and also i read 8.3.3 and i don't understand how to do it at all. i never took MPLAB i dunno how to write
[post=14785]Quoted post[/post]​
You are correct. I still want you to connect pin 19 to ground and pin 20 to Vdd, just add the capacitor across those two pins.

For Vref(-), the picture on page 113 shows that you can leave the pin open, but you must select a configuration that connects Vref(-) to Vss instead of to the external pin.

Page 112 shows the values of configuration bits you need to write to register ADCON1. Your homework is to tell me what eight bit hexadecimal value you need to write to registe ADCON1.

If you cannot understand paragraph 8.3.3 you need to get some local face to face help because I can't convey the things you need to understand in this forum. I will try to answer questions, and I will try to lead you in the right direction but I will not do the work for you. You must buckle down in a quiet place and you must read and you must try things and YOU MUST FAIL at some of the things you try because that is the only way that you can learn. So lets get past the fear of failure, go grab your free MPLAB program and TRY SOMETHING.

Let me remphasize this point. Even if I did your project for you it probably would not work the first time around. As good as I am at this, I have seldom if ever in 45 years written a program that worked the first time. You would be just as stuck.

Let's examine section 8.3.3 It says

1. Set the PWM period by writing to the PR2 register. What should we write?
We should write hexadecimal FF. That is the value from our modified table 8-3 that gives us the period for a frequency of 976 Hz. Second Homework Question-- What is the period of a square wave with a frequency of 976 Hz.?
Rich (BB code):
   MOVLW  H'FF'
   BSF   STATUS,5   ; Set RP0 in STATUS(0x03) to address bank 1
   MOVWF  PR2
   BCF   STATUS,5   ; Clear RP0 in STATUS(0x03) to address bank 0
2. Set the PWM duty cycle by writing to the CCPR1L and CCP1CON<5:4> bits
I choose to write the ten bit value corresponding to half scale or 0x200. Says me, this should produce a square wave with a 50% duty cycle
Rich (BB code):
   MOVLW  H'80'
   MOVWF  CCPR1L    ; move high order bits to CCPR1L in bank 0

   MOVLW  H'CF'    ; put zeros in W<5:4>
   ANDWF  CCP1CON,1  ; W & CCP1CON -> CCP1CON in bank 0
I'm not 100% sure about the syntax for the ANDWF instruction. Different assemblers have different rules on on what happens if the second operand of the instruction is 0 or 1 or W or blank.

3. Make the CCP1 pin an output by clearing the TRISC<2> bit.
Your third and last homework for this session is to write one or more instructions to do this simple task.

Good Luck
 

Thread Starter

damochi

Joined Feb 17, 2006
40
The answer to question 1 should be 9Fh and the answer for number 2 would be 1/F = 1/976 = 1.025*10^-3
i'm still try to figure out the last question
 

Thread Starter

damochi

Joined Feb 17, 2006
40
Originally posted by damochi@Mar 9 2006, 02:15 AM
do i need to compile the two sets of codes together
[post=14796]Quoted post[/post]​
just one question is it possible to use 1000hz instead of 976Hz
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 8 2006, 10:34 PM
just one question is it possible to use 1000hz instead of 976Hz
[post=14797]Quoted post[/post]​
No it is not possible to change the frequency of the PWM arbitrarily. The 976 Hz. is a function of the input frequency (4MHz.), the prescaler we have chosen (4) and the value in the Timer 2 Period Register(PR2). If you want to have the PWM output frequency be 1000 Hz. then something else must change. You could raise the crystal frequency from 4 MHz. to 4.096 Mhz. and with PR2=0xFF and Timer 2 Prescaler = 4 you would get 1000 Hz. There is no real reason to do this however.
You can compute the PWM frequency with the following equation if you like

Rich (BB code):
PWM_frequency = OSC_frequency/4/(PR2+1)/Timer2_prescaler
4e+06 / 4 / 256 / 4 = 976.5625 Hz. or
4.096e+06 / 4/ 256 / 4 = 1000.0 Hz.
If you start lowering the value of PR2 to get closer to 1000 Hz. then the resolution of the PWM will not match the resolution of the A/D converter. We should try to walk before we try to run.

The two fragments of programming are a small part of what you will need to create a program that will run successfully. When you are done the program structure will look something like this
Rich (BB code):
address 0 ---> goto INIT ; First instruction executed when RESET is complete
...
address xx --->INIT:
            Initialize registers for port pins
            Initialize and configure A/D Converter
            Initialize and configure PWM
            Initialize register file variables
...
...
address yy ----> MAIN_LOOP:
            Start an A/D conversion
            While(A/D converter is busy) do nothing
            Read 10 bit A/D result
            Copy A/D result into PWM duty cycle register
            For 10 milliseconds -- do nothing
            goto MAIN_LOOP
I expect you will have many questions about this program layout but it is the simplest overall design I can think of with a chance of success. I am guessing that you will need on the order of 70-100 instructions to do this simple process. You may be clever and surprise me with program that takes less than 70 instructions.

On the homework questions
1) I don't think that configuration 9F will work very well for your purposes. If you go back and review my earlier posts I said you should configure the A/D result to be LEFT-justified. This means the most significant 8 bits will be in the result high register, and the least significant 2 bits will be in the high order bits of the result low register. This format closely matches the format of the PWM duty cycle register. It is not exact, the two LSBs need to be shifted two places to the right before you can write them to the right place CCP1CON.

Since pin Vref(-) is left OPEN on your current sketch I would suggest tha you consider a configuration value that places Vref(-) at Vss. the correct answer will be in the range 00 to 0E that you will write to ADCON1

2) 1.025 milliseconds is the period corresponding to 976 Hz.

3) You still need to figure out what to do with TRISC<2>

Good Luck
 

Thread Starter

damochi

Joined Feb 17, 2006
40
ok let me get this straihgt we trying to get A 976 Hz square wave with a 50% duty cycle coming out of RC2 i.e Pin 13 right?

if that is so i just need to consult some text books i'll be back with the answers
 

Thread Starter

damochi

Joined Feb 17, 2006
40
after doing a lot of reading i came up with these

1. Set the PWM period (976Hz = 1.025ms) by writing to the PR2 register.

PWM Period = [PR2 + 1]*4*Tosc*TMR2 PreScale value
Use 4 for TMR2 prescale.
Tosc = 1/4000000 = 2.5*10-7
Rearranging the equation gives...
PR2 = (Period/ (4 * Tosc * TMR2 Prescale)) - 1
Therefore...
PR2 = (1.025ms/ (4 * 2.5 * 10-7 * 4)) - 1 = 255.25

Rich (BB code):
  bsf STATUS,RP0
  movlw d'255'  ; when TMR2 = 255 = end of Period
  movwf PR2
  bcf STATUS,RP0
2. Set the PWM Duty Cycle by writing to the CCPR1L register and CCP1CON<5:4> bits.
CCPR1L contains the upper 8 bits of the 10 bit Duty Cycle value CCP1CON<5:4> contain the lower 2 bits
PWM Duty Cycle = (CCPR1L:CCP1CON<5:4>)*Tosc*TMR2 Prescale Value

CCPR1L:CCP1Con<5:4> = PWM Duty Cycle / (Tosc * TMR2 Prescale)

PWM Duty Cycle = 50% of Period

PWM Duty Cycle = 50% of 0.001 = 0.0005

CCPR1L:CCP1Con<5:4> = 5.124^-04 / (2.5 * 10-7 * 4)

CCPR1L:CCP1Con<5:4> = 512.5

512.5 in 10 bit binary = 1000000000

CCPR1L = 10000000 CCP1Con<5:4> = 00
Write the 10 bit value

Rich (BB code):
  movlw b'10000000' ; set bits 9 - 2
  movwf CCPR1L
  bcf CCP1CON,CCP1X ; set bit 1
  bcf CCP1CON,CCP1Y ; set bit 0



3. Make the CCP1 pin an output by clearing the TRISC<2> bit

Rich (BB code):
    bsf STATUS,RP0
    movlw b'10000000'
    andwf TRISC
    bcf STATUS,RP0



4. Set the TMR2 prescale value and enable TMR2 by writing to T2CON.
We decided previously to set the prescale value to 4.
TMR2 prescale are bits 1 and 0 in T2CON
TMR2 enable is bit 2

Rich (BB code):
  movlw b'00000101' ; TMR2 = on, prescale = 1:4
  movwf T2CON
5.Configure the CCP1 module for PWM

Rich (BB code):
  movf CCP1CON,W
  andlw b'00110000' ; mask all but previously set Duty Cycle bits
  iorlw b'00001111' ; and enable PWM mode
  movwf CCP1CON
 

Thread Starter

damochi

Joined Feb 17, 2006
40
i was on our student central and my lecturer posted this on the website

'Digital' Voltmeter Module (GJA)



Info and 'Data' on Position Servo
Futaba S3003 Servo 'data' (77.648 Kb)

Here is some information on then type of position servo we will be using for the EMAP projects.
We will be supplying you with the Futaba S3003 general purpose servo, which is typical of the breed.
I use the term 'data' loosely, because it has proved impossible to get precise specifications on the exact timing of PWM requirements for this servo (or any other), and so it will be necessary for you to carry out some pragmatic 'characterisation' of the S3003 once you have supplied it with the basic requirements. The information supplied in this document should will allow you to get into the right ball-park! The Futaba web site confirms that the numerical data relating to bearings, speed, torque, weight, etc is correct (for the S3003), but these are non-critical for this application. Doh!
All sources are agreed on TWO things, the repetition rate of the signal should be 50Hz (i.e. 20 ms period) and the pulse width for centre position is 1.5 ms!
If you want to know more, type "RC Servo" into Google and have a nose around.

i am confused
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 9 2006, 03:00 PM
after doing a lot of reading i came up with these

1. Set the PWM period (976Hz = 1.025ms) by writing to the PR2 register.

PWM Period = [PR2 + 1]*4*Tosc*TMR2 PreScale value
Use 4 for TMR2 prescale.
Tosc = 1/4000000 = 2.5*10-7
Rearranging the equation gives...
PR2 = (Period/ (4 * Tosc * TMR2 Prescale)) - 1
Therefore...
PR2 = (1.025ms/ (4 * 2.5 * 10-7 * 4)) - 1 = 255.25

Rich (BB code):
   bsf STATUS,RP0
   movlw d'255'  ; when TMR2 = 255 = end of Period
   movwf PR2
   bcf STATUS,RP0
2. Set the PWM Duty Cycle by writing to the CCPR1L register and CCP1CON<5:4> bits.
CCPR1L contains the upper 8 bits of the 10 bit Duty Cycle value CCP1CON<5:4> contain the lower 2 bits
PWM Duty Cycle = (CCPR1L:CCP1CON<5:4>)*Tosc*TMR2 Prescale Value

CCPR1L:CCP1Con<5:4> = PWM Duty Cycle / (Tosc * TMR2 Prescale)

PWM Duty Cycle = 50% of Period

PWM Duty Cycle = 50% of 0.001 = 0.0005

CCPR1L:CCP1Con<5:4> = 5.124^-04 / (2.5 * 10-7 * 4)

CCPR1L:CCP1Con<5:4> = 512.5

512.5 in 10 bit binary = 1000000000

CCPR1L = 10000000 CCP1Con<5:4> = 00
Write the 10 bit value

Rich (BB code):
   movlw b'10000000'; set bits 9 - 2
   movwf CCPR1L
   bcf CCP1CON,CCP1X; set bit 1
   bcf CCP1CON,CCP1Y; set bit 0
3. Make the CCP1 pin an output by clearing the TRISC<2> bit

Rich (BB code):
       bsf STATUS,RP0
       movlw b'10000000'
       andwf TRISC
       bcf STATUS,RP0



4. Set the TMR2 prescale value and enable TMR2 by writing to T2CON.
We decided previously to set the prescale value to 4.
TMR2 prescale are bits 1 and 0 in T2CON
TMR2 enable is bit 2

Rich (BB code):
   movlw b'00000101'  ; TMR2 = on, prescale = 1:4
   movwf T2CON
5.Configure the CCP1 module for PWM

Rich (BB code):
    movf  CCP1CON,W
    andlw b'00110000'; mask all but previously set Duty Cycle bits
    iorlw  b'00001111'; and enable PWM mode
    movwf CCP1CON
[post=14822]Quoted post[/post]​
Wow -- see what happens when you exert a little bit of effort. I'm impressed.
1. The code for question 1 looks fine
2. The code looks good but the comments are wrong. I think the following would be correct:
Rich (BB code):
  movlw b'10000000'; set bits 9 - 2 - to b'10000000'
  movwf CCPR1L
  bcf CCP1CON,CCP1X; clear bit 1
  bcf CCP1CON,CCP1Y; clear bit 0
CCP1X and CCP1Y shoud evaluate to 5 and 4 respectively
3. Your code sequence will clear all the bits 6..0 in the TRISC register and preserve bit 7. If that is OK then the sequence will work because it certainly clears bit 2.
4. This code looks good for selecting the prescaler and turning on the timer.
5. This code looks good for preserving the least significant bits and setting the PWM mode.

I'd say you passed with flying colors.
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 9 2006, 04:08 PM

All sources are agreed on TWO things, the repetition rate of the signal should be 50Hz (i.e. 20 ms period) and the pulse width for centre position is 1.5 ms!
If you want to know more, type "RC Servo" into Google and have a nose around.

i am confused
[post=14823]Quoted post[/post]​
You now know how to generate a PWM signal which can vary from 0% to 100% without having precise control of the frequency.

This application is a bit slower in that the frequency is 50Hz (Period = 20 milliseconds) and the frequency control needs to be precise. A servo motor is a motor that you can command to go to, and hold a certain position. Servo motors were instrumental in the development of flight controls on early aircraft. We are not interested in having the motor run continuously, and we are not interested in having it rotate at a certain velocity.
It knows what position is being commanded by the width of the high going pulse.

We know that if we create a train of pulses with a high time of 1.5 milliseconds and a low time 18.5 milliseconds that the motor will interpret this as a command to go to the middle of its travel and stay there. If the pulse train continues forever then the motor will hold that position.

If we shorten the pulse a little bit to say 1.48 milliseconds high and 18.52 milliseconds low the the motor shaft should rotate a little bit in one direction. If we now lengthen the pulse to 1.52/18.48 then the motor should rotate in the opposite direction through the mid point to about the same place on the opposite side.

To characterize the motor we want to find out how short we can make the pulse before the servo motor runs into a mechanical stop. Then we want to find out how long we can make the pulse before it runs into a mechanical stop.

Hope this helps
Good Luck
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 10 2006, 04:32 AM
but i have a big problem still i dunno how to compile the codes i've got now on MPLAB
[post=14833]Quoted post[/post]​
In MPLAB there should be the concept of creating a project.
In the project you tell MPLAB what kind of processor you have, where your files are and so forth. Once MPLAB has this information it can build your project. There should be a single button to activate this process. Later if you make a change to your files you just hit the button again and the rebuild happens as a result.

Read the help files and the documentation that came with MPLAB

Good Luck
 

Thread Starter

damochi

Joined Feb 17, 2006
40
i have try to compile the code in this form at but it's given me build error but i dunno what i'm doing wrong

Rich (BB code):
#include <P16f873.inc>
;Set the PWM period (976Hz = 1.025ms) by writing to the PR2 register

 bsf    STATUS,RP0
 movlw  d'255'   ; when TMR2 = 255 = end of Period
 movwf  PR2
 bcf    STATUS,RP0,

=================================================================
;Set the PWM Duty Cycle by writing to the CCPR1L register and CCP1CON<5:4> bits. 

 movlw b'10000000'; set bits 9 - 2 - to b'10000000'
 movwf CCPR1L
 bcf    CCP1CON,CCP1X; clear bit 1
 bcf    CCP1CON,CCP1Y; clear bit 0

==================================================================
;Make the CCP1 pin an output by clearing the TRISC<2> bit 
   
 bsf    STATUS,RP0
 movlw  b'10000000'
 andwf  TRISC
 bcf    STATUS,RP0
==================================================================
;Set the TMR2 prescale value and enable TMR2 by writing to T2CON.

 movlw b'00000101' ; TMR2 = on, prescale = 1:4
 movwf T2CON

==================================================================
;Configure the CCP1 module for PWM 
 movf  CCP1CON,W
 andlw b'00110000'; mask all but previously set Duty Cycle bits
 iorlw  b'00001111'; and enable PWM mode
 movwf CCP1CON
END
 

Thread Starter

damochi

Joined Feb 17, 2006
40
i have tried compiling it again but this time i omitted the equal signs i used for separting the codes and it gave me this report

Clean: Deleting intermediary and output files.
Clean: Done.
Executing: "C:\Program Files\Microchip\MPASM Suite\MPAsmWin.exe" /q /p16F873 "damochi.asm" /l"damochi.lst" /e"damochi.err"
Message[302] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 6 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[305] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 21 : Using default destination of 1 (file).
Message[302] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 21 : Register in operand not in bank 0. Ensure that bank bits are correct.
Warning[205] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 36 : Found directive in column 1. (END)
Loaded G:\Embbeded microcontollers\PIC\damochi.COD.
BUILD SUCCEEDED: Fri Mar 10 15:57:49 2006

so is that alright
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 10 2006, 12:33 PM
i have tried compiling it again but this time i omitted the equal signs i used for separting the codes and it gave me this report

Clean: Deleting intermediary and output files.
Clean: Done.
Executing: "C:\Program Files\Microchip\MPASM Suite\MPAsmWin.exe" /q /p16F873 "damochi.asm" /l"damochi.lst" /e"damochi.err"
Message[302] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 6 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Message[305] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 21 : Using default destination of 1 (file).
Message[302] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 21 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Warning[205] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 36 : Found directive in column 1. (END)
Loaded G:\Embbeded microcontollers\PIC\damochi.COD.
BUILD SUCCEEDED: Fri Mar 10 15:57:49 2006

so is that alright
[post=14846]Quoted post[/post]​
If you read the information on the assembler carefully you will notice that the semi-colon is used to tell it that the remainder of the line is a COMMENT. When you tell it something is a comment it will not look for PIC instructions and operands.

If you go to the assembler documentation each of the messages should be explained in more detail. I'll help with the first one but you need to figure out the rest.

Message[302] G:\EMBBEDED MICROCONTOLLERS\PIC\DAMOCHI.ASM 6 : Register in operand not in bank 0. Ensure that bank bits are correct.

"302" is the message number. This message is not a fatal error it is merely a warning. The string "G:\.....DAMOCHI.ASM" is the name of the file it is working on. See the little number '6'? You do -- great. That is the line number where the error occurred. The warning is saying that register PR2 is in register bank 1 and you need to make sure that the register bank bits are set correctly. The bsf/bcf instructions are taking care of this little detail. At some future time you may turn these warnings off but I would leave them on for now.

Don't forget to put a goto instruction at the bottom of you program so it will execute repeatedly. You dont want to go to all this work and have the program execute one time only before going off into the weeds.

You need to figure out what the rest of the warnings are talking about. Then you need to single step through the program using the simulator in MPLAB so you understand precisely what each instruction does.

In the assembler documentation there should be a section on instructions to the assembler that do not generate PIC instructions. There is one called "ORG" that you should find out about.

Good Luck
 

Thread Starter

damochi

Joined Feb 17, 2006
40
hey thanks for the explanation but i tried figuring it out but i still can't find out what the problem is .can yu please help me with these i'm running out of time
 

Papabravo

Joined Feb 24, 2006
21,228
Originally posted by damochi@Mar 10 2006, 08:42 PM
hey thanks for the explanation but i tried figuring it out but i still can't find out what the problem is .can yu please help me with these i'm running out of time
[post=14854]Quoted post[/post]​
Line 21 has two problems. You did not specify where the result was supposed to go. The choices are the W register or the file register. By default it chooses the file register. This choice is also represented by the value 1. The other warning is the same as the one for line 6. The file register you specified is in bank 1.

The last warning indicates that the END statement should not start in column 1

It's too bad about time running out, I hope you make it.
 
Status
Not open for further replies.
Top