CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

generate 40khz signal using PWM

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Guest








generate 40khz signal using PWM
PostPosted: Sun Nov 16, 2008 1:21 am     Reply with quote

hi all,

I needs to create a remote controller using 16F877A micro controller. Here before sending the IR signal, it should be needed to modulate using 40khz carrier signal.

So i have faced a big problem in creating this carrier signal using PWM modulation. If anyone can help me by posting a sample code (related to my problem) or by posting some web references, it will be very helpful to me.

thanks all,
Kushan Very Happy
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Sun Nov 16, 2008 10:16 am     Reply with quote

Is there a specific reason you are using PWM? I recommend you use a simple delay_us. Your code becomes much easier. Someone faced a similar problem a few days back http://www.ccsinfo.com/forum/viewtopic.php?t=36741 .

Rohit
Guest








PostPosted: Mon Nov 17, 2008 10:12 pm     Reply with quote

Hi,

Thanks for you advises. Here in addition to generate the IR signals to control the air conditioners, i need to capture the environment temperature and send those measured temperatures trough UART to a Xbee mote. Then it does the required serial communication to establish the network.

So here i need to do a lot of calculations by using the 16f877a micro controller. therefore it takes a number of instruction cycles to complete all the tasks. then it won't create the carrier signal according to the our requirements.

A hint or help in this direction will be greatly appreciated.

thanks
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Mon Nov 17, 2008 10:35 pm     Reply with quote

Kushan,

Please do not create multiple threads with the same request http://www.ccsinfo.com/forum/viewtopic.php?t=36774 . It will be treated as spam by forum members, and will be ignored. You may post all your queries in one thread. When a new post is added to the thread it moves to the top of the discussion forum, and has a 'new post' icon beside it. Members will look into your problem and reply as necessary.

Quote:
generate the IR signals to control the air conditioners
Most IR devices use a specific IR protocol to transfer data. Is your air conditioner an 'intelligent' AC, ie does it have a manufacturer supplied IR unit? Or have you made a simple relay-based ON/OFF IR receiver? In the first case you need to understand the protocol that the manufacturer uses and try to replicate it on your PIC. In the second case you will only need to output a series of pulses.

When you need to send complicated IR data, it is easier to send this data using a subroutine (in which the IRLED is toggled manually), rather than using PWM. Even if you have multiple other devices to service and calculations to perform, this can still easily be done.

An algorithm like this can be followed:
Measure temperature (average it out, if required);
Perform calculations;
Send through Zigbee;
Send IR;
(Loop).

I don't know what calculations you need to do, and what IR signals you need to send, but this whole process (for a standard temperature control system) should take about 1 second. Do note that this time that I ahve arrived at is a result of my experiences with IR and temperature controllers. Your time will be dependent on your requirements and system specifications.

Rohit
Guest








PostPosted: Tue Nov 18, 2008 2:19 am     Reply with quote

I kindly appreciate your advice regarding the forum posts.

Yes, the air conditioner has a manufacturer supplied IR unit. I have already analyzed the IR signal bit patterns for ON signal and OFF signal. Moreover I know the bit pattern accurately with all the time period in ms. Also I have already tried with the bellow code segment to send the ON/OFF signal.

But the IR receiver doesn't identify these incoming signals. Finally I analyze the IR signal using a logic analyzer. It shows small fluctuation which should not be present on the output signal. Then I tried to generate the carrier signal using PWM modulation. But unfortunately I was not able to generate 40KHz carrier signal as the output. It gives only 4KHz carrier signal.

Any suggestions regarding my issues are kindly appreciated.

Thanks in advance.
Kushan
Code:

#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES WRT_50%                  //Lower half of Program Memory is Write Protected

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

  #include <math.h>
  #include <stdlib.h>
  #include <string.h>
 
#define KEY_Bit_C1 178        //1-8 bits of the IR bit pattern
#define KEY_Bit_C2 77         //9-16 bits of the IR bit pattern
#define KEY_Bit_C3 31         //17-24 bits of the IR bit pattern
#define KEY_Bit_C4 224        //25-32 bits of the IR bit pattern
#define KEY_Bit_ON_C5 20      //decimal equivalent of the on signal bits from 33 to 40
#define KEY_Bit_OFF_C3 123    //decimal equivalent of the on signal bits from 17 to 24
#define KEY_Bit_OFF_C5 224    //decimal equivalent of the on signal bits from 33 to 40

BYTE Is_AC_ON = 0;
BYTE Is_AC_OFF = 1;
BYTE Is_Set_AC_ON = 0;
int8 Output_Byte;  //variable to store the decimal valus while passing to the Create_Bit_Pattern() function

void Create_Bit_Pattern(int Output_Byte);
void Generate_IR_Signal(void);
void generateCarrierOne(void);
void generateCarrierZero(void);
void generateCarrierLow(void);

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   // TODO: USER CODE!!
while(true){
   
      if(input(PIN_B5) && !Is_Set_AC_ON && !Is_AC_ON){
         Is_Set_AC_ON = 1;
         Generate_IR_Signal();
         
      }
      else if(input(PIN_B5) && Is_Set_AC_ON && Is_AC_ON){
         Is_Set_AC_ON = 0;
         Generate_IR_Signal();
      }
   }
}

//function to generate IR bit patterns
void Generate_IR_Signal(void){
   int a;
   int b;
   
   if(Is_AC_ON == 0 && Is_AC_OFF == 1 && Is_Set_AC_ON == 1){         //Bit stream for the On signal
      output_bit(PIN_B3, 1);//This is to create initial high pulse.
      generateCarrierOne();
      generateCarrierOne();
      generateCarrierOne();
      output_bit(PIN_B3, 0);
      generateCarrierOne();
      generateCarrierOne();
      generateCarrierOne();
     
      //Here start sending of 48 bit long IR signal. it is needed to send the same signal twice.
      for(a=0;a<2;a++){
         Create_Bit_Pattern(Output_Byte = KEY_Bit_C1);       
         Create_Bit_Pattern(Output_Byte = KEY_Bit_C2);
         Create_Bit_Pattern(Output_Byte = KEY_Bit_C3);
         Create_Bit_Pattern(Output_Byte = KEY_Bit_C4);
         Create_Bit_Pattern(Output_Byte = KEY_Bit_ON_C5);
         Create_Bit_Pattern(Output_Byte = (255 - KEY_Bit_ON_C5));

         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
         generateCarrierOne();
         generateCarrierOne();
      }
      Is_AC_ON = 1;
      Is_AC_OFF = 0;
   }

   else if(Is_AC_ON == 1 && Is_AC_OFF == 0 && Is_Set_AC_ON == 0){     //Bit stream for the off signal
     
      output_bit(PIN_B3, 1);
      generateCarrierOne();
      generateCarrierOne();
      generateCarrierOne();
      output_bit(PIN_B3, 0);
      generateCarrierOne();
      generateCarrierOne();
      generateCarrierOne();
     
      for(b=0;b<2;b++){
         Create_Bit_Pattern(Output_Byte = KEY_Bit_C1);
         Create_Bit_Pattern(Output_Byte = KEY_Bit_C2);
         Create_Bit_Pattern(Output_Byte = KEY_Bit_OFF_C3);
         Create_Bit_Pattern(Output_Byte = (255 - KEY_Bit_OFF_C3));
         Create_Bit_Pattern(Output_Byte = KEY_Bit_OFF_C5);
         Create_Bit_Pattern(Output_Byte = (255 - KEY_Bit_OFF_C5));
         
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
         generateCarrierOne();
         generateCarrierOne();
      }
      Is_AC_ON = 0;
      Is_AC_OFF = 1;
   }
}

//funtion to generate the bit patterns
void Create_Bit_Pattern(int Output_Byte){
      if((Output_Byte & 128) == 0b10000000){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 64) == 0b01000000){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 32) == 0b00100000){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 16) == 0b00010000){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 8) == 0b00001000){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 4) == 0b00000100){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 2) == 0b00000010){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
      if((Output_Byte & 1) == 0b00000001){
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierOne();
      }
      else{
         output_bit(PIN_B3, 0);
         generateCarrierLow();
         output_bit(PIN_B3, 1);
         generateCarrierZero();
      }
}

void generateCarrierOne(void){            //Carrier signal during the High state
   int a;
   for(a=0;a<56;a++){
      output_bit(PIN_B2, 1);
      delay_us(13);
      output_bit(PIN_B2, 0);
      delay_us(12);
   }
}

void generateCarrierZero(void){        //Carrier signal during the Zero state
   int a;
   for(a=0;a<14;a++){
      output_bit(PIN_B2, 1);
      delay_us(13);
      output_bit(PIN_B2, 0);
      delay_us(12);
   }
}

void generateCarrierLow(void){     //Carrier signal during the Low state
   int a;
   for(a=0;a<28;a++){
      output_bit(PIN_B2, 1);
      delay_us(13);
      output_bit(PIN_B2, 0);
      delay_us(12);
   }
}
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Tue Nov 18, 2008 3:26 am     Reply with quote

Code:
output_bit(PIN_B2, 1);
delay_us(13);
output_bit(PIN_B2, 0);
delay_us(12);

Please note that this will not generate exactly 40kHz. Though delay_us(13) and delay_us(12) add up to 25us, output_bit instruction also take up time. If you look at the assembly listing of the output_bit instruction, you will see the compiler automatically injects direction setting code (movlw, movwf, etc, etc). This can be prevented by using the statement #use fast_io(B), and manually setting the TRISB register. Even after doing this, you will still need to fine tune the delay statements.

Another thing: in the function Create_Bit_Pattern, why don't you use a bit shift? It will generate more compact code.

Code:
for (loop_var=8;loop_var>0;loop_var--)
    {
          if (shift_left(&Output_Byte,1,0))
          {
                 generateCarrierLow();
                 generateCarrierOne();
          }
          else
          {
                 generateCarrierLow();
                 generateCarrierZero();
          }
     }


Rohit
mlkushan



Joined: 16 Nov 2008
Posts: 22
Location: Sri Lanka

View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger

PostPosted: Tue Nov 18, 2008 7:58 pm     Reply with quote

Thanks a lot Rohit for your help,

With the aid of your help. I was able to simplify the above code. So now I have ended up with more compact code and it has been posted below. It works fine in the simulator.

Here also if I uncomment #pragma use fast_io(B) and //#pragma use standard_io(B), This program does not give the required output. Actually after giving an input through the port B5, simulator does not give any output on port B2. So please be kind enough to show me the reason. Is there any mistake which have been done by me in the bellow code segment.

Thank you all and any help regarding my matters is highly appreciated.
Kushan Sharma


Code:

#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES WRT_50%                  //Lower half of Program Memory is Write Protected

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

  #include <math.h>
  #include <stdlib.h>
  #include <string.h>

#define KEY_Bit_C1 178        //1-8 bits of the IR bit pattern
#define KEY_Bit_C2 77         //9-16 bits of the IR bit pattern
#define KEY_Bit_C3 31         //17-24 bits of the IR bit pattern
#define KEY_Bit_C4 224        //25-32 bits of the IR bit pattern
#define KEY_Bit_ON_C5 20      //decimal equivalent of the on signal bits from 33 to 40
#define KEY_Bit_OFF_C3 123    //decimal equivalent of the on signal bits from 17 to 24
#define KEY_Bit_OFF_C5 224    //decimal equivalent of the on signal bits from 33 to 40

void Create_Bit_Pattern(int outputPattern[6]);

#inline
void generateCarrier(void){            //Carrier signal during the High state
      //#pragma use fast_io(B)
      output_bit(PIN_B2, 1);
      delay_us(13);
      output_bit(PIN_B2, 0);
      delay_us(12);
      //#pragma use standard_io(B)
}

void main()
{
   int outputPatternArray[6];  //array to store the pattern structure
   int i; //for the pupose of using within all the for loops
   BYTE Is_AC_ON = 0;
   BYTE Is_AC_OFF = 1;
   BYTE Is_Set_AC_ON = 0;
   
   outputPatternArray[0] = KEY_Bit_C1; //first sixteen bits are same for every bit pattern
   outputPatternArray[1] = KEY_Bit_C2;
     
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   set_tris_b(0x1f);   //set as I/O
   
while(true){
   if(input(PIN_B5) && !Is_Set_AC_ON && !Is_AC_ON){
      Is_Set_AC_ON = 1;
     
      for(i=0;i<168;i++){generateCarrier();}  //this is to create the sync pulse in the bit pattern
      delay_us(4200);
      for(i=0;i<168;i++){generateCarrier();}
     
      outputPatternArray[2] = KEY_Bit_C3;
      outputPatternArray[3] = KEY_Bit_C4;
      outputPatternArray[4] = KEY_Bit_ON_C5;
      outputPatternArray[5] = (255 - KEY_Bit_ON_C5);
   
      Create_Bit_Pattern(outputPatternArray);
      delay_us(700);
      for(i=0;i<168;i++){generateCarrier();}
      Create_Bit_Pattern(outputPatternArray);
     
      Is_AC_ON = 1;
      Is_AC_OFF = 0;
   }
   else if(input(PIN_B5) && Is_Set_AC_ON && Is_AC_ON){
      Is_Set_AC_ON = 0;
     
      for(i=0;i<168;i++){generateCarrier();}  //this is to create the sync pulse in the bit pattern
      delay_us(4200);
      for(i=0;i<168;i++){generateCarrier();}
     
      outputPatternArray[2] = KEY_Bit_OFF_C3;
      outputPatternArray[3] = (255 - KEY_Bit_OFF_C3);
      outputPatternArray[4] = KEY_Bit_OFF_C5;
      outputPatternArray[5] = (255 - KEY_Bit_OFF_C5);
     
      Create_Bit_Pattern(outputPatternArray);
      delay_us(700);
      for(i=0;i<168;i++){generateCarrier();}
      Create_Bit_Pattern(outputPatternArray);
     
      Is_AC_ON = 0;
      Is_AC_OFF = 1;
   }
}
}

//funtion to generate the IR bit patterns
void Create_Bit_Pattern(int outputPattern[6]){
int a;
int b;
int c;
int Output_Byte;

for (a=0;a<6;a++){
   Output_Byte = outputPattern[a]; 
   for (b=8;b>0;b--)
      {
          if (shift_left(&Output_Byte,1,0))
          {
                 delay_us(700);
                 for(c=0;c<56;c++){generateCarrier();}
          }
          else
          {
                 delay_us(700);
                 for(c=0;c<14;c++){generateCarrier();}
          }
      }
   }
}

_________________
Kushan Sharma
mlkushan@gmail.com
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Wed Nov 19, 2008 4:34 am     Reply with quote

In main()
Quote:
set_tris_b(0x1f);
this sets b0, b1, b2, b3, b4 as inputs; and b5, b6, b7 as outputs.

Now, in the next line
Quote:
if(input(PIN_B5)......
this will not work, as pin_b5 is an output.

Rohit
mlkushan



Joined: 16 Nov 2008
Posts: 22
Location: Sri Lanka

View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger

PostPosted: Thu Nov 20, 2008 7:22 pm     Reply with quote

Many thanks to you Rohit,

Now I'm in a correct path. So I was able to create almost 100% accurate 40KHz carrier signal. So now it works fine. The required bit pattern also can be generated without any deviations. But still there are few problems on my circuit designing. Although micro controller gives the accurate bit pattern, modulated signal does not give the correct signal. it gives a delayed signal with small fluctuations. That might be due to the biasing problem of the AND gate transistor which has been used to combine the actual signal and the carrier signal. Also it is needed to have another transistor to drive the IR LED. Soon after finishing those problems I hope my circuitry will work fine.

So thank you very much.
Kushan Sharma
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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