Project name: Slapme
Short description
The main idea of the project is to make a sensor capable of detecting audio spikes, such that it can be used for triggering certain electronics (e.g. TVs, lighting …)
The theory behind this is quite simple, we get a small electret microphone (in this case salvaged from a mobile phone found under my bed) and run the signal through a pre-amp. This signal is fed into an ADC channel on the MCU. Because this particular mic seems to show adaptive features, the levels of triggering (on a scale of 0..1024) are below 100 and above 900. These are subject to change because of the sensitivity to background noise.
The level of noise detected is shown on a series of LEDs tied to PORTC.
On detection, the led animation will stop or restart (based on its current state).
Schematics
Pictures
Front side:
Back side:
And whole system:
Part list
(Rest of the parts are included in the main board and will not be listed here)
Code
#include <stdio.h> #include <avr\io.h> #include <avr\interrupt.h> #include <avr\delay.h> int uart_putchar(char c, FILE *unused); int uart_getchar(FILE* f); FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); FILE mystdin = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ); int val; char paused = 0; int debounce_ctr = 0; int ADC_get(uint8_t channel) { ADMUX = (1<<REFS0); ADMUX |= channel; ADCSRA |= (1<<ADSC); loop_until_bit_is_set(ADCSRA, ADIF); return ADC; } void ADC_init(void) { ADMUX = (1<<REFS0); ADCSRA = (1<<ADEN) | (1<<ADATE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); } void USART_init(void) { UCSRB = (1<<RXEN) | (1<<TXEN); UCSRC = (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1); UBRRL = 103; } void Timer1_init(void) { OCR1A = 1000; TCCR1A = 0; TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10); TIMSK |= _BV(OCIE1A); } SIGNAL(SIG_OUTPUT_COMPARE1A) { uint8_t i; val = ADC_get(0); val -= 900; //experimental noise level if(val < 0) val = 0; val = (int)((float)val/0.121f); // linear adjust printf("\n%4d ", val); // at each clap (or noise spike), the leds pause if (!paused) { // this should be log if (val > 0) PORTC |= 0x01; else PORTC &= ~0x01; if (val > 128) PORTC |= 0x02; else PORTC &= ~0x02; if (val > 256) PORTC |= 0x04; else PORTC &= ~0x04; if (val > 384) PORTC |= 0x08; else PORTC &= ~0x08; if (val > 512) PORTC |= 0x10; else PORTC &= ~0x10; if (val > 640) PORTC |= 0x20; else PORTC &= ~0x20; if (val > 768) PORTC |= 0x40; else PORTC &= ~0x40; if (val > 896) PORTC |= 0x80; else PORTC &= ~0x80; } if (val < 100 || val > 900) { if (debounce_ctr < 0) { paused ^= 1; printf("claps claps\n"); // need to debounce a bit because the mic is adaptive debounce_ctr = 30; } } debounce_ctr --; } int main(void) { uint8_t key; uint8_t val = 1; long i; USART_init(); stdin = &mystdin; stdout = &mystdout; cli(); ADC_init(); Timer1_init(); DDRC = 0xFF; sei(); while(1); return 0; } int uart_putchar(char c, FILE *unused) { if (c == '\n') uart_putchar('\r', 0); loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return 0; } int uart_getchar(FILE* f) { char c; loop_until_bit_is_set(UCSRA, RXC); c = UDR; if(c=='\r') c='\n'; uart_putchar(c,NULL); return c; }
Final results
Although the fact that the opamp is not powered differentially, the output should not suffer side-effects like a sudden cutoff due to the fact that the levels were linearly adjusted in code. On further develpment, a series of relays could be attached to an external power supply (12V for Omron relays) and using some MOSFETs one could use this for any house-hold appliance.