+ Post New Thread
Results 1 to 10 of 10
  1. #1
    Advanced Member level 5
    Points: 30,455, Level: 42
    Achievements:
    7 years registered

    Join Date
    Sep 2008
    Location
    cambridge
    Posts
    6,367
    Helped
    467 / 467
    Points
    30,455
    Level
    42

    Need two PWMs from PIC16F18856 microcontroller

    Hi,
    We are using PIC16F18856.
    We need to set a fixed PWM of 30% duty at approx. 500Hz on RA2. We also need a variable PWM on RA1. (frequency anywhere between 2kHz and 300Hz, but again it will be a fixed frequency)
    Do you think its possible to do this?
    PIC16F18856 datasheet
    http://ww1.microchip.com/downloads/e...-40001824D.pdf

    •   AltAdvertisment

        
       

  2. #2
    Advanced Member level 5
    Points: 22,107, Level: 36
    barry's Avatar
    Join Date
    Mar 2005
    Location
    California, USA
    Posts
    4,230
    Helped
    936 / 936
    Points
    22,107
    Level
    36

    Re: Need two PWMs from PIC16F18856 microcontroller

    Huh? A 'fixed PWM OF 30 % duty at 500 Hz' is not PWM. That's a pulse train. Of course this is possible. And, you do realize that this uP has a built-in PWM, right?


    1 members found this post helpful.

  3. #3
    Newbie level 2
    Points: 34, Level: 1

    Join Date
    Nov 2018
    Posts
    3
    Helped
    0 / 0
    Points
    34
    Level
    1

    Re: Need two PWMs from PIC16F18856 microcontroller

    PWM Modulator Using Op-Amp (MAX492). The content is very simple, very helpful. Components in this article can help you understand better understanding of this article. For example, in this article, you can go to find and buy these components: MAX492.



    •   AltAdvertisment

        
       

  4. #4
    Super Moderator
    Points: 249,046, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,337
    Helped
    13176 / 13176
    Points
    249,046
    Level
    100

    Re: Need two PWMs from PIC16F18856 microcontroller

    Depending on the processor clock, it may be not possible to generate the intended low PWM frequencies directly with 8-bit PIC. It should be always possible with some software support.


    1 members found this post helpful.

    •   AltAdvertisment

        
       

  5. #5
    Advanced Member level 1
    Points: 4,156, Level: 15
    Achievements:
    7 years registered
    hexreader's Avatar
    Join Date
    Apr 2011
    Location
    England
    Posts
    477
    Helped
    184 / 184
    Points
    4,156
    Level
    15

    Re: Need two PWMs from PIC16F18856 microcontroller

    I agree with FvM. Software PWM should be no problem, but direct PWM to those two pins may or may not be practical. You have picked a modern PIC, so the chances are higher.

    If I get time, I will write some code for the job.



  6. #6
    Advanced Member level 1
    Points: 4,156, Level: 15
    Achievements:
    7 years registered
    hexreader's Avatar
    Join Date
    Apr 2011
    Location
    England
    Posts
    477
    Helped
    184 / 184
    Points
    4,156
    Level
    15

    Re: Need two PWMs from PIC16F18856 microcontroller

    Not having much luck so far :(

    Seems to be a tougher task than I imagined. Code Configurator tool (MCC) seems to suggest that PWM6 and PWM7 can output what you want to ports A1 and A2, but I have not succeeded in making it work. Might need someone cleverer than me to work it all out.



  7. #7
    Advanced Member level 1
    Points: 4,156, Level: 15
    Achievements:
    7 years registered
    hexreader's Avatar
    Join Date
    Apr 2011
    Location
    England
    Posts
    477
    Helped
    184 / 184
    Points
    4,156
    Level
    15

    Re: Need two PWMs from PIC16F18856 microcontroller

    I now discover that PWM6 and PWM7 share the same timer- timer 2. This means that independent frequencies are not achievable in any obvious way.

    Here is my best attempt so far. Uses mikroElectronika mikroC compiler to make PPS simpler, but if I ever manage a working version, porting to MPLABX should be straight forward. I test on PIC18857 as I have one, but I assume '56' and '57' are identical other than memory size.

    Code:
    // PWM test for PIC18857 using 4MHz internal oscillator
    // amateur code - use at your own risk - author accepts no responsibility for anything, anywhere, ever
    // Example of using NCO module for DDS  - gives approx 500Hz square wave on RA2
    
    // spec from forum - We need to set a fixed PWM of 30% duty at approx. 500Hz on RA2.
    // We also need a variable PWM on RA1. (frequency anywhere between 2kHz and 300Hz, but again it will be a fixed frequency)
    
    void main() {
    
        OSCEN = 0x20;                                                               // internal oscillator explicit selection
        OSCFRQ = 0x02;                                                              // change internal oscillator to 4 MHz
        OSCCON1 = 0x60;                                                             // select internal oscillator, divider = 1
    
        ANSELA = 0;                                                                 // all digital
        TRISA = 0;                                                                  // all output
        LATA = 0;                                                                   // start all low
        ANSELB = 0;                                                                 // all digital
        TRISB = 0;                                                                  // all output
        LATB = 0;                                                                   // start all low
        ANSELC = 0;                                                                 // all digital
        TRISC = 0;                                                                  // all output
        LATC = 0;                                                                   // start all low
    
        Unlock_IOLOCK();                                                            // allow PPS mapping
        PPS_Mapping_NoLock(2, _OUTPUT, _PWM7OUT);                                   // Set pin A2 to be Output, and map PWM7 to it
        PPS_Mapping_NoLock(1, _OUTPUT, _NCO);                                       // Set pin A1 to be Output, and map NCO to it
    
        NCO1CON = 0x80;                                                             // enable NCO in 50% mode
        NCO1CLK = 0x00;                                                             // processor clock as NCO source
        NCO1INCH = 0x01;                                                            // always write high before low
        NCO1INCL = 0x03;                                                            // latch high and low together  - 0002 gives approx 1Hz
    
        T2CLKCON = 0x01;                                                            // Fosc/4 as clock
        T2CON = 0xd0;                                                               // T2 on, 1:4 prescaler, 1:1 postscaler
        T2HLT = 0x00;                                                               // free running mode
        
        PR2 = 0x3e;                                                                 // 0x3e seems to give 500Hz
        
        PWM7CON = 0x80;                                                             // enable PWM7
        PWM7DCH = 0x13;                                                             // 0x1300 seems to give 30% duty
        PWM7DCL = 0x00;                                                             // only top 2 bits used for fine control
        
        while(1){
    
        }
    }



  8. #8
    Super Moderator
    Points: 249,046, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,337
    Helped
    13176 / 13176
    Points
    249,046
    Level
    100

    Re: Need two PWMs from PIC16F18856 microcontroller

    As far as I understand, timer 4 and 6 can be chosen alternatively for each PWM unit. But as mentioned before, you face the problem of maximal PWM period, you'll probably need to go for a more complex solution.



  9. #9
    Super Moderator
    Points: 66,847, Level: 63
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    13,639
    Helped
    3122 / 3122
    Points
    66,847
    Level
    63

    Re: Need two PWMs from PIC16F18856 microcontroller

    Hi,

    500Hz, 30% duty cycle:

    run an ISR about every 200us (5kHz):
    * increment counter (0..9)
    * on counter = 0, 1, 2 --> output HIGH, else output LOW.

    But I donīt know if its possible with PIC to run an ISR every 200us...

    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



    •   AltAdvertisment

        
       

  10. #10
    Advanced Member level 1
    Points: 4,156, Level: 15
    Achievements:
    7 years registered
    hexreader's Avatar
    Join Date
    Apr 2011
    Location
    England
    Posts
    477
    Helped
    184 / 184
    Points
    4,156
    Level
    15

    Re: Need two PWMs from PIC16F18856 microcontroller

    Quote Originally Posted by FvM View Post
    As far as I understand, timer 4 and 6 can be chosen alternatively for each PWM unit. But as mentioned before, you face the problem of maximal PWM period, you'll probably need to go for a more complex solution.
    Amazing how I could miss the obvious! That's the solution, thanks FvM.

    This mikroC code seems to work just fine, as far as I can tell:
    Code:
    // PWM test for PIC18857 using 4MHz internal oscillator
    // amateur code - use at your own risk - author accepts no responsibility for anything, anywhere, ever
    
    // spec from forum - We need to set a fixed PWM of 30% duty at approx. 500Hz on RA2.
    // We also need a variable PWM on RA1. (frequency anywhere between 2kHz and 300Hz, but again it will be a fixed frequency)
    
    void main() {
    
        OSCEN = 0x20;                                                               // internal oscillator explicit selection
        OSCFRQ = 0x02;                                                              // change internal oscillator to 4 MHz
        OSCCON1 = 0x60;                                                             // select internal oscillator, divider = 1
    
        ANSELA = 0;                                                                 // all digital
        TRISA = 0;                                                                  // all output
        LATA = 0;                                                                   // start all low
       
        Unlock_IOLOCK();                                                            // allow PPS mapping
        PPS_Mapping_NoLock(2, _OUTPUT, _PWM7OUT);                                   // Set pin A2 to be Output, and map PWM7 to it
        PPS_Mapping_NoLock(1, _OUTPUT, _PWM6OUT);                                   // Set pin A1 to be Output, and map PWM6 to it
    
        T2CLKCON = 0x01;                                                            // Fosc/4 as clock
        T2CON = 0xd0;                                                               // T2 on, 1:4 prescaler, 1:1 postscaler
        T2HLT = 0x00;                                                               // free running mode
    
        T6CLKCON = 0x01;                                                            // Fosc/4 as clock
        T6CON = 0xd0;                                                               // T6 on, 1:4 prescaler, 1:1 postscaler
        T6HLT = 0x00;                                                               // free running mode
    
        PR2 = 0x3e;                                                                 // 0x3e seems to give 500Hz
        PR6 = 0x4e;                                                                 // 0x4e seems to give 400Hz
        CCPTMRS1 = 0x1D;                                                            // PWM6 clocked by timer 6, PWM7 clocked by timer 2
        
        PWM6CON = 0x80;                                                             // enable PWM6
        PWM6DCH = 0x23;                                                             // 0x2300 seems to give 45% duty
        PWM6DCL = 0x00;                                                             // only top 2 bits used for fine control
    
        PWM7CON = 0x80;                                                             // enable PWM7
        PWM7DCH = 0x13;                                                             // 0x1300 seems to give 30% duty
        PWM7DCL = 0x00;                                                             // only top 2 bits used for fine control
        
        while(1);                                                                   // infinite loop
    }
    Will probably get around to porting this to MPLABX and XC8 sometime.... don't know when.

    - - - Updated - - -

    It took a lot less time than I expected to port code to XC8....

    Code:
    // PIC16F18856
    // XC8 compiler
    // MPLAB X V3.61
    // date 10 Nov 2018
    
    // updated by amateur coder who accepts no responsibility for anything, anywhere, ever
    // spec from forum - We need to set a fixed PWM of 30% duty at approx. 500Hz on RA2.
    // We also need a variable PWM on RA1. (frequency anywhere between 2kHz and 300Hz, but again it will be a fixed frequency)
    
    // CONFIG1
    #pragma config FEXTOSC = OFF                // External Oscillator mode selection bits (Oscillator not enabled)
    #pragma config RSTOSC = HFINT1              // Power-up default value for COSC bits (HFINTOSC (1MHz))
    #pragma config CLKOUTEN = OFF               // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
    #pragma config CSWEN = ON                   // Clock Switch Enable bit (The NOSC and NDIV bits can be changed by user software)
    #pragma config FCMEN = OFF                  // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)
    
    // CONFIG2
    #pragma config MCLRE = OFF                  // Master Clear Enable bit (MCLR pin function is port defined function)
    #pragma config PWRTE = ON                   // Power-up Timer Enable bit (PWRT enabled)
    #pragma config LPBOREN = OFF                // Low-Power BOR enable bit (ULPBOR disabled)
    #pragma config BOREN = ON                   // Brown-out reset enable bits (Brown-out Reset Enabled, SBOREN bit is ignored)
    #pragma config BORV = LO                    // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
    #pragma config ZCD = OFF                    // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
    #pragma config PPS1WAY = OFF                // Peripheral Pin Select one-way control (The PPSLOCK bit can be set and cleared repeatedly by software)
    #pragma config STVREN = OFF                 // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will not cause a reset)
    
    // CONFIG3
    #pragma config WDTCPS = WDTCPS_31           // WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
    #pragma config WDTE = OFF                   // WDT operating mode (WDT Disabled, SWDTEN is ignored)
    #pragma config WDTCWS = WDTCWS_7            // WDT Window Select bits (window always open (100%); software control; keyed access not required)
    #pragma config WDTCCS = SC                  // WDT input clock selector (Software Control)
    
    // CONFIG4
    #pragma config WRT = OFF                    // UserNVM self-write protection bits (Write protection off)
    #pragma config SCANE = not_available        // Scanner Enable bit (Scanner module is not available for use)
    #pragma config LVP = OFF                    // Low Voltage Programming Enable bit (High Voltage on MCLR/Vpp must be used for programming)
    
    // CONFIG5
    #pragma config CP = OFF                     // UserNVM Program memory code protection bit (Program Memory code protection disabled)
    #pragma config CPD = OFF                    // DataNVM code protection bit (Data EEPROM code protection disabled)
    
    // #pragma config statements should precede project file includes.
    
    #include                              // forum will remove xc.h within braces :(
    #include                          // forum will remove stdint.h within braces :(
    
    #define  _XTAL_FREQ 4000000
    
    void main(void){
        
        OSCEN = 0x20;                           // internal oscillator explicit selection
        OSCFRQ = 0x02;                          // change internal oscillator to 4 MHz
        OSCCON1 = 0x60;                         // select internal oscillator, divider = 1
        
        TRISA = 0x90;                           // RA4 temperature input, RA7 ?
        ANSELA = 0x10;                          // RA4 analogue selection for temperature input
    
        CM1CON0 = 0x00;
        CM1CON1 = 0x00;
        CM2CON0 = 0x00;
        CM2CON1 = 0x00;
    
        ZCDCON = 0x00;
    
        RA1PPS = 0x0e;                                                              // map PWM6 to RA1
        RA2PPS = 0x0f;                                                              // map PWM7 to RA1
        
        T2CLKCON = 0x01;                                                            // Fosc/4 as clock
        T2CON = 0xd0;                                                               // T2 on, 1:4 prescaler, 1:1 postscaler
        T2HLT = 0x00;                                                               // free running mode
    
        T6CLKCON = 0x01;                                                            // Fosc/4 as clock
        T6CON = 0xd0;                                                               // T6 on, 1:4 prescaler, 1:1 postscaler
        T6HLT = 0x00;                                                               // free running mode
    
        PR2 = 0x3e;                                                                 // 0x3e seems to give 500Hz
        PR6 = 0x4e;                                                                 // 0x4e seems to give 400Hz
        CCPTMRS1 = 0x1D;                                                            // PWM6 clocked by timer 6, PWM7 clocked by timer 2
        
        PWM6CON = 0x80;                                                             // enable PWM6
        PWM6DCH = 0x23;                                                             // 0x2300 seems to give 45% duty
        PWM6DCL = 0x00;                                                             // only top 2 bits used for fine control
    
        PWM7CON = 0x80;                                                             // enable PWM7
        PWM7DCH = 0x13;                                                             // 0x1300 seems to give 30% duty
        PWM7DCL = 0x00;                                                             // only top 2 bits used for fine control
        
        // main loop    
        while(1){       
        
        }
    }
    Last edited by hexreader; 10th November 2018 at 17:54.



--[[ ]]--