Variable software PWM 16F84(a)

General discussion on mikroC.
Post Reply
Author
Message
N_Tesla
Posts: 4
Joined: 07 Aug 2006 23:36

Variable software PWM 16F84(a)

#1 Post by N_Tesla » 07 Aug 2006 23:41

I would like to find some code on internet for variable software PWM regulation for 16F84(A).

For example i would use 2 buttons one for increasing and other for decrasing duty cycle.

Anybody hlp me? :?:

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#2 Post by xor » 08 Aug 2006 00:12

N. Tesla would never ask that question......he would have the anwer 50 years ahead..... :D :D
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

N_Tesla
Posts: 4
Joined: 07 Aug 2006 23:36

#3 Post by N_Tesla » 08 Aug 2006 11:56

Yes i know. Im yust testing your knowlage and as i can see nobody knows how. 8)

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#4 Post by xor » 08 Aug 2006 20:25

N_Tesla wrote:Im yust testing your knowlage and as i can see nobody knows how. 8)
Nobody :?: :shock: :?: I have written many many PWM programs in mikroBASIC which are posted in the forums. JPC has written much about it in the forums in mikroPASCAL. We both have PWM projects posted in mikroElektronika's Project Wepage.

But PWM is a big word and the PIC has its capabilities and its limits. You need to be more specific about your PWM request....such as what period are you after? What is the range of your duty-cycle?.....and so on.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

N_Tesla
Posts: 4
Joined: 07 Aug 2006 23:36

#5 Post by N_Tesla » 08 Aug 2006 23:01

Im a beginer so i would like to do that:

2 push buttons (one for up and one for down) one transistor conected to pic 16f84A an one DC motor controled by the PWM signals from pic microcontrolers wich are "driving" the transistor that is driving the DC motor.


So when i push one butn PWM signals (duty cycles) are longer and are incrising all the time the button is pressed up to full speed. And other button when its pressed the duty cycle lowers and so does the speed and power of DC motor.

I know this is wery simple but if u are a bigginer its hard.

I found on internet examples of PWM but in all the frequency is fix and the only way to change the duty cycle is to rewrite program and flash it again. I would like to use buttons and have a program for it.

So far i know how to produce PWM pulses and control I/O pins i know how to write a program that reads "button presed" but i dont know how to write the program that would combine button presed with increasing/decreasing duty cycle of PWM produced.

N_Tesla
Posts: 4
Joined: 07 Aug 2006 23:36

#6 Post by N_Tesla » 08 Aug 2006 23:05

But my knowlage is growing every day and im close but yust not there yet.

So i would apriciate some code from more expirience code writers on wich i could learn something new.

8)

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#7 Post by xor » 08 Aug 2006 23:54

These are in mikroBASIC but they may give you some ideas:

http://www.mikroe.com/forum/viewtopic.php?t=4994

This one also uses pushbuttons to change the duty cycle:
http://www.mikroe.com/forum/viewtopic.php?t=5667
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

anton
Posts: 807
Joined: 23 Sep 2004 09:16
Location: South-Africa
Contact:

#8 Post by anton » 09 Aug 2006 06:54

Hi N Tesla,

I wrote some code for software PWM using interrupts about a month ago for mikroPascal. You can easily convert it to mikroC

Here is the code:
This code is working on a PIC16F88 at 8MHz.

Code: Select all


//*****************************************************************************
// This program will enable you to use 4 software PWM channels on the PIC16
// The PWM frequency is about 400Hz using a 8 MHz crystal, but can go up to
// 1kHz with a 20MHz crystal.
// The PWM resolution is in 100 steps, from 1 to 100
//
// Anton Rieckert           anton.rieckert@gmail.com      www.riecktron.za.net
// mikroPascal v5.03
// 5 June 2006
//*****************************************************************************
program Software_PWM;
const
     ___PWM1  : byte = 0;          // Output pin for first channel
     ___PWM2  : byte = 1;          // Output pin for second channel
     ___PWM3  : byte = 2;          // Output pin for third channel
     ___PWM4  : byte = 3;          // Output pin for forth channel

var
   DutyCycle  : array[4] of byte;  // This is where each channel's duty cycle
                                   // is stored
   IntCycle   : byte;              // Variable for the interrupt

Procedure Interrupt;
Begin
     asm
        // PWM Channel 1
        BSF     STATUS, C
        MOVF    main_global_dutycycle, W
        SUBWF   main_global_intcycle, W

        BTFSS   STATUS, C
        BSF     PORTB, ___PWM1
        BTFSC   STATUS, C
        BCF     PORTB, ___PWM1

        // PWM Channel 2
        BSF     STATUS, C
        MOVF    main_global_dutycycle + 1, W
        SUBWF   main_global_intcycle, W

        BTFSS   STATUS, C
        BSF     PORTB, ___PWM2
        BTFSC   STATUS, C
        BCF     PORTB, ___PWM2

        // PWM Channel 3
        BSF     STATUS, C
        MOVF    main_global_dutycycle + 2, W
        SUBWF   main_global_intcycle, W

        BTFSS   STATUS, C
        BSF     PORTB, ___PWM3
        BTFSC   STATUS, C
        BCF     PORTB, ___PWM3

        // PWM Channel 4
        BSF     STATUS, C
        MOVF    main_global_dutycycle + 3, W
        SUBWF   main_global_intcycle, W

        BTFSS   STATUS, C
        BSF     PORTB, ___PWM4
        BTFSC   STATUS, C
        BCF     PORTB, ___PWM4

        // Inc the counter
        INCF    main_global_intcycle, F
        MOVF    main_global_intcycle, W
        SUBLW   100
        BTFSC   STATUS, Z
        CLRF    main_global_intcycle

        BCF     PIR1, TMR2IF
     end;
End;

Procedure Init;
Begin
     ADCON1 := 6;                   // Turn off the ADC
     CMCON := 7;                    // Turn off the comparators
     PORTB := 0;                    // Make PortB 0
     TRISB := 0;                    // Make PortB output

     // This is only for the P18F88, uncomment the next to lines if
     // you are using the P16F88!!!
     //OSCCON := $7E;
     //OSCTUNE := $1F;

     // Set the initial Duty Cycle
     IntCycle := 1;

     // Enable the TMR2 interrupt
     INTCON := $C0;           // enable TMR2 interrupt
     SetBit(PIE1, TMR2IE);
     SetBit(T2CON, TMR2ON);
     PR2 := 5;
End;

Begin
     Init;

     // Just an example, you can see the brightness of LEDs
     DutyCycle[0] := 1;        // Set the first duty cycle to 1%
     DutyCycle[1] := 25;       // Set the second duty cycle to 25%
     DutyCycle[2] := 50;       // Set the third duty cycle to 50%
     DutyCycle[3] := 80;       // Set the forth duty cycle to 80%
     
     Repeat Until 1 = 0;
End.
Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)

teicors
Posts: 6
Joined: 03 Jun 2010 09:18

Re: Variable software PWM 16F84(a)

#9 Post by teicors » 04 Oct 2010 22:56

Hi,
I don't if someone still read this post, but I have a trouble: I converted the anton small program for MikroPascal to MikroC, but if the program in Pascal works perfectly, I can't say the same stuff for the program in C.

Code: Select all


short __PWM1 = 0;          // Output pin for first channel
short __PWM2 = 1;          // Output pin for second channel
short __PWM3 = 2;          // Output pin for third channel
short __PWM4 = 3;          // Output pin for forth channel
short dutycycle[4];          // This is where each channel's duty cycle
                                    // is stored
short intcycle;                 // Variable for the interrupt

void interrupt() {
     asm {
        // PWM Channel 1
        BSF     STATUS, C;
        MOVF    _dutycycle, W ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C               ;
        BSF     PORTB, ___PWM1           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM1           ;

        // PWM Channel 2
        BSF     STATUS, C                ;
        MOVF    _dutycycle+1, W ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C                ;
        BSF     PORTB, ___PWM2           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM2           ;

        // PWM Channel 3
        BSF     STATUS, C                ;
        MOVF    _dutycycle+2 , W  ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C                ;
        BSF     PORTB, ___PWM3           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM3           ;

        // PWM Channel 4
        BSF     STATUS, C                ;
        MOVF    _dutycycle+3 , W  ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C                ;
        BSF     PORTB, ___PWM4           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM4           ;

        // Inc the counter
        INCF    _intcycle, F  ;
        MOVF    _intcycle, W  ;
        SUBLW   100                      ;
        BTFSC   STATUS, Z                ;
        CLRF    _intcycle     ;

        BCF     PIR1, TMR2IF             ;
     }
}

void Init() {

//     ADCON1 = 6;                   // Turn off the ADC
     CMCON = 7;                    // Turn off the comparators
     PORTB = 0;                    // Make PortB 0
     TRISB = 0;                    // Make PortB output

     // This is only for the P18F88, uncomment the next to lines if
     // you are using the P16F88!!!
     //OSCCON := $7E;
     //OSCTUNE := $1F;

     // Set the initial Duty Cycle
     IntCycle = 1;

     // Enable the TMR2 interrupt
     INTCON = 0xC0;           // enable TMR2 interrupt
     pie1.tmr2ie=1;
     t2con.TMR2ON=1;
     PR2 = 255;
}


void main() {     Init();     // Just an example, you can see the brightness of LEDs
     dutycycle[0] = 1;        // Set the first duty cycle to 1%
     dutycycle[1] = 25;       // Set the second duty cycle to 25%
     dutycycle[2] = 50;       // Set the third duty cycle to 50%
     dutycycle[3] = 80;       // Set the forth duty cycle to 80%
     do {} while (1);
}
where's my fault ??

Cheers
Angelo

madhunm
Posts: 35
Joined: 18 Feb 2005 23:24

Re: Variable software PWM 16F84(a)

#10 Post by madhunm » 03 Dec 2010 14:12

teicors wrote:Hi,
I don't if someone still read this post, but I have a trouble: I converted the anton small program for MikroPascal to MikroC, but if the program in Pascal works perfectly, I can't say the same stuff for the program in C.

Code: Select all

     // This is only for the P18F88, uncomment the next to lines if
     // you are using the P16F88!!!
     //OSCCON := $7E;
     //OSCTUNE := $1F;
where's my fault ??

Cheers
Angelo

Hi Angelo,

you have to uncomment the above lines if you are using a 16F88 and then change them to

Code: Select all

OSCCON = 0x7E;
OSCTUNE = 0x1F;

i tried it and it works.

thanks,
madhu

razvan8x
Posts: 2
Joined: 10 May 2011 20:57

Re: Variable software PWM 16F84(a)

#11 Post by razvan8x » 10 May 2011 21:03

How can i change this code to generate a PWM frequency more than 22kHz with a 25MHZ crystal?

Code: Select all

short __PWM1 = 0;          // Output pin for first channel
short __PWM2 = 1;          // Output pin for second channel
short __PWM3 = 2;          // Output pin for third channel
short __PWM4 = 3;          // Output pin for forth channel
short dutycycle[4];          // This is where each channel's duty cycle
                                    // is stored
short intcycle;                 // Variable for the interrupt

void interrupt() {
     asm {
        // PWM Channel 1
        BSF     STATUS, C;
        MOVF    _dutycycle, W ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C               ;
        BSF     PORTB, ___PWM1           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM1           ;

        // PWM Channel 2
        BSF     STATUS, C                ;
        MOVF    _dutycycle+1, W ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C                ;
        BSF     PORTB, ___PWM2           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM2           ;

        // PWM Channel 3
        BSF     STATUS, C                ;
        MOVF    _dutycycle+2 , W  ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C                ;
        BSF     PORTB, ___PWM3           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM3           ;

        // PWM Channel 4
        BSF     STATUS, C                ;
        MOVF    _dutycycle+3 , W  ;
        SUBWF   _intcycle, W  ;

        BTFSS   STATUS, C                ;
        BSF     PORTB, ___PWM4           ;
        BTFSC   STATUS, C                ;
        BCF     PORTB, ___PWM4           ;

        // Inc the counter
        INCF    _intcycle, F  ;
        MOVF    _intcycle, W  ;
        SUBLW   100                      ;
        BTFSC   STATUS, Z                ;
        CLRF    _intcycle     ;

        BCF     PIR1, TMR2IF             ;
     }
}

void Init() {

//     ADCON1 = 6;                   // Turn off the ADC
     CMCON = 7;                    // Turn off the comparators
     PORTB = 0;                    // Make PortB 0
     TRISB = 0;                    // Make PortB output

     // This is only for the P18F88, uncomment the next to lines if
     // you are using the P16F88!!!
     //OSCCON := $7E;
     //OSCTUNE := $1F;

     // Set the initial Duty Cycle
     IntCycle = 1;

     // Enable the TMR2 interrupt
     INTCON = 0xC0;           // enable TMR2 interrupt
     pie1.tmr2ie=1;
     t2con.TMR2ON=1;
     PR2 = 255;
}


void main() {     Init();     // Just an example, you can see the brightness of LEDs
     dutycycle[0] = 1;        // Set the first duty cycle to 1%
     dutycycle[1] = 25;       // Set the second duty cycle to 25%
     dutycycle[2] = 50;       // Set the third duty cycle to 50%
     dutycycle[3] = 80;       // Set the forth duty cycle to 80%
     do {} while (1);
}

Thank you!

Post Reply

Return to “mikroC General”