Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PWM problems........Urgent

Status
Not open for further replies.

aniketrane

New Member
Hi guys,
I am working on PIC18F452. I am having problem generating PWM with it. I am using Mplab 6.3 along with MPLAB-C18. I also tried to work on assembly code. It has been derived from the tutorial by Nigel Goodwin at
I have tried everything as the tutorial says but still I cant get the PWM output. I am using a DSO to observe the waveforms. My PIC board runs at 4MHz as in contrast to Nigel’s 20 MHz demo, but I think that I should get some output at different frequency.
Where I may be going wrong? Do I need to connect any Resistor or capacitor at PWM output pin to observe waveform ( I am directly connecting DSO probe to it.)?
Please reply urgent as possible.

Code:
include "P18F452.inc"
LIST P=18F452

org 0x00
goto start
start:
    	MOVLW    0x06
    	MOVWF    ADCON1

    	MOVLW    0		;set PORTC as all outputs
    	MOVWF    TRISC


	MOVF     CCP1CON,W	;set CCP1 as PWM
    	ANDLW    0xF0
    	IORLW    0x0C
    	MOVWF    CCP1CON


    	MOVLW    126		;set highest PWM value
    	BANKSEL  PR2		;over this (127) is permanently on
    	MOVWF    PR2

    	MOVF     T2CON,W	;set prescaler to 16
    	ANDLW    0xF8		;PWM at 2500HZ
    	IORLW    0x02
    	MOVWF    T2CON

    	MOVF     T2CON,W	;set postscaler to 1
    	ANDLW    0x07
    	IORLW    0x00
    	MOVWF    T2CON
    	
    	CLRF	CCPR1L		;set PWM to zero


    	BSF      T2CON, TMR2ON	;and start the timer running
end


Below is the Code for MPLAB-C18


Code:
#include <p18F452.h>
#include<delays.h>
#include<timers.h>
#include<pwm.h>

void main()
{
ClrWdt();
TRISC=0x00;
TRISB=0x00;
PORTC=0x00;
While(1)
{
PORTB=0x80;
OpenTimer2(TIMER_INT_OFF & T2_PS_1_16& T2_POST_1_1 );
OpenPWM1(0xF8);
SetDCPWM1(126);
}
ClosePWM1();
CloseTimer2();
}
 
There is also no 'end' on your program
after 'BSF T2CON, TMR2ON' your program just stops, wich means the program will continue to run until the end of program memory and then roll over back to start...

you should add an infinite loop at the end to stop it there
GOTO $
 
Exo said:
There is also no 'end' on your program
after 'BSF T2CON, TMR2ON' your program just stops, wich means the program will continue to run until the end of program memory and then roll over back to start...

you should add an infinite loop at the end to stop it there
GOTO $

Yes, it's only a part of my tutorial, the main part of the full program runs in a loop which varies the PWM with time delays inbetween, to demonstrate how to use the two PWM channels to control a small robot vehicle.
 
Ah, Nigel, I know that you don't use C for PIC, but I would like to ask this for pwm mode:

As using CCS C, I only have the function

set_pwm_duty ();

which is used to set pwm duty. But I don't know if it wait until the end of pwm period to change the duty or not. Because, as writing in ASM, once I need to change the duty, I have to wait until the flag of pwm HIGH.

So, if I use set_pwm_duty function, I don't know if it do so or not. So is there any problem if we don't wait the flag and change the duty? will it make a wrong duty?

I'm thinking of it that if we change the duty, that is the CCP1RL (for example) will get new value. If the new value is larger than the old, everything seems to be oki. But if the new duty smaller than the old, and the timer2 did run through the new duty value. So what happens?

Thanks muchie.
 
falleafd said:
Ah, Nigel, I know that you don't use C for PIC, but I would like to ask this for pwm mode:

As using CCS C, I only have the function

set_pwm_duty ();

which is used to set pwm duty. But I don't know if it wait until the end of pwm period to change the duty or not. Because, as writing in ASM, once I need to change the duty, I have to wait until the flag of pwm HIGH.

So, if I use set_pwm_duty function, I don't know if it do so or not. So is there any problem if we don't wait the flag and change the duty? will it make a wrong duty?

As far as I'm aware (without checking the datasheet) there's no need to wait for anything before changing the PWM duty cycle. The value you write goes to a buffer register, the hardware then reloads from this buffer register the next time it times out.

I'm thinking of it that if we change the duty, that is the CCP1RL (for example) will get new value. If the new value is larger than the old, everything seems to be oki. But if the new duty smaller than the old, and the timer2 did run through the new duty value. So what happens?

As you already know, I don't do C 8)

I suggest you try looking at the code that the C compiler produces and see what it's doing.
 
Yes, the C code only need call set_pwm_duty() function.

The problem is that I use L298 to control my motor. It's no problem with ASM but I'm trying in C.

As I want to change the direction I use:

set_pwm2_duty(0); // CCP2 = 0
set_pwm1_duty (duty);// CCP1 = duty

then change

set_pwm1_duty(0);
set_pwm2_duty(duty);

In ASM as we stop CCP2, that is CCP2 = LOW, we just clear CCPR2L.
and we wait to next period to set CCP1. No bang here. Because if CCP1 and CCP2 are both HIGH at a time, bang bang bang boom boom boom :))

So I'm afraid if we need to wait for it or not? as updating value for CCPRxL will it change immediately or wait until the next period???

That is my problem.
 
falleafd said:
Yes, the C code only need call set_pwm_duty() function.

The problem is that I use L298 to control my motor. It's no problem with ASM but I'm trying in C.

As I want to change the direction I use:

set_pwm2_duty(0); // CCP2 = 0
set_pwm1_duty (duty);// CCP1 = duty

then change

set_pwm1_duty(0);
set_pwm2_duty(duty);

In ASM as we stop CCP2, that is CCP2 = LOW, we just clear CCPR2L.
and we wait to next period to set CCP1. No bang here. Because if CCP1 and CCP2 are both HIGH at a time, bang bang bang boom boom boom :))

So I'm afraid if we need to wait for it or not? as updating value for CCPRxL will it change immediately or wait until the next period???

As I mentioned before, check what code the C compiler actually produces, but changes to the PWM registers occur at the next load into the actually working PWM registers.

From what I can gather you're using both PWM channels to feed a single motor?, the code in my tutorial (which was designed for a small robot) uses each PWM output to feed a single motor (left and right). Reversing direction is done by an extra pin switching high or low, which reverses the motor in hardware - either using a DPDT relay or an H Bridge.
 
Yes,Iknow how to use hardware for reversed direction. However, because I want to build a packaged module for motor control using 16f876a. And you see we will waste one pin of CCP and lost amount of money for ext hardware.

That is I don't want to.

To control PID for a motor with 16F876, we only need encoder inputs, and current limit input. And two pins to control the motor.

Well, I've tested my program and it worked very good. I think no problem with C code. As finished this project, I'll post it here.

Thanks muchie Nigel.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top