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

  • 8 x LED
  • 8 x resistor 330R [smd]
  • 3 x resistor 10K
  • 1 x resistor 1K
  • 2 x resistor 1M (can be replaced by 1M linear pot)
  • 1 x Dual opamp LM358 (only one used)
  • 1 x 4.7uF [smd]
  • 1 x 0.1uF [smd]
  • 1 x electret mic

(Rest of the parts are included in the main board and will not be listed here)

Code

main.c
#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.

pm/prj2011/dloghin/slapme.txt · Last modified: 2021/04/14 17:07 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0