Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
Thread Tools Display Modes
Old 7th April 2008, 11:35 PM   (permalink)
Default PWM on a PIC

PWM in title
How would i go about making a PWM signal using software alone.. 38khz of course

i know this much:

Code:
/*
 * PWM registers configuration
 * Fosc = 8000000 Hz
 * Fpwm = 37735.85 Hz (Requested : 38000 Hz)
 * Duty Cycle = 50 %
 * Resolution is 7 bits
 * Prescaler is 1
 * Ensure that your PWM pin is configured as digital output
 * see more details on http://www.micro-examples.com/
 * this source code is provided 'as is',
 * use it at your own risks
 */
PR2 = 0b00110100 ;
T2CON = 0b00000100 ;
CCPR1L = 0b00011010 ;
CCP1CON = 0b00011100 ;
From http://www.micro-examples.com/public...alculator.html

But that just sets the registers... Now what?

Do i just do a high/low with delays? Or would that be just a software PWM by itself?

Last edited by AtomSoft; 7th April 2008 at 11:40 PM. Reason: Topic Typo
AtomSoft is offline   Reply With Quote
Old 7th April 2008, 11:38 PM   (permalink)
Default See the other thread

See Krumlinks' Thread.

http://www.electro-tech-online.com/m...e-pic13xx.html

Done correctly, you let the hardware do it all for you. Read the Capture/Compare/PWM module doc till your eyes fall out. It is there.
__________________
August Treubig
AG5AT

Last edited by August Treubig; 7th April 2008 at 11:40 PM.
August Treubig is offline   Reply With Quote
Old 7th April 2008, 11:42 PM   (permalink)
Default

Thx.. Not sure i understand but ..
Code:
    // speed up the clock to 8MHz
    OSCCONbits.IRCF0=1; OSCCONbits.IRCF1=1;
    OSCCONbits.IRCF1=1;
    OSCCONbits.IRCF2=1;
    OSCCONbits.SCS0=0;
    OSCCONbits.SCS1=0;
    //18F1330 Speed clock up to 32MHz using PLL
    OSCTUNEbits.PLLEN=1;
    ADCON1 = 0; // make RA0 digital
    TRISA = 0xFE;
    while(1)
        {
        PORTA = 0xFF;
        delay_us(13);
        PORTA = 0x00;    
        delay_us(13);
    }
so basically i just set the registers and send a high and low to the corresponding pin with a delay right?

So to send 0000001 i would send

Low
Delay
Low
Delay
Low
Delay
Low
Delay
Low
Delay
Low
Delay
Low
Delay
High
?

Like that?

or

High
Delay(small)

High
Delay(small)

High
Delay(small)

High
Delay(small)

High
Delay(small)

High
Delay(small)

High
Delay(small)

High
Delay(longer)
AtomSoft is offline   Reply With Quote
Old 7th April 2008, 11:44 PM   (permalink)
Default

Its for a IR Remote....
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 12:10 AM   (permalink)
Default Actually no

I understand what it is for. Please look at the code first code that I posted in the other thread.

While it isn't for Sony or the more popular stuff. It is for my Panasonic HD TV. It will turn it on and off every time. The key here is that it uses PWM hardware to generate the 38khz signal.

The second example came first and is a working (at 4mhz) section of code that used to be in the first program.

With the PWM hardware, you tell it the length of the pulse and then in another place the duty cycle. In our case 50%. Then you turn it on and the hardware does it all.

__________________
August Treubig
AG5AT
August Treubig is offline   Reply With Quote
Old 8th April 2008, 01:28 AM   (permalink)
Default

Not sure how it works tho....

Um can you comment some of it like um...
You said ... You tell it the length of the pulse and the duty cycle... Is the duty cycle what is sending the actual code?

How would i send 2 bytes? like

0x0D and then 0x00 ?
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 01:52 AM   (permalink)
Default

"The SIRC protocol uses a pulse width encoding of the bits. The pulse representing a logical "1" is a 1.2ms long burst of the 40kHz carrier, while the burst width for a logical "0" is 0.6ms long. All bursts are separated by a 0.6ms long space interval. The recommended carrier duty-cycle is 1/4 or 1/3."

so to send a 0x00 i have to send :
start (high) for 2.4ms
.6ms delay
"high' for .6ms
delay .6ms
"high' for .6ms

something like that?

Just setting that 1 pin high and low for periods of time?

Im confused because you use PORTA = 0xFF that sets all of PORTA bits. Even the ones not on the IR led.... right
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 01:57 AM   (permalink)
Default The answers are in the other thread

Please look at Krumlink's thread. I have posted the code in pieces there.


Ok here is the whole thing for 18F1320

Code:
#include <system.h>

//Target PIC18F1320 configuration word

//#pragma DATA _CONFIG, _CP_OFF & _LVP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSC_OSC_NOCLKOUT

#pragma DATA  _CONFIG1H, _INTIO2_OSC_1H & _FSCM_OFF_1H
#pragma DATA  _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _BORV_27_2L
#pragma DATA  _CONFIG2H, _WDT_OFF_2H & _WDTPS_32K_2H
#pragma DATA  _CONFIG3H, _MCLRE_ON_3H
#pragma DATA  _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_ON_4L

#pragma DATA  _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
#pragma DATA  _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
#pragma DATA  _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
#pragma DATA  _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
#pragma DATA  _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
#pragma DATA  _CONFIG7H, _EBTRB_OFF_7H

//Set clock frequency
#pragma CLOCK_FREQ    8000000


// 38 khz

#define CCP1Period    12
#define    CCP1DutyCy    25



bit        running = 0;

unsigned char    turnon[6] = { 0x40, 4, 1, 0, 0xbc, 0xbd};

void interrupt( void )
{
    // Handle timer1 interrupt
    // Used to time the length of pulses
    if( pir1.TMR1IF )
    {
        running = 0;
        t1con.TMR1ON = 0;    // Turn TIMER1 off
        pir1.TMR1IF = 0; //clear timer 1 interrupt bit
    }
}

void xmit_pulse(short micro_pulse)
{
    static short    clock_count;
    clock_count = 65536 - micro_pulse;
    LOBYTE( tmr1l, clock_count);
    HIBYTE( tmr1h, clock_count);
    pir1.TMR1IF = 0;        // Reset overflow bit
    t1con.TMR1ON = 1;    // Turn TIMER1 on
    running = 1;

    trisb.3 = 0;
    t2con.TMR2ON = 1;
    while (running) ;        // Wait for pulse time to end    
    t2con.TMR2ON = 0;
    tmr2 = 0;
    portb.3 = 0;
    trisb.3 = 1;
}

void send_on(void) {
    static char    i;
    static char    j;
    static char    t;
    static unsigned char    *ovalue;
    static unsigned char    k;

//    Send it 3 times
    for (k = 0; k < 3; k++) {
        ovalue = &turnon;
        xmit_pulse(3550);    // 4 ms header
        delay_100us(10);    // 1 ms
        delay_10us(6);        // .6 ms
        for (i = 0; i < 6; i++) {
            for (j = 8; j > 0; j--) {
                t = j - 1;
                if (test_bit(*ovalue, t)) {
//                    A one
                    xmit_pulse(512);        // 400 micro s 
                    delay_100us(10);        // 1 ms
                    delay_10us(2);            // .2 ms
                }
                else {
//                    A zero
                    xmit_pulse(512);        // 400 micro s
                    delay_100us(3);            // 400 micro s
                }
            }
            ovalue++;
        }
//        End bit
        xmit_pulse(400);
        delay_ms(70);
    }
}
void main( void )
{
    static unsigned char    Low;
    static unsigned char    High;
    static unsigned int        Duty = CCP1DutyCy;
    // Set speed to 8 mhz
    set_bit(osccon, IRCF2);
    set_bit(osccon, IRCF1);
    set_bit(osccon, IRCF0);
    ccp1con = 0;        // CCP Module off
    tmr2 = 0;            // Clear Timer 2
    //Configure port B
    trisb = 0x00;
    trisb.3 = 1;
    intcon2.NOT_RBPU = 0;
    //Initialize port B
    portb = 0;

    //Set timer 1
    //prescaler rate 1:1
    //Internal clock (FOSC/4)
    t1con = 00001000b;

    // Configure Capture/Compare/PWM for PWM
    // at 38khz.  
    //Set timer 2 prescaler rate
    // T2CPS = 1:4
    t2con = 00000001b;
    //t2con = 0;
    pr2 = CCP1Period;
    Low = Duty & 3;
    High = Duty >> 2;
    ccpr1l = High;
    ccp1con = 00001100b;
    ccp1con.5 = Low.1;
    ccp1con.4 = Low.0;

    intcon.PEIE = 1;        // Enable peripheral interrupts
    intcon.GIE = 1;         // Enable global interrupt
    pie1.TMR1IE = 1;        // Enable Timer 1 interrupts

// test    
    trisb.3 = 0;
    t2con.TMR2ON = 1;
    while (1) ;
//  test

//    Main Loop
    send_on();
    while (1) {
    }
}
Configuring the PWM using TMR2

Code:
// 38 khz

#define CCP1Period    12
#define    CCP1DutyCy    25

    static unsigned char    Low;
    static unsigned char    High;
    static unsigned int        Duty = CCP1DutyCy;

    // Configure Capture/Compare/PWM for PWM
    // at 38khz.  
    //Set timer 2 prescaler rate
    // T2CPS = 1:4
    t2con = 00000001b;
    //t2con = 0;
    pr2 = CCP1Period;
    Low = Duty & 3;
    High = Duty >> 2;
    ccpr1l = High;
    ccp1con = 00001100b;
    ccp1con.5 = Low.1;
    ccp1con.4 = Low.0;
Turn it on

Code:
    trisb.3 = 0;
    t2con.TMR2ON = 1;
__________________
August Treubig
AG5AT
August Treubig is offline   Reply With Quote
Old 8th April 2008, 02:15 AM   (permalink)
Default

That seems like way too much code just to send a pulse....

And just telling me to look at the code doesnt really help... I thank you for trying to point me to the right direction but this doesnt answer my question.

which was:

HIGH(4ms) - would be start bit
LOW(1ms) - a space
HIGH(1ms) - a 0
LOW(1ms) - a space
HIGH(2ms) - a 1

would it be something like that to send a start then 0 and 1 bit?

Maybe its me or this code isnt commented well enough. Remember im a nooB still and well... this seems too much for something that seems so simple to achieve.
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 04:08 AM   (permalink)
Default

This code starts the PWM on Junebugs RB3, you can watch RB3 using MPLABS simulator / logic analyzer.
Code:
// 37.7kHZ PWM IR carrier signal
#include <p18f1320.h>
#pragma config WDT = OFF,OSC = INTIO2,LVP = OFF
void main(void) {    
    OSCCON=0x72; // speed up the clock to 8MHz
    ADCON1 = 0; 
    TRISBbits.TRISB3 = 0;
    PR2 = 0b00110100 ;
    T2CON = 0b00000100 ;
    CCPR1L = 0b00011010 ;
    CCP1CON = 0b00011100 ;
    while(1) {
     }    
}
An IR LED on RB3 with this running should pretty much jam any nearby IR receivers.
Attached Images
File Type: png PWMJunebug.png (7.5 KB, 12 views)
__________________
Bill
Smart Kits build Smart People

http://www.blueroomelectronics.com
blueroomelectronics is offline   Reply With Quote
Old 8th April 2008, 05:02 AM   (permalink)
Default

ok i can see how it starts it ...

To turn it off i do...
T2CON = 0b00000000 ;

i assume... But how do i send out the data still? still no straight answer..

To send data does it require me to set RB3 HIGH? If so :

When i set it high do i have to make a delay for the amount of time it has to be high to represent a logical 1, 0 and space. (also start)
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 05:09 AM   (permalink)
Default

I would set the duty to 0% for a zero; then to 50% for a 1. The 38KHz is a carrier (envelope) for the data, as long as the data timing is correct the IR decoder will strip away the carrier automatically and pass the raw data to the PIC.
http://www.sixca.com/eng/articles/remote/index.html


Also read this for the data format for Sony RC5
http://www.sbprojects.com/knowledge/ir/sirc.htm

Those black squares are actually a 38KHz square wave! (the carrier)
__________________
Bill
Smart Kits build Smart People

http://www.blueroomelectronics.com

Last edited by blueroomelectronics; 8th April 2008 at 05:11 AM.
blueroomelectronics is offline   Reply With Quote
Old 8th April 2008, 05:10 AM   (permalink)
Default

ok ok ok that kinda made more send let me fiddle lol
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 05:35 AM   (permalink)
Default

OK ok ok i think im getting it but still confusing just a little maybe lol

CCPR1L = 157 ;//Would this be high? or good enough
CCPR1L = 0; // I guess good enough for low

Now all i have to do is make a delay of 600uS and for a 2.4ms i can call it 4 times? while at 50% then drop to 0% and call the delay 1 time for a space..

Does that sound about right so far?
AtomSoft is offline   Reply With Quote
Old 8th April 2008, 05:38 AM   (permalink)
Default

CCPR1L = 0b00011010 ; // this should set it to 50%

I've got to sleep but will look tomorrow, sounds like you've got the right idea.

If you have an older Sony TV or VCR they may have a SIRCs jack on the (1/8" stereo phone plug). You can send unmodulated TTL level RC5/SIRC (0-5V) data to that connector.

Search for SONY+ RC5 or SIRC
__________________
Bill
Smart Kits build Smart People

http://www.blueroomelectronics.com

Last edited by blueroomelectronics; 8th April 2008 at 05:42 AM.
blueroomelectronics is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Latest
Quik PIC Programming kit Krumlink General Electronics Chat 5 27th January 2008 11:27 PM
Am I USING PIC UART CORRECTLY?? cyprio7 Micro Controllers 46 15th January 2008 06:02 PM
Capturing and reproducing audio with a PIC Fred.Amoson Micro Controllers 14 14th December 2007 08:21 PM
Problems switchin relay with PIC Andy1845c General Electronics Chat 5 17th November 2007 06:13 PM
High ADC sampling rate PIC, 18F needed? bananasiong Micro Controllers 24 28th October 2007 12:13 PM



All times are GMT. The time now is 04:15 PM.


Electronic Circuits  |  Electronics Wiki
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.