freakone | projekty

freakone.pl

Klaskacz - dwudrożny włącznik dźwiękowy

Celem projektu było skonstruowanie układu, który będzie umożliwiał zdalne włączanie dowolnego urządzenia podpinanego pod zwykłe gniazdko sieciowe.

Dodatkowymi warunkami były: możliwość obsługi więcej niż jednego urządzenia, możliwość definiowania własnych schematów klaśnięć.

Po krótkim poszukiwaniu znalazłem gotowy układ w ofercie AVT: Kit 721/2. Spełniał on jednak jedynie założenie początkowe - umożliwiał jedynie zdalne włączanie jednego urządzenia przez jedno klaśnięcie.

Swój układ oparłem na wzmacniaczu przedstawionym w w/w kicie (idealnie nadaje się do tego zadania - filtruje niskie częstotliwości), dwóch przekaźnikach S3-5 oraz mikrokontrolerze Atmega 8. Zostały zastosowane 2 stabilizatory napięcia - L7805 zasila atmegę (5V), a LM317 wysterowany rezystorami 380R i 1K8 zespół wzmacniacza (napięcie ok 8.2 V dobrane empirycznie - przy tej wartości wystepują największe skoki na wyjściu podczas klaśnięcia). Wzmacniacz można spokojnie zasilać bezpośrednio z zasilacza, jednak trzeba przy tym zmienić program mikrokontolera. Na wyjściu wzmacniacza przy użytym stabilizatorze występuje napięcie 1.6V, przy głośnym klaśnięciu przekracza 3V.

Atmega jest taktowana wewnętrznym rezonatorem 8MHz. 4 ledy służą debugowi, dzieki nim możemy widzieć jak program rozpoznaje klaski czy inne dźwięki. Przetwornik A/D jest włączony w trybie Free Running - działa bez przerwy - dlatego cały kod umieszony został w przerwaniu od zakończonej konwersji.

Schemat układu
Pliki programu Eagle

Płytki nie projektowałem, gdyż aktualnie nie mam dostępu do wytrawiarki (całość została złożona na płytce prototypowej).

Kod źródłowy dla mikrokontrolera:

#include
#include
#include

#define TAB 4
#define TBI(reg,bit) reg^=1<#define TIME_CLAP 1500
#define TIME_SILENT 200
#define TIME_SILENT_WAIT 300

void adc_init()
{
ADMUX = (1 << REFS0) | (1 << MUX0);
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2) | (1 << ADFR) | (1 << ADSC);
}

void intro()
{
for(int ii = 0; ii < 2; ii++)
for(int i = 0; i < 4; i++)
{
TBI(PORTD, i);
_delay_ms(100);
}

for(int ii = 0; ii < 5; ii++)
{
for(int i = 0; i < 4; i++)
{
TBI(PORTD, i);
}

_delay_ms(100);
}

}

volatile double wynik_old = 100;
volatile double wynik_detect = 0;

volatile int counter = 0;
volatile int wait, wait2, wait3 = 0;

SIGNAL (SIG_ADC)
{
double wynik = (ADCL | (ADCH << 8));
wynik = (wynik * 4.95) / 1024;

if(counter % 2 == 0)
{
if(wynik > wynik_old * 1.4)
{
counter++;
wynik_detect = wynik;
}
else
{
wait++;
}
}
else
{
if(wynik * 1.3 < wynik_detect)
{
if(++wait2 > TIME_SILENT)
{
counter++;
wait2 = 0;
}
}
else
{
wait3++;
}

}

wynik_old = wynik;

if(wait > TIME_CLAP || wait3 > TIME_SILENT_WAIT)
{
if(counter > 5)
{
TBI(PORTD, 7);
_delay_ms(200);
}
else if (counter > 3)
{
TBI(PORTD, 6);
_delay_ms(200);
}
counter = 0;
wait = 0;
wait3 = 0;
PORTD |= 0b00001111;
}

if(counter < 4)
PORTD &= ~(1 << counter);
else if(counter < 8)
PORTD |= (1 << (counter-4));
}



int main()
{
DDRD = 0xff;
PORTD = 0;

intro();
adc_init();
sei();

while(1)
{
}
}