|
|
View previous topic :: View next topic |
Author |
Message |
bimo
Joined: 29 Dec 2011 Posts: 6
|
Problem to control a PWM signal ! |
Posted: Thu Dec 29, 2011 2:40 pm |
|
|
Greetings !
It's my first message in this forum and hope it won't be the last.
Well I have a little problem and I guess I can't find a best place than in here to expose it .
Can someone give a look at this sample code and tells me if i missed something ?
Code: |
void main()
{
long duty=0;
SET_TRIS_C(0x00); // all C port pins set to outputs
SET_TRIS_B(0xFF); // all B port pins set to inputs
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1 , 249 , 1); // to generate a 20Khz signal
ouput_C(0x00);
while(1)
{
if(!input(PIN_B0)) //button "speed up"
{
duty++;
set_pwm1_duty(duty);
}
if(!input(PIN_B1) && duty > 0) // "slow down"
{
duty--;
set_pwm1_duty(duty);
}
}
}
|
This is a code to control a DC motor with a MOSFET and all stuffs.
All the electronics parts work just fine with a Function generator.
Now when I wanted to do it with a PWM signal coming from a PIC16F876A (C2 PIN) I got nothing...!
Well not exactly nothing.....at each restart I get a signal on the C2 PIN with a frequency of 20 KHz exactly but with random pulse width !!!
And when I made some delays between lines to execute my program lines slowly, I found that the signal is generated exactly when the line "setup_timer_2(T2_DIV_BY_1 , 249 , 1);" is executed !
Is this normal ?!
And another thing, my PIC is connected to two buttons on B0 and B1 pins
and when I pushed them over and over I got no change, the pulse width of the signal was still the same.
Did I miss something ?
I use a PIC16F876A with a 20MHz oscillator.
i use as compiler the CCS PCWH compiler
help please ! |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Dec 29, 2011 3:16 pm |
|
|
right away i see:
1- unless you are declaring #use fastio() - then the set_tris statements are at best redundant .
2- you OUGHT to declare a safe default set_pwm1(xx) value
AS soon as you setup the pwm generator
3- place a solid upper bound of less than 1024 on ++duty
4- got pullups or pulldowns on port B pins you are testing??
5-have you considered
(a) how FAST the duty cycle can change when button pressed as coded??
(b) Button debounce and delay ??
address all these things and you are going to be a lot better off |
|
|
bimo
Joined: 29 Dec 2011 Posts: 6
|
|
Posted: Thu Dec 29, 2011 3:35 pm |
|
|
thanks Asmboy for your answer
i was sure somebody would say that
well, know that i already cheked all theses theorys...otherwise even this code shoud make the signal to change :
while(1)
{
duty++;
set_pwm1_duty(duty);
delay_ms(100);
}
well ....nothing !
the signal don't change it's first random status..
as you can see no more readings on B port PINs and the problem continues, i even enabled the int_Timer2 and Global interrupts
..same thing !
i thought that my PIC could be damaged i changed it and the result was just the same
i forced a 0% duty cycle exactly after setting up the timer2
it's like if the "set_pwm1_duty(duty);" has no effect on the PIC but the "setup_timer_2" function does work, i changed the prescaler value and i got a new frequency and it was exact, but always with an uncontrolable random pulse with !
you know what i think....there is something wrong with this function "set_pwm1_duty(duty);" i can setup the timer but i can't control the pluse with could be something wrong with my compiler ?
i use an older version than the one on the CCS download section
version 3.2...is this one contains a bug or something....cause i found haundreds of examples for PWM and all of them use the same technique, there owners clames that it works fine for them, but why not for me ?
any ideas ?
thanks in advance |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Dec 29, 2011 4:03 pm |
|
|
do NOT enable the timer2 int - it is not involved here-
then try this snippet and forget about the buttons fro a moment:
Code: |
setup_timer_2( T2_DIV_BY_1, 255, 1 ); // 10 bit res 8 mhz clock
delay_ms(2); // was 5ms wait for PWM to stabilize
set_pwm1_duty(511); // 50% duty cycle
setup_ccp1(CCP_PWM);
|
and in main
Code: |
void main(void){
while(1){}
}
|
do you get a 50% duty cycle NOW or not ???
if you don't get a square wave NOW-
then try a slower crystal like 4 mhz and see what that produces |
|
|
bimo
Joined: 29 Dec 2011 Posts: 6
|
|
Posted: Thu Dec 29, 2011 4:36 pm |
|
|
I wrote exactly your snippet and nothing else.
Well...in the first start up i got a square signal of 19.53 KHz 50 % duty cycle.
But when i restarted my PIC again a got the same signal frequency but with a different duty cycle, i did it again and again and each time i got something different !
Certainly you're gonna say that I'm playing you...trust me !
I desoldered the 20 MHz crystal and it's capacitors and replaced it with a 16 MHz !
Guess what !....same thing !
Again with an 8 Mhz.....no change.
I can change the frequency but can't control the duty cycle !.... I even tested it with a PIC16F877A rather than the other PIC16F876A and i got absolutely the same result !
I really don't know what to do...tell me what is your compiler ?
This is driving me crazy ! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 29, 2011 6:08 pm |
|
|
Have you ever made the PIC do anything, such as blink an LED ?
Is PWM the first thing you have ever tried ? If so, blink an LED first.
Try this program:
Code: |
#include <16F876A.H>
#fuses HS, NOWDT, NOPROTECT, NOBROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
//=========================
void main()
{
// Blink an LED on pin B0. A 220 to 470 ohm series resistor is required.
while(1)
{
output_high(PIN_B0);
delay_ms(500);
output_low(PIN_B0);
delay_ms(500);
}
} |
If that works, then try this PWM program.
Code: |
#include <16F876A.h>
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=20000000)
//==========================
void main()
{
setup_timer_2(T2_DIV_BY_16, 255, 1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(128); // 50% duty cycle
while(1);
}
|
|
|
|
bimo
Joined: 29 Dec 2011 Posts: 6
|
|
Posted: Fri Dec 30, 2011 4:41 am |
|
|
Well suspected that too but know that my PIC works fine
and this is my first test with the PWM modules but not the PICs ever.
I did many mini projects with 16f84 / 16f876 / 16f877.
This time my project is a DC motor speed controller.
The best way is to generate a PWM signal at a certain frequency and play with duty cycle to change the motor speed.
First I wrote a function that generates a PWM but the minimum delay was 1 ms and it generated a signal, and by changing it's duty cycle i could change the motor speed.
BUT !!!!
The frequency of this signal was very small and i could here the noisy tones coming form my motor.
The frequency was approximately 2 to 3 KHz.
By optimizing more and more my code i managed to make it up to 7 KHz, but the tones was always audible and even worse !!!
So I posted my problem in a Forum and the told me to use directly the PWM modules with which i can generate frequencies up to 200KHz...
So I did, to not risk my MOSFET to burn up I'm connecting the C2 PIN directly to my Oscilloscope (cause you know a startup with a 100% duty cycle may damage my MOSFET and it did indeed!).
Anyways, I don't use LEDs but I'm using a beeper or a buzzer that informs me if my PIC is working fine or not
At start up it makes 3 beeps and starts to loop (while(1)) and waiting for buttons on B0 and B1 to be pushed, once done it makes a 100 ms beep and increment/decrement the duty cycle and so on.
Here is my complete code:
Code: |
#include<16F876A>
#use delay(clock=20000000)
#fuses NOWDT, HS, PUT, NOPROTECT, NODEBUG, NOBROUNOUT, NOLVP, NOCPD, NOWRT
void beep(int x)
{
int i,j;
for(j=0; j<x; j++)
for(i=0 ; i < 50 ; i++)
{
output_high(PIN_C1);
delay_ms(1);
output_low(PIN_C1);
delay_ms(1);
}
}
void main()
{
long duty=0;
SET_TRIS_A(0xFF); // what ever (not used)
SET_TRIS_B(0xFF); // all pins to inputs
SET_TRIS_C(0x00); // all pins to outputs
ouput_c(0x00); // initialise c port
setup_timer_2(T2_DIV_BY_1,249,1) // for a 20 KHz non audible tone frequency
delay_ms(2);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0); // initialise with 0% duty cycle
beep(3);
while(1)
{
if(!input(PIN_B0) && duty < 249)
{
duty++;
set_pwm1_duty(duty);
beep(1);
delay(100);
}
if(!input(PIN_B1) && duty > 0)
{
duty--;
set_pwm1_duty(duty);
beep(1);
delay_ms(100);
}
}
}
|
Did I miss somthing ?
Then I tried with this loop.
Code: |
while(1)
{
duty++;
set_pwm1_duty(duty);
beep(1);
delay_ms(200);
}
|
The result was the same.
Once the line "setup_ccp1(CCP_PWM);" is executed i got on my oscilloscope a
signal with the correct frequency but with a random duty cycle
some time I got 10%...0%....60%....100%...
and uncontrollable and I do hear beeps every 200 ms but the pulses period still the same !
I know that I'm not that stupid, but if someone in this case could convince me with the opposite I'll be glad :D
May day ....May day !!! |
|
|
bimo
Joined: 29 Dec 2011 Posts: 6
|
|
Posted: Fri Dec 30, 2011 10:03 am |
|
|
Here.... I took the snippet above and compile it and it produced this LST file:
Code: |
CCS PCM C Compiler, Version 3.200, 16465
Filename: C:\Users\PC\Desktop\test pic\test.LST
ROM used: 37 words (0%)
Largest free fragment is 2048
RAM used: 6 (3%) at main() level
6 (3%) worst case
Stack: 0 locations
*
0000: MOVLW 00
0001: MOVWF 0A
0002: GOTO 004
0003: NOP
.................... #include <16F876A.h>
.................... //////// Standard Header file for the PIC16F876A device ////////////////
.................... #device PIC16F876A
.................... #list
....................
.................... #fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
.................... #use delay(clock=20000000)
....................
.................... //==========================
.................... void main()
.................... {
0004: CLRF 04
0005: MOVLW 1F
0006: ANDWF 03,F
0007: BSF 03.5
0008: MOVF 1F,W
0009: ANDLW F0
000A: IORLW 0F
000B: MOVWF 1F
000C: MOVLW 07
000D: BCF 03.5
000E: MOVWF 1F
.................... setup_timer_2(T2_DIV_BY_16, 255, 1);
*
0011: MOVLW 00
0012: MOVWF 78
0013: IORLW 06
0014: MOVWF 12
0015: MOVLW FF
0016: BSF 03.5
0017: MOVWF 12
.................... setup_ccp1(CCP_PWM);
*
000F: MOVLW FF
0010: MOVWF 20
*
0018: BCF 03.5
0019: BCF 20.2
001A: MOVF 20,W
001B: BSF 03.5
001C: MOVWF 07
001D: BCF 03.5
001E: BCF 07.2
001F: MOVLW 0C
0020: MOVWF 17
.................... set_pwm1_duty(128); // 50% duty cycle
0021: MOVLW 80
0022: MOVWF 44
....................
.................... while(1);
0023: GOTO 023
.................... }
....................
0024: SLEEP
Configuration Fuses:
Word 1: 3F72 HS NOWDT PUT NODEBUG NOPROTECT BROWNOUT NOLVP NOCPD NOWRT |
I suspect the function set_pwm1_duty(); is not working properly cause it has no effect on my PIC.
Can an assembly expert verify this asm code for me? Please especially this:
Code: |
.................... set_pwm1_duty(128); // 50% duty cycle
0021: MOVLW 80
0022: MOVWF 44
|
Is it ok or there is something wrong with it ?
Thanks in advance ! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Fri Dec 30, 2011 10:27 am |
|
|
Now, the code you post, won't compile (missing ';' on the end of the timer setup line), so is not what you are actually using. Not a good start...
I took:
Code: |
#include<16F876A>
#use delay(clock=20000000)
#fuses NOWDT, HS, PUT, NOPROTECT, NODEBUG, NOBROUNOUT, NOLVP, NOCPD, NOWRT
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_2(T2_DIV_BY_1,249,1); // for a 20 KHz non audible tone frequency
delay_ms(2);
setup_ccp1(CCP_PWM);
set_pwm1_duty(128); // initialise with 50% duty cycle
while(TRUE);
}
|
Compiled it with 3.200, and the listing shows:
Code: |
.................... setup_ccp1(CCP_PWM);
0065: BCF 20.2
0066: MOVF 20,W
0067: BSF 03.5
0068: MOVWF 07
0069: BCF 03.5
006A: BCF 07.2
006B: MOVLW 0C
006C: MOVWF 17
.................... set_pwm1_duty(128); // initialise with 50% duty cycle
006D: MOVLW 80
006E: MOVWF 15
.................... while(TRUE);
006F: GOTO 06F
.................... }
....................
0070: SLEEP
|
Which is correct.
So it is not a compiler version issue. The one thing that could cause the anomalous behaviour is that the devices.dat file you have is corrupted (if you have the PCW version, perhaps somebody has used the chipedit tool incorrectly.
Seriously, re-install from the original files, or from a backup, and try again.
Why the sudden crop of 6+ year old compilers being used?.
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Dec 30, 2011 1:32 pm |
|
|
Quote: |
Why the sudden crop of 6+ year old compilers being used?.
|
unfortunately there are several "cracked" versions of 3.12 ,3.20 and even some 4.1x CCS compiler files circulating and in use by worldwide entities.
i hesitate to mention how to find them - but , most disgracefully,
they are out there....
while it is certainly ++odd , i guess it is possible that a brand new forum member might be using a very old , inherited version of CCS -
yet -- the ubiquitous presence of cracked - and potentially malfunctioning , compiler setups does give one pause for consideration. |
|
|
bimo
Joined: 29 Dec 2011 Posts: 6
|
|
Posted: Fri Dec 30, 2011 7:16 pm |
|
|
Before going to sleep i wanted to share this with you.
Finally i could make work, and you were right the problem came from my compiler i this it's buggy. Even after a reinstall the problem was the same so i change it to "PIC C Compiler CCS PCWHD 4 093" and with it and like magic all my problems disappeared and i managed to control my motor speed with PWM signal at 20 KHz frequency without any problem and all the noisy tones are gone !!
thanks every body and have a nice one |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Dec 31, 2011 8:33 am |
|
|
so -OK -here is a fun google search...
i think you can see what i was talking about here , except let me add- it is my fondest hope that the cracking process would cause the compiler to mal-function |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|