Clapper Project with PIC16F688
This is a simple clapper project that can be used to detect audible claps and then be used to do something like turn appliances on and off. It uses a PIC16F688 microcontroller and a couple discrete components. The sensitivity and delays of the clapper can be adjusted to your liking. It might even be worth throwing in a potentiometer or some dip switches to make these changes on the fly. By default, the sensitivity is pretty high in the code below.
On to the source code. It's actually pretty simple. It uses an interrupt based timer and a comparator to analyze the signal coming off of the microphone. The sensitivity is adjusted with different values for VRCON. Check your datasheet here. RC2 is used to indicate that a clap was detected. RC3 is used as the actual on/off output.
/* * Copyright (C) 2016, Joshua Henderson <www.digitalpeer.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <xc.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #define _XTAL_FREQ 8000000 #pragma config FOSC=INTOSCIO, WDTE=OFF, MCLRE=OFF, int time_elapsed; int i; void interrupt ISR(void){ if (PIR1bits.TMR1IF) { i++; if(i == 3) time_elapsed = 1; PIR1bits.TMR1IF = 0; } } int main(int argc, char** argv) { // OSC frequency = 8Mhz IRCF0=1; IRCF1=1; IRCF2=1; //set the SCS bits to select internal oscillator block OSCCONbits.SCS = 1; TRISCbits.TRISC2 = 0; // Output TRISCbits.TRISC3 = 0; // Output ANSELbits.ANS6 = 0; // Digital ANSELbits.ANS7 = 0; // Digital TRISCbits.TRISC1 = 1; // Input ANSELbits.ANS5 = 0; CMCON0 = 0b00100100; //VRCON = 0b10100010; // not-so-sensitive VRCON = 0b10100011; // sensitive while(HTS == 0); // initialize leds off RC2 = 0; RC3 = 0; // test toggle clap led __delay_ms(100); RC2 = 1; __delay_ms(100); RC2 = 0; // enable global interrupts INTCONbits.GIE = 1; // timer1 interrupt INTCONbits.PEIE = 1; // enable timer1 PIR1bits.TMR1IF = 0; PIE1bits.TMR1IE = 1; do { RC2 = 0; TMR1H = 0; TMR1L = 0; time_elapsed = 0; i = 0; T1CON = 0b00110000; if (CMCON0bits.C2OUT) { RC2 = 1; // debounce looking for second clap __delay_ms(80); // wait for second clap T1CONbits.TMR1ON = 1; while(!CMCON0bits.C2OUT && !time_elapsed); if(CMCON0bits.C2OUT && !time_elapsed) RC3 = ~RC3; __delay_ms(100); } } while(1); return 0; }
Here's a reproduction of the breadboard in Fritzing with a relay added on.
Here's what the final board looks like. It's a bit odd shaped because it's meant to slide into a project box vertically.
A similar project using a different microcontroller can be found at Making a simple clap switch.