
Coś efektowniejszego przeważnie kosztuje troche więcej, a sterownik przeważnie nie jest przystosowany do pracy na "świeżym powietrzu".
Mam dosyć dużą choinkę przed domem, postanowiłem ją udekorować. Skoro chińczycy mogą robić mrygające lampki - czemu my nie możemy?
Z powodu braku czasu i małej liczby elementów urządzenie zostało zmontowane na płytce uniwersalnej, no i niestety nie powstała jeszcze obudowa.
Pomysł:
W jak najprostszy sposób płynnie zapalać i gasić trzy łańcuchy lampek.
Realizacja:
Mikrokontroler ATMEGA8, trzy optotriaki MOC3021, trzy triaki BT-600.
Aby płynnie sterować jasnością świecenia żarówek niezbędne jest sterowanie fazowe.
W skrócie:
sterujemy triakiem, zasilamy go prądem przemiennym. Jeśli włączymy triak, będzie on załączony (niezależnie od stanu na elektrodzie sterującej) do momentu przejścia prądu przez zero. Także jedyną możliwością jest sterowanie momentem (kątem) włączenia triaka. Inaczej mówiąc czekamy aż prąd przejdzie przez zero (bo wcześniej tyrystor - jeśli był włączony to dalej jest) i od tego momentu odliczamy czas zależny od tego na jaką część półokresu chcemy włączyć triak.

Zatem aby posterować takim triakiem niezbędna jest informacja kiedy prąd przeszedł przez zero. Ponieważ żarówka jest obciążeniem o charakterze rezystancyjnym, prąd jest w fazie z napięciem. Zatem badając przebieg napiecia możemy jednoznacznie powiedzieć od kiedy należy liczyć wspomniany wcześniej czas.
Układ zasilam z ładowarki od Nokii (tej transformatorowej). Ponieważ w środku nie ma żandego kondziołka, można bezpośrednio za pomocą napięcia z niej posterować tranzystorem od synchronizacji. Sygnał z kolektora podaje na wejście INT0 Atmegi (która ma ustawione przerwanie przy opadającym zboczu sygnału). Reszta układu jest zasilana z tego samego mostka. Ponieważ np 7805 wymaga jakiegoś kondensatora na wejściu (wygładzenia napięcia) odseparowałem reszte układu od napięcia wyprostowanego dwupołówkowo (niezbędnego do synchronizacji) za pomocą diody prostowniczej.

Na wyjściu aby uzyskać separację galwaniczną zastosowałem takie rozwiązanie:

Aby uzyskać odpowiedni prąd wyzwalania optotriaka R8 = 330ohm.
Całość zabezpieczona bezpiecznikiem 2A. Triaki dostały wspólny radiator. Jest dużo za duży, ale taki miałem pod ręką. Układ zabezpieczyłem wyłącznikiem różnicowo prądowym 30mA (na wszelki wypadek).
Dodatkowo na wyjściach podłączyłem diody LED przydatne podczas uruchamiania układu.
Program:
Program sterujący urządzeniem jest stosunkowo prosty. W momencie wykrycia opadającego zbocza wyzwalane jest przerwanie. Kod w przerwaniu odlicza odpowiedni czas i załącza wyjście uP (a więc i optotriak...)
W opisywanym przypadku steruje trzema wyjściami. Nie widze jednak przeciwwskazań, żeby zrobić układ sterujący n wyjściami. Wystarczy pokopiować blok odpowiedzialny za sterowanie danym wyjściem (// Obsluga X lancucha w programie). Listning programu pod spodem
Zdjęcia układu:



Film pokazujący jak działają lampki

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
long int LANCUCH1=500; // okresla jasnosc swiecenia 1 lancucha
long int LANCUCH2=4432; // okresla jasnosc swiecenia 2 lancucha
long int LANCUCH3=4432; // okresla jasnosc swiecenia 3 lancucha
int licznik=0;
int wyjdz=0; // zmienna pomocnicza do petli w przerwaniu
int wyjdz1=0;
int wyjdz2=0;
int wyjdz3=0;
int kierunek1=1; // okresla zmiane jasnosci (jasniej / ciemniej) 1 lancucha
int kierunek2=1; // okresla zmiane jasnosci (jasniej / ciemniej) 1 lancucha
int kierunek3=-1; // okresla zmiane jasnosci (jasniej / ciemniej) 1 lancucha
int predkoscA=150; //okresla predkosc zmian jasnosci w pierwszym zakresie
int predkoscB=15; //okresla predkosc zmian jasnosci w drugim zakresie
int predkoscC=5; //okresla predkosc zmian jasnosci w trzecim zakresie
#define LAN1ON sbi(DDRB,PB1); sbi(PORTB,PB1); //makro wlacz lancuch pierwszy
#define LAN1OFF sbi(DDRB,PB1); cbi(PORTB,PB1); //makro wylacz lancuch pierwszy
#define LAN2ON sbi(DDRB,PB2); sbi(PORTB,PB2);
#define LAN2OFF sbi(DDRB,PB2); cbi(PORTB,PB2);
#define LAN3ON sbi(DDRB,PB3); sbi(PORTB,PB3);
#define LAN3OFF sbi(DDRB,PB3); cbi(PORTB,PB3);
SIGNAL (SIG_INTERRUPT0)
{
TCNT1=0; //wyzeruj licznik
do
{
// Obsluga 1 lancucha
if(TCNT1>=LANCUCH1&&wyjdz1==0) //jesli timer naliczy tyle zeby wlaczyc lancuch
{
LAN1ON; //wlacz diode
wyjdz1=1;//wyjdz (dioda wlaczona, wiec mozna stad uciec)
//kod oblicza po jakim czasie ma zostac wlaczona dioda
//poniewaz jasnosc swiecenia zalezy od kwadratu napiecia
//a my chcemy zmieniac jasnosc, zalozono pewna aproksymacje krzywej nieliniowej
//za pomoca trzech prostych o roznych nachyleniach (predkoscX)
//zmienna kierunek okresla w ktora strone bedziemy sie poruszac po krzywej
if(LANCUCH1<=500) kierunek1 = 1;
if(LANCUCH1>=7150) kierunek1 = -1;
if(LANCUCH1>=0 && LANCUCH1<1000) {LANCUCH1=LANCUCH1+predkoscA*kierunek1;}
if(LANCUCH1>=1000 && LANCUCH1<5000) {LANCUCH1=LANCUCH1+predkoscB*kierunek1;}
if(LANCUCH1>=5000 && LANCUCH1<10000) {LANCUCH1=LANCUCH1+predkoscC*kierunek1;}
}
// Obsluga 2 lancucha
if(TCNT1>=LANCUCH2&&wyjdz2==0) //jesli timer naliczy tyle zeby wlaczyc lancuch
{
LAN2ON; //wlacz diode
wyjdz2=1;//wyjdz (dioda wlaczona, wiec mozna stad uciec)
//kod oblicza po jakim czasie ma zostac wlaczona dioda
//poniewaz jasnosc swiecenia zalezy od kwadratu napiecia
//a my chcemy zmieniac jasnosc, zalozono pewna aproksymacje krzywej nieliniowej
//za pomoca trzech prostych o roznych nachyleniach (predkoscX)
//zmienna kierunek okresla w ktora strone bedziemy sie poruszac po krzywej
if(LANCUCH2<=500) kierunek2 = 1;
if(LANCUCH2>=7150) kierunek2 = -1;
if(LANCUCH2>=0 && LANCUCH2<1000) {LANCUCH2=LANCUCH2+predkoscA*kierunek2;}
if(LANCUCH2>=1000 && LANCUCH2<5000) {LANCUCH2=LANCUCH2+predkoscB*kierunek2;}
if(LANCUCH2>=5000 && LANCUCH2<10000) {LANCUCH2=LANCUCH2+predkoscC*kierunek2;}
}
// Obsluga 3 lancucha
if(TCNT1>=LANCUCH3&&wyjdz3==0) //jesli timer naliczy tyle zeby wlaczyc lancuch
{
LAN3ON; //wlacz diode
wyjdz3=1;//wyjdz (dioda wlaczona, wiec mozna stad uciec)
//kod oblicza po jakim czasie ma zostac wlaczona dioda
//poniewaz jasnosc swiecenia zalezy od kwadratu napiecia
//a my chcemy zmieniac jasnosc, zalozono pewna aproksymacje krzywej nieliniowej
//za pomoca trzech prostych o roznych nachyleniach (predkoscX)
//zmienna kierunek okresla w ktora strone bedziemy sie poruszac po krzywej
if(LANCUCH3<=500) kierunek3 = 1;
if(LANCUCH3>=7150) kierunek3 = -1;
if(LANCUCH3>=0 && LANCUCH3<1000) {LANCUCH3=LANCUCH3+predkoscA*kierunek3;}
if(LANCUCH3>=1000 && LANCUCH3<5000) {LANCUCH3=LANCUCH3+predkoscB*kierunek3;}
if(LANCUCH3>=5000 && LANCUCH3<10000) {LANCUCH3=LANCUCH3+predkoscC*kierunek3;}
}
//zabezpieczenie na wypadek przekroczenia zakresu
if(TCNT1>=7200) {wyjdz=1;}
if(wyjdz1==1 && wyjdz2==1 && wyjdz3==1) wyjdz=1; //jesli wszystkie lancuchy zostana obsluzone, uciekamy
}
while(wyjdz==0);
//Przygotowanie zmiennych do obslugi nastepnego przerwania
wyjdz=0;
wyjdz1=0;
wyjdz2=0;
wyjdz3=0;
//Sterujemy triakami, wiec wyjscia mozna wylaczyc, bo i tak triak wylaczy sie przy przejsciu pradu przez 0
LAN1OFF;
LAN2OFF;
LAN3OFF;
}
int main()
{
// Definicje do timera
TCNT1 = 0xFF00; // wartość początkowa T/C1
TCCR1A = 0x00; // włącz tryb czasomierza T/C1
TCCR1B = _BV(CS10);// preskaler clk
//Deklaracja zmiennych i stalych
GIMSK = _BV(INT0); //włącz obsługę przerwań Int0
MCUCR = _BV(ISC01); // włącz generowanie przerwań przez
// opadające zbocze na Int0
sei(); // włącz obsługę przerwań
while(1)
{
}
return 0;
}
Cool? Ranking DIY