• 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.

fire alaram sound using PIC16F886

How to send PWm signal in TOn time of Timer0

  • pwm ,pic

    Votes: 1 100.0%
  • pwm ,pic

    Votes: 0 0.0%

  • Total voters
    1
Status
Not open for further replies.

ajit_nayak87

New Member
I am coding on pIC16F886 IC. I am trying to generate Fire alarm siren with PWMsignal . I have few questions as below. I copied code from Example code My spaker circuit look like this video , I am sending PWM pulses instead of audio Input mosfet circuit

I could able to produce based on PWM signal.

Below code produce 50% duty cycle with 2Khz frequency.Now i am trying to produce fire alaram sound for that I am plan to use Timer1 interrupt 16 bit. During Ton time of timer send PWM signal for duty cycle 50% and Toff time of timer1 i will turn of PWM timer. can someone suggest how can make below changes.
C:
#include <htc.h>
#include <stdio.h>
#include<pic.h>
#include<stdint.h>
#define _XTAL_FREQ 20000000
unsigned int i=0;
#define TMR2PRESCALE 16
long freq;
unsigned int x;
#define LED RC7
#define LED1 RC6
#define LED2 RC2
unsigned short int cnt, num,Dgt=0;
unsigned int i;
unsigned int j;

void out_p(int l , int k);
int PWM_Max_Duty()
{
 return(_XTAL_FREQ/(freq*TMR2PRESCALE);
}
PWM1_Init(long fre)
{
 PR2 = (_XTAL_FREQ/(freq*4*TMR2PRESCALE)) - 1;
 freq = fre;
}

PWM1_Duty(unsigned int duty)
{
 if(duty<1024)
 {
 duty = ((float)duty/1023)*PWM_Max_Duty();
 CCP1X = duty & 2;
 CCP1Y = duty & 1;
 CCPR1L = duty>>2;
 }
}

PWM1_Start()
{
 CCP1M3 = 1;
 CCP1M2 = 1;
 #if TMR2PRESCALE == 1
 T2CKPS0 = 0;
 T2CKPS1 = 0;
 #elif TMR2PRESCALE == 4
 T2CKPS0 = 1;
 T2CKPS1 = 0;
 #elif TMR2PRESCALE == 16
 T2CKPS0 = 1;
 T2CKPS1 = 1;
 #endif
 TMR2ON = 1;
 TRISC2 = 0;
}

PWM1_Stop()
{
 CCP1M3 = 0;
 CCP1M2 = 0;
}


void SetPWMDutyCycle(unsigned int DutyCycle) // Give a value in between 0 and 1024 for DutyCycle
{
 CCPR1L = DutyCycle>>2; // Put MSB 8 bits in CCPR1L
 CCP1CON &= 0xCF; // Make bit4 and 5 zero
 CCP1CON |= (0x30&(DutyCycle<<4)); // Assign Last 2 LSBs to CCP1CON
}


void InitPWM(void)
{
 TRISC2 = 0; // Make CCP1 pin as output
 CCP1CON = 0x0C; // Configure CCP1 module in PWM mode
PR2 = 0xFF; // Configure the Timer2 period
 T2CON = 0x01; // Set Prescaler to be 4, hence PWM frequency is set to 4.88KHz.
SetPWMDutyCycle(0); // Intialize the PWM to 0 duty cycle
T2CON |= 0x04; // Enable the Timer2, hence enable the PWM.
}


void Delay(int k)
{
for(j=0;j<k;j++);
}
void tone(int Frequency,int duration)
{
 SetPWMDutyCycle(Frequency);
 Delay(duration);

}


void Timer1_Interrupt()
 {

 INTCON = 0b00000000;
 PIE1=0b00000001;
 PIR1=0x01;
 TMR1H=0x0B;
 TMR1L=0xDC;
 T1CON=0x31;
 // T1CON=0x01;
 }



 void Init_Controller()
 {
 cnt=100;
 TRISC=0b00000000;
 PORTC=0b00000000;
 TRISB=0b10000000;
 PORTB = 0b00000000;
 TRISA=0b00000000;
 PORTA=0X00;
 ADCON0 = 0b00000000;
 ANSEL = 0b00000000;
 Timer1_Interrupt();
 LED=0;
 LED1=0;
 LED2=0;

 }


void interrupt isr(void)
 {
 if(TMR1IF==1)
 {
 TMR1H=0xEA; // Load the time value(0x0BDC) for 100ms delay
 TMR1L=0x60; //Timer1 Interrupt for 65000
 TMR1IF=0; // Clear timer interrupt flag
 Dgt++;

 LED=!LED;
 LED1=!LED1;


 }

 }

void main(void)
 {
Init_Controller();
 Timer1_Interrupt();
 GIE=1;
 PEIE=1;
 TMR1IE=1;
PWM1_Init(5000);
PWM1_Start();

while(1)
 {

 PWM1_Duty(500);

 }

}
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Don't confuse PWM sounds and beeper sounds.... If you generate a 2khz PWM at 50% it's no different to toggling a pin high / low..

It is easier to create simple sounds that output to a speaker just using a timer than programming a PWM to output complex sounds.. The code you posted just changes the PWM frequency... Don't get me wrong, It will work okay but its easier to just use the timer..
 

ajit_nayak87

New Member
This what i obeserved , Intially i tried with timer 1 just turn on & turn off for duration of 100ms. I could able to produce sound but not louder. Then i research where i could able to find PWM signal generator where i could able to produce more sound . This what i want. Keeping frequency constant based on timer1 is it possible to send desired frequency during Ton time of timer and make it frequency 0 during turn Off timer.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
I am using 5V ,8ohm ,2W , 100-200Khz speaker . It can create 96db of sound. There is no doubt on spec of Speaker....
Pic pin isn't strong enough to drive a 2W speaker directly, you'll need to amplify the current..

upload_2017-11-25_15-42-2.png
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Can you tell how can change my code , to turn on PWM for TON time and OFF pwm for Toff time
Changing the TON and TOFF time doesn't change the frequency... The CCPR1L holds the duty cycle.. This is tested against PR2....
If PR2 = 255 and CCPR1l = 127 then there is a 50% duty cycle
If PR2 = 255 and CCPR1l = 63 then there is a 25% duty cycle
If PR2 = 255 and CCPR1l = 192 then there is a 75% duty cycle

But the frequency will be the same.... If you are just increasing the TON to make it louder your frequency will become distorted..

If you alter your frequency BUT! you need to maintain a high duty cycle you need to change 4 registers each time a note is played..

SO! you will need to set the frequency and then alter the duty cycle once the PR2 is set..

C:
void tone(int Frequency, int duration)
{
 SetPWMDutyCycle(Frequency);
 SetPWMDutyCycle(DutyCycle) ;
 Delay(duration);
}
However! The above will not work as when the frequency moves over the time base the PR2 will move from 255 to a lower value which makes the duty cycle different.. DutyCycle in your code is 0 ~ 1024 You need to make the duty cycle adjustable to the PR2 register.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Here is a ringtone C file...
Notice there isn't a PWM in sight!!
C:
/*****************************************************************************/
/*                                                                           */
/*       RTTTL Ring Tone Player for Microchip PIC16F87x Microcontrollers     */
/*                   Copyright [email protected]                 */
/*                       Version 1.0 17th August 2003                        */
/*                                                                           */
/*****************************************************************************/
#include <xc.h>
#define TONE    RB0
void InitTimer(void);
void delayms(unsigned char cnt);
void PlayNote(unsigned short note, unsigned char octave, unsigned int duration);
unsigned char beep;
unsigned char preloadTMR1L;
unsigned char preloadTMR1H;
unsigned short TMR0Count;
unsigned char beat_speed;
#define MissionImpossible
void main(void)
{
    unsigned int pointer = 0;
    unsigned int octave = 0;
    unsigned int duration = 0;
    unsigned short note = 0;
    unsigned int defaultoctave = 0;
    unsigned int defaultduration = 0;
#ifdef AxelF
    /* AxelF */
    const unsigned char Melody[] = {"32p,8g,8p,16a#.6,8p,16g,16p,16g,8c6,8g,8f,8g,8p,16d.6,8p,16g,16p,16g,8d#6,8d6,8a#6,8g,8d6,8g6,16g,16f,16p,16f,8d,8a#6,2g,4p,16f6,8d6,8c6,8a#6,4g,8a#.6,16g,16p,16g,8c6,8g,8f,4g,8d.6,16g,16p,16g,8d#6,8d6,8a#6,8g,8d6,8g6,16g,16f,16p,16f,8d,8a#6,2g"};
    defaultoctave = 5;
    defaultduration = 4;
    beat_speed = 125;
#endif
#ifdef HappyBirthday
    /* HappyBirthday */
    const unsigned char Melody[] = {"8g.,16g,a6,g,c6,2b6,8g.,16g,a6,g,d6,2c6,8g.,16g,g6,e6,c6,b6,a6,8f6.,16f6,e6,c6,d6,2c6,8g.,16g,a6,g,c6,2b6,8g.,16g,a6,g,d6,2c6,8g.,16g,g6,e6,c6,b6,a6,8f6.,16f6,e6,c6,d6,2c6"};
    defaultoctave = 5;
    defaultduration = 4;
    beat_speed = 125;
#endif
#ifdef Itchy
    /* Itchy & Scratcy */
    const unsigned char Melody[] = {"8c,8a5,4p,8c,8a,4p,8c,a5,8c,a5,8c,8a,4p,8p,8c,8d,8e,8p,8e,8f,8g,4p,8d,8c,4d,8f,4a#,4a,2c7"};
    defaultoctave = 6;
    defaultduration = 8;
    beat_speed = 198;
#endif
#ifdef MissionImpossible
    /* Mission Impossible */
    const unsigned char Melody[] = {"16d5,16d#5,16d5,16d#5,16d5,16d#5,16d5,16d5,16d#5,16e5,16f5,16f#5,16g5,8g5,4p,8g5,4p,8a#5,8p,8c6,8p,8g5,4p,8g5,4p,8f5,8p,8p,8g5,4p,4p,8a#5,8p,8c6,8p,8g5,4p,4p,8f5,8p,8f#5,8p,8a#5,8g5,1d5"};
    defaultoctave = 6;
    defaultduration = 4;
    beat_speed = 150;
#endif
    TRISB0 = 0;     /* Make TONE an output */
    beep = 0;
    InitTimer();
    PEIE = 1;
    GIE = 1;      /* Enable General Purpose Interrupts */
    do {
        octave = defaultoctave;  /* Set Default Octave */
        if ((Melody[pointer] == '3') && (Melody[pointer+1] == '2')) {
            duration = 32;
            pointer += 2;
        }
        else if ((Melody[pointer] == '1') && (Melody[pointer+1] == '6')) {
            duration = 16;
            pointer += 2;
        }
        else if (Melody[pointer] == '8') {
            duration = 8;
            pointer++;
        }
        else if (Melody[pointer] == '4') {
            duration = 4;
            pointer++;
        }
        else if (Melody[pointer] == '2') {
            duration = 2;
            pointer++;
        }
        else if (Melody[pointer] == '1') {
            duration = 1;
            pointer++;
        } else duration = defaultduration;
        if (Melody[pointer + 1] == '#') {
            /* Process Sharps */
            switch (Melody[pointer]) {
                case 'a' : note = 10726;
                           break;
                case 'c' : note = 9019;
                           break;
                case 'd' : note = 8035;
                           break;
                case 'f' : note = 6757;
                           break;
                case 'g' : note = 6024;
                           break;
            }
            pointer +=2;
        } else {
            switch (Melody[pointer]) {
                case 'a' : note = 11364;
                           break;
                case 'b' : note = 10123;
                           break;
                case 'c' : note = 9555;
                           break;
                case 'd' : note = 8513;
                           break;
                case 'e' : note = 7584;    
                           break;
                case 'f' : note = 7158;
                           break;
                case 'g' : note = 6378;
                           break;
                case 'p' : note = 0;
                           break;
            }
            pointer++;
        }
        if (Melody[pointer] == '.') {
            /* Duration 1.5x */
            duration = duration + 128;
            pointer++;
        }
        if (Melody[pointer] == '4') {
            octave = 4;
            pointer++;
        } else if (Melody[pointer] == '5') {
            octave = 5;
            pointer++;
        } else     if (Melody[pointer] == '6') {
            octave = 6;
            pointer++;
        } else     if (Melody[pointer] == '7') {
            octave = 7;
            pointer++;
        }
        if (Melody[pointer] == '.') {
            /* Duration 1.5x */
            duration = duration + 128;
            pointer++;
        }
        PlayNote(note, octave, duration);
    
       
     } while (Melody[pointer++] == ',');
    
    /* Wait until last note has played */
    while(TMR0Count) { };
    beep = 0;
    /* Loop */
    while(1) {};
}
void PlayNote(unsigned short note, unsigned char octave, unsigned int duration)
{
    /* Process octave */
    switch (octave) {
        case 4 : /* Do noting */
             break;
        case 5 : /* %2 */
             note = note >> 1; 
             break;
        case 6 : /* %4 */
             note = note >> 2;
             break;
        case 7 : /* %8 */
             note = note >> 4;
             break;
    }
    /* Wait until last note has played */
    while(TMR0Count) { };
    beep = 0;
    /* Process New Note Frequency */
    if (note) {
        note = ~note;
        preloadTMR1L = (note & 0xFF);
        preloadTMR1H = ((note & 0xFF00) >> 8);
    }
    
    /* Process Note Duration */    
    TMR0Count = 255/(duration & 0x7F);
    /* If duration is 1.5x add .5 to duration */
    if (duration & 0x80) TMR0Count = (TMR0Count + (TMR0Count >> 1));   
    if (note) beep = 1;
}
void InitTimer(void)
{
    /* Initialise Timer 0 */
    OPTION_REG = 0b11010111;  /* Set TMR0 to Internal CLk, 1:256 */
    T0IF = 0;             /* Clear TMR0 Flag, ready for use */
    T0IE = 1;             /* Enable Timer Overflow Interrupt */
    /* Initialise Timer 1 */
    T1CON = 0b00000001;   /* Counter Enabled, Using Ext Pin 1:1 Prescaler */
    TMR1IF = 0;           /* Clear Flag */
    TMR1IE = 1;           /* Enable Interrupt */
}
void interrupt interr(void)
{
    if (T0IF) {
        TMR0 = beat_speed;
        if (TMR0Count) TMR0Count--;
        T0IF = 0;
    }
    if (TMR1IF) {
        if (beep) TONE = !TONE;
        else      TONE = 0;
        TMR1H = preloadTMR1H;
        TMR1L = preloadTMR1L;
        TMR1IF = 0; /* Clear Flag */
    }
}
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
The output is not that good I tried this with 2 speakers a 1/2 watt and a 1 watt it's out was 100 mA at 11 volts
That was just a sample.... If you make a audio amp it would be better..

100mS isn't in the audio spectrum is it? A piano starts at 31hz ( barely audible ).. Fire alarms are around 500Hz (low ) and 3Khz (High) and about 110 db..
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top