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

Frequency detector in analog signal

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
guy



Joined: 21 Oct 2005
Posts: 297

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

Frequency detector in analog signal
PostPosted: Tue Sep 20, 2016 9:48 pm     Reply with quote

It's hard to define this piece of code. I wrote it to detect repetitive pulses from a light sensor (detect a flashing light) under different ambient light conditions. It assumes the pulse in the analog signal is easily detectable and without other significant frequencies or noise but it doesn't require specific voltages or amplitude. It could be used to detect recurring pulses, measure their frequency, and it also contains an optimized IIR low pass filter which is useful.
Theory of operation:
1. A sample is taken by taking 4 consecutive ADC readings and averaging them.
2. Each sample is fed into an IIR Low Pass Filter in order to establish a baseline, average signal level.
3. Rising and falling edges of pulses are detected by comparing a sample to the average baseline. For example when looking for a rising edge of the pulse, if a sample is 5% higher than the average it is detected.
4. The time between rising and falling edges is measured, allowing for 10% error in timing. After several repetitive pulses are measured the program goes to Detected mode and gives 3 beeps every 30 seconds.


Code:
#include <16F1829.h>
#device ADC=10
#fuses INTRC_IO,NOLVP,PUT,BROWNOUT,BORV25,NOCLKOUT,NOWDT
#use delay(CLOCK=8000000)   // 8MHz

#define   PUSHBUTTON   PIN_B6   // pulled up, low=ON
//#define   BZR         PIN_C3..C7, low=ON


#DEFINE THRES   50   // 50/1024 = rise/fall detection threshold:
               // 5% of full scale above/below average
#DEFINE NUM_PULSES_DETECT   3
#define   PULSE_ACCURACY   0.1   // ס10% pulse accuracy
#define LOOP_TIME   50   // *1ms


void main() {
   int16 smpl;
   int16 lpf;
   int32 tmp;
   int16 riseTmr=0,fallTmr=0;
   int16 prevRiseTmr=0,prevFallTmr=0;
   int16 riseCntr=0,fallCntr=0;
   byte i;
   short startup;
   short roundd;
   short waitRising=1;

   setup_adc(ADC_CLOCK_DIV_16);   // 8MHz
   SETUP_ADC_PORTS(sAN2);         // PIN 17, PIN_A2
   SET_ADC_CHANNEL(2);
   delay_ms(1);
   read_adc();      // dummy read - ignore result
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   PORT_B_PULLUPS(0x40);   // B6 pushbutton pulled up

   output_c(0);   // BZR on
   delay_ms(50);
   output_c(0xFF);   // BZR off

   
   startup=1;
   set_timer1(0);
   
   while(1) {
      smpl=0;
      for(i=0;i<4;i++) {
         delay_ms(1);
         smpl+=read_adc();   // take new sample
      }
      smpl>>=2;   // average 4 samples, then process:
      if(startup) {
         startup=0;
         lpf=smpl;   // initial lpf value for IIR filter
      }
      
      // calc LPF (IIR)
      tmp=lpf;
      tmp<<=5;   // weight of new sample 1/32
      
      tmp-=lpf;
      tmp+=smpl;
      
      roundd=bit_test(tmp,4);
      tmp>>=5;
      if(roundd) tmp++;
      
      if(lpf==tmp) {    // make sure to reach dest. at some point
         if(lpf<smpl) lpf++;
         else if(lpf>smpl) lpf--;
      }
      else lpf=tmp;
      
      // compare new sample to average :
      
      // test for rising edge:
      if(waitRising) {
         if(smpl>lpf+THRES) {
            // rising edge:
            waitRising=0;
            // compare to last rise-to-rise time:
            if((riseTmr>=prevRiseTmr*(1-PULSE_ACCURACY))&&(riseTmr<=prevRiseTmr*(1+PULSE_ACCURACY))) {
               // similar rise-to-rise time:
               if(riseCntr<0xFFFF) riseCntr++;
            }
            else {
               // different rise-to-rise time:
               riseCntr=0;
               fallCntr=0;
            }
            
            // save timer for next round:
            prevRiseTmr=riseTmr;
            riseTmr=0;
         }
      }
      else {   
         // test for falling edge:
         if((lpf>=THRES)&&(smpl<lpf-THRES)) {
            // falling edge:
            waitRising=1;
            // compare to last fall-to-fall time:
            if((fallTmr>=prevFallTmr*(1-PULSE_ACCURACY))&&(fallTmr<=prevFallTmr*(1+PULSE_ACCURACY))) {
               // similar fall-to-fall time:
               if(fallCntr<0xFFFF) fallCntr++;
            }
            else {
               // different fall-to-fall time:
               riseCntr=0;
               fallCntr=0;
            }
            
            // save timer for next round:
            prevFallTmr=fallTmr;
            fallTmr=0;
         }
      }

      // test if enough pulses detected:
      if((riseCntr>=NUM_PULSES_DETECT)&&(fallCntr>=NUM_PULSES_DETECT)) {
         // !!!! CELEBRATE !!!!
         riseCntr=0;
         fallCntr=0;
         goto detected;
      }

      // advance timers:
      riseTmr++;   // allow overflow - it will prevent false similar pulses detected
      fallTmr++;   // allow overflow - it will prevent false similar pulses detected
      while(get_timer1()<(LOOP_TIME*250));
      set_timer1(get_timer1()-(LOOP_TIME*250-3));   // -3 is finetune
   }
   
   /////////////
   
detected:
   smpl=0;
   while(input(PUSHBUTTON)) {
      if(smpl==30000) smpl=0;
      if((smpl==0)||(smpl==200)||(smpl==400)) output_c(0);   // BZR on
      if((smpl==100)||(smpl==300)||(smpl==500)) output_c(0xFF);// BZR off
      smpl++;
      delay_ms(1);
   }
   
   reset_cpu();
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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