niedziela, 20 marca 2011

DIY: Sterownik oświetlenia w drzwiach (ATtiny13)


Autor: Tomek
Redakcja: Dondu

Sterownik oświetlenia na ATtiny13

Mówi się, że „Potrzeba matką wynalazku, a lenistwo ojcem”. Mój projekt z pewnością nie powstał z potrzeby, ale raczej z wygody. Jest to czujnik oświetlenia, który automatycznie zapala oświetlenie w pokoju, gdy ktoś do niego wejdzie.

Rozwiązanie w sumie jest bardzo proste, choć wymaga nieco pracy w zakresie podłączenia do instalacji oświetleniowej oraz zamontowania czujników. De facto ta część jest najtrudniejsza, gdy chce się to wykonać w sposób estetyczny. Ja na razie poszedłem w kierunku eksperymentu stąd estetyka nie była dla mnie na tym etapie istotna :-)






Sterownik oświetlenia w obudowie


Zasada działania

Projekt został oparty o mikrokontroler ATtiny13 oraz kilka optoelementów i przekaźnik 12V/230V. Idea i zasada działania polega na wykrywaniu przy pomocy fal podczerwonych tego, czy ktoś wchodzi, bądź wychodzi z pomieszczenia.

Układ zlicza ilość osób wchodzących do pokoju. Jeśli do pomieszczenia wejdą trzy osoby, to światło zostanie zgaszone za trzecią, ale po z góry ustalonej zwłoce. Osobiście zdarza mi się wychodzić z pokoju na dosłownie ”sekundę” i wracać, więc taka funkcjonalność na pewno w moim przypadku się przyda.


Rozmieszczenie diod i fototranzystorów w futrynie drzwi.


Gdy światło podczerwone emitowane przez diody IR pada bez przeszkód na fototranzystory, mikrokontroler wie, że nic ani nikt nie stoi w tym miejscu. Dopiero w zależności od tego, z którego kierunku ktoś nadchodzi światło zostaje włączone, bądź wyłączone.

Kierunek jest ustalany na podstawie kolejności w jakiej wiązki były przerywane.
Zasada działania bajecznie prosta, zatem przejdźmy do konkretów, a właściwie do hardware’u.


Hardware

Najważniejsze, oprócz mózgu (mikrokontrolera) w tym projekcie było to, jak zbudować układ, który by potrafił odróżnić czy ktoś stoi w danym miejscu (między diodą IR, a czujnikiem), czy też nie. Zastosowałem w projekcie, z oczywistych względów ;), pasmo podczerwone, na które oko ludzkie jest niewrażliwe. Dzięki temu, w niewidoczny dla człowieka sposób, jesteśmy w stanie kontrolować czy ktoś przecina wiązki IR. Metodą wielu, wielu, prób i błędów, eksperymentalnie dobrałem odpowiednie wartości rezystorów w szeregu z fototranzystorami tak, aby w miarę precyzyjnie reagowały one zmianą stanu na wejściu mikrokontrolera tylko na to pasmo podczerwone.


Przykładowa charakterystyka fototranzystora


Ja widać z grafiki charakterystyka fototranzystora nie jest idealna. Charakteryzuje się on co prawda największą czułością w paśmie do którego jest przeznaczona, jednak reaguje on na wszystkie inne, widzialne również pasma, co zaobserwowałem podczas testów. Dlatego dobranie rezystora w szereg z fototranzystorem było takie ważne, dzięki temu nie reaguje on na żarówki w przedpokoju, w którym zostały one zamontowane.

Wykorzystałem diody i fototranzystory jednego producenta i o takim samym paśmie działania, aby uzyskać maksymalnie dużą czułość przy możliwie niewielkim nakładzie pracy. Oczywiście nic nie stoi na przeszkodzie, aby użyć innych diod, bądź fototranzystorów. Dla przykładu powiem, że w pierwotnej wersji, w której rezystor szeregowy z fototranzystorem był dobrany nie najlepiej, oświetlenie w przedpokoju zakłócało dosyć mocno działanie.


Schematy

Schemat układu



Schemat czujników



Schemat modułu przekaźnika
z diodą eliminującą zakłócenia


Na schemacie oprócz mikrokontrolera widać również stabilizator liniowy 7805 (regulator napięcia), na którego wejściu podłączono +12V. Aby zapewnić dobre i stabilne zasilanie dodałem kilka kondensatorów elektrolitycznych w obwodzie stabilizatora, które są wymagane, więcej szczegółów w notach katalogowych. Jak widać znalazło się również miejsce dla kilku kondensatorów odsprzęgających 100nF.

Dlaczego układ zasilany jest z zasilacza wtyczkowego 12-woltowego, skoro i tak jest ono utrzymywane na poziomie +5V? Wymaga tego przekaźnik NT73-2CS12-24, do którego wysterowania potrzebne jest +12V. Jest on sterowany pośrednio, gdyż przez tranzystor mosfet BS170. Mimo, że jest on w obudowie TO-92 prąd drenu jest wielokrotnie większy od tego jaki potrzebujemy. Zmierzyłem, że przy zasilaniu 12V przekaźnik pobiera niecałe 30mA i również spadek napięcia jest na nim niewielki, więc z tranzystor starczy z dużym zapasem i nie wymaga chłodzenia, w przeciwieństwie do stabilizatora, ale o tym nieco później.

W układzie znajduje się również dioda sygnalizacyjna LED, microswitch, rezystor 4k7 podciągający do resetu ATtiny o raz wtyki do podłączenia czujników (fototranzystorów).

Wracając do fototranzystorów, zajmijmy się teraz nimi pod kątem sterowania. Wejścia czujników są podciągnięcie do zasilania. Gdy na fototranzystor pada podczerwień wzmacnia on ów sygnał świetlny co powoduje spadek napięcia na wejściu mikrokontrolera i powoduje interpretację sygnału jako „0”. Natomiast gdy wiązka IR zostaje przerwana, na wejściu jest „1”.

Bardzo „pomocną” sprawą są tutaj przerzutniki Schmitta na pinach wejściowych mikrokontrolera, dzięki którym stan na wejściu nie waha się, a z pewną histerezą przełącza stan. W artykule z powyższego linku dostępny jest film prezentujący zachowanie się przerzutników Schmitta na wejściach układu.




Płytki PCB

Płytki pod diody i fototranzystory wykonałem specjalnie nieco większe niż trzeba, aby w przyszłości ułatwić nieco montaż pod boazerią/na ścianie.


PCB z nadajnikiem i odbiornikiem 1


PCB z nadajnikiem i odbiornikiem 2


Płytka z mikrokontrolerem wyszła nie najgorsza. Docelowe wymiary miały być takie, aby zmieściła się do obudowy, którą miałem.


PCB z mikrokontrolerem


PCB dostępne do ściągnięcia na dole strony.



Wykaz elementów:
  • ATtiny13A-PU
  • przekaźnik nt73-2cs12-5
  • 2 diody L-53F3BT
  • 2 fototranzystory L-53P3BT
  • rezystory 1x 4k7, 2x 20k, 2x 75R, 1x 1K, 1x 240R
  • kondensatory 1x 220uF, 1x 100uF, 3x 100nF
  • 5 gniazd 2 pinowych
  • 5 wtyków 2 pinowych
  • 1 gniazdo do zasilacza
  • zasilacz gniazdkowy 12V
  • stabilizator 7805
  • tranzystor BS170
  • trochę przewodów ze skrętki
  • microswitch niski
  • dioda LED czerwona 3mm
  • podstawka DIP8
  • obudowa z odzysku
  • laminat + wytrawiacz

Software

Konstrukcja programu jest klasyczna, można rzec. W pierwotnej wersji chciałem oprzeć działanie na przerwaniach zewnętrznych, które wybudzałyby układ przy przerywaniu wiązek podczerwieni. Zmieniłem po drodze zdanie i napisałem program w inny sposób, z tego względu, że nie ma tutaj żadnych wymagań, oczywiście w granicach rozsądku, co do zasilania tak więc nie ma potrzeby usypiania układu.

LINK do kodu, aby móc kod przejrzeć w edytorze. Umieściłem dosyć szerokie komentarze, które nie wyglądają dobrze w przeglądarce.

/*
 * sterownik_oswietlenia.c
 *
 * Created: 2014-02-21 01:48:18
 *  Author: Tomek
 * Konkurs: ferie 2014
 */ 

#define F_CPU 1000000L //zdefiniowanie prędkości taktowania procesora
#include <stdio.h>  // dołączenie potrzebnych bibliotek
#include <avr/io.h>
#include <util/delay.h>


#define PRZ (1<<PB0)  // makrodefinicja przełącznika
#define PRZ_ON PORTB &=~PRZ
#define PRZ_OFF PORTB |=PRZ

#define LED (1<<PB1)  // makrodefinicja diody LED
#define LED_ON PORTB |=LED
#define LED_OFF PORTB &=~LED

int przerwano_1(void);  // prototypy funkcji, ktorych kod widać na końcu
int przerwano_2(void);                
int ustaw_przekaznik(int);                      

int N=1; // inicjalizacja zmiennej globalnej odpowiedzialnej za zliczanie osob, które wchodzą do 
   // na starcie światło się włącza, więc zakładam, że w pomieszczeniu jest 1 osoba
  
int l;  // zmienna odpowiedzialna za odliczanie wielokrotnosci 10ms, aby swiatlo nie gaslo zaraz po wyjściu
int const CZAS_ZWLOKI = 10*100; // stała odpowiedzialna za ustawienie czasu zwloki wylaczenia swiatla, np 30sekund*100;
   
   
int main(void)
{
 DDRB|=(1<<PB0)|(1<<PB1); // wyjścia LED i przekaźnika
 PORTB|=(1<<PB3)|(1<<PB4); // czujniki
 PORTB|=(1<<PB2);   // przycisk
 

 LED_ON; _delay_ms(100); LED_OFF; _delay_ms(100); // mignięcie diodą na powitanie :)
 LED_ON; _delay_ms(100); LED_OFF;
 
    while(1)
    {
  if (!(PINB & 0b100)) {  // gdy zostanie wciśnięty przycisk
   _delay_ms(50);   // oczekiwanie 50ms na ustabilizowanie się drgań styków
   if (!(PINB & 0b100)) {
    N= (N<=0) ? 1 : 0; // gdy N<=0 to wtedy przypisz 0 do N
   }
   LED_ON;
   _delay_ms(400); // oczekiwanie 400ms po to, aby przypadkiem za 1 dotknięciem nie spowodować kilku przełączeń światła
   LED_OFF;  // przy okazji miga diodą, aby zasygnalizować, że "chwycił"
  }
  
  if (przerwano_1() && !przerwano_2()) {  // gdy ktoś wychodzi z pokoju
   while (przerwano_1()) {     // gdy przerwano 1 wiązkę
    while (przerwano_2()) {    // następnie gdy przerwano drugą wiązkę
      if (!przerwano_1()) {  // oraz finalnie gdy 1 wiązka "odzyskała widoczność"
        LED_ON;
        if (N==1) {   // jesli wychodzi ostatnia osoba z pokoju
          while (!przerwano_1()) { // jesli wroci za mniej niz czas zwloki to swiatlo niezgasnie
           l++;     // odliczanie wielokrotnosci 10ms
           if (l >= CZAS_ZWLOKI) { // a jesli przyjdzie pozniej to zgasnie 
            N--;
            break;
           }
           _delay_ms(10); // odczekaj 10ms 
          }
        } else {
          N--;  // jesli w pokoju została conajmniej jedna osoba to wtedy odejmij
        }
        LED_OFF;
        break;     // dekrementuj N oraz przerwij while(przerwano_2())
      }
    }
   }
  }
  else if (przerwano_2() && !przerwano_1()) { // analogicznie do wychodzenia z pokoju
   while (przerwano_2()) {     // przerwano 2 wiązkę
    while (przerwano_1()) {    // przerwano 1 wiązkę
      if (!przerwano_2()){  // wiązka 2 "odzyskała widoczność"
       N++;
       break;     // zwiększ licznik osób oraz przerwij while(przerwano_1())
      }       
    }
   }
  }
  N=ustaw_przekaznik(N);  // ustawianie przekaznika, szczegoly w linijce 79
  l=0;     // ustaw zmienna zliczajaca, patrz linia 60
    }
}

int ustaw_przekaznik(int k) { // funkcja odpowiedzialna za sterowanie przekaźnikiem
 if (k<=0) {     // w przypadku pomyłki i naliczenia ujemnej liczby osób w pokoju
  k=0;     // kod koryguje to i ustawia N=0, tzn zwraca
  PRZ_OFF;
 } else {     // gdy liczba osób w pokoju większa od 0 to zapal światło
  PRZ_ON;
 }
 return k;     // zwróć ilość osób w pokoju do zmiennej N
}

int przerwano_1(void) {    // sprawdzanie wiązki 1 tzn na PB3
 return (PINB & 0b1000) ? 1 : 0; // jeśli wiązka jest przerwana zwróć 1, w przeciwnym wypadku 0
}

int przerwano_2(void) {    // sprawdzanie wiązki 2 tzn na PB4, analogicznie do przerwano_1()
 return (PINB & 0b10000) ? 1 : 0;
}
Kod dosyć krótki, komentarze wyczerpują zdecydowanie temat.



Wykonanie

Trawienie rozpocząłem od płytek mniejszych, czyli podstawek pod diody IR i fototranzystory. Poniżej na zdjęciu widzimy wytrawione 4 moduły przed rozcięciem na 4. Jak na pierwsze trawienie - spoko ;).


Na pierwszy ogień płytki nadajników i odbiorników

Świeżo wytrawione PCB :-)

Jest to mój pierwszy projekt DIY, który wygląda ambitniej niż składak „na pająka” lub improwizacja na płytce uniwersalnej ;). Konkurs ten był impulsem dla mnie, aby zrobić coś nieco bardziej profesjonalnie i specjalnie dlatego własnoręcznie wytrawiłem PCB. Jedyna metoda jaką byłem wstanie to zrobić była metoda termotransferowa, może nie wygląda zabójczo dobrze, ale ja z pewnością jestem z tych płytek dumny.


Naniesione opisy, również termotransferem

Procesor umieściłem w podstawce DIP-8, aby móc w razie potrzeby go wyciągnąć i móc przeprogramować. Nie widzę potrzeby montowania złącza KANDA do programowania układu zwłaszcza, że ma być to mała płytka.


Uzbrojone PCB

Podłączenie przekaźnika

Nie lada problem miałem z podłączeniem przekaźnika, po długim dumaniu nad tematem uznałem, że najbezpieczniej będzie nie wyprowadzać 230V z puszki włącznika światła, toteż przekaźnik umieściłem za przełącznikiem, w puszce w ścianie. Zdecydowałem, że rozsądnie będzie układ podłączyć w szereg z włącznikiem, aby móc np. w dzień wyłączyć całkowicie światło w prosty sposób, tj. włącznikiem, a wieczorem go włączyć i resztę roboty zostawić mojemu wynalazkowi.



Przekaźnik w koszulce zabezpieczającej


Troszkę koszulka zabezpieczająca się źle zgrzała, ale najważniejsze czyli styki osłania i zabezpiecza przed zwarciem.

Należy zwrócić uwagę, aby tak podłączyć przekaźniki i włączniki tak, aby rozłączały FAZĘ, a nie ZERO!!!.

Jest to bardzo ważne, bo w przeciwnym wypadku przy wyłączonym świetle urządzenie, żarówka bądź cokolwiek innego nadal będzie pod napięciem 230V.


Należy mieć na uwadze, że przekaźnik zawiera cewkę, która jest induktorem i aby zabezpieczyć mikrokontroler, a w moim przypadku mosfet sterujący, należy zastosować między stykami cewki przekaźnika diodę, ja zastosowałem szybką 1N4148, która skutecznie zabezpieczy układ przed impulsami wysokiego napięcia pochodzącego ze zgromadzonej w cewce energii.

W takich częstotliwościach jakie występują w moim układzie egzamin zda każda dioda, nawet popularna prostownicza 1N4007, której parametry, pojemność złączowa, czas przełączania będą wystarczające przy częstotliwościach rzędu setek Hz.


Napięcie 230V jest niebezpieczne dla życia. Przy takich pracach należy posiadać odpowiednie uprawnienia oraz zachować ostrożność.



Zasilanie i bilans mocy

Układ jest zasilany z zasilacza wtyczkowego zapewniającego 12V i prąd maksymalny 800mA. Cały układ łącznie z peryferiami szczytowo pobiera 130mA. Wydaje się sporo, bilans w przybliżeniu wygląda następująco.

Najwięcej prądu „pożerają” diody IR, ich maksymalny prąd wynosi aż 50mA, dopasowane rezystory limitują ten prąd do wartości około 80mA na 2 diody, co jest bezpieczną wartością i gwarantuje długą pracę.

Kolejnym największym „pożeraczem” jest przekaźnik, który co prawda pobiera prąd tylko przy wyłączonym świetle, ale pobiera aż 30mA. Na ostatnim miejscu, mózg operacji, ATtiny, którego pobór jest znikomy.

Należy również uwzględnić straty na stabilizatorze, który podczas działania odczuwalnie się nagrzewa do maksymalnie zmierzonych 50°C w zamkniętej obudowie. Prąd przez niego płynący to około 100mA (130mA pomniejszony o 30mA przekaźnika). Wydziela się więc na nim szczytowo około:




Jest to na tyle duża wartość, że warto zastosować mały radiator w postaci zwykłego kawałka blachy, bądź tak jak w moim mały radiator z pamięci BGA.

Warto wspomnieć o trochę prowizorycznym rozwiązaniu przycisku na obudowie, niestety nie zdobyłem w rozsądnym czasie tak wysokich microswitch’y, o ile istnieją aż tak wysokie, więc rozwiązałem problem małym plastikowym patyczkiem, który Kropelką przykleiłem.

Całość umieściłem w obudowie po zasilaczu zewnętrznym, wymiary płytki dopasowałem aby pasowała ładnie do obudowy. Układ u mnie pracuje już zmontowany od tygodnia i nie przegrzewa się, i pracuje stabilnie.


Do pobrania

Schematy i PCB w Eagle oraz kod źródłowy programu: Sterownik_oswietlenia_Tomek.zip (kopia)




Ewentualne poprawki i uwagi

Obecność przycisku i diody daje pewne pole manewru co do kilku drobnych funkcjonalności, które w przyszłości można zastosować.

Układ, który zbudowałem chciałbym zamontować w sposób niewidoczny, niestety nie miałem jeszcze możliwości zamontować czujników pod boazerią, więc czujniki są naklejone na boazerii co wygląda dosyć nieestetycznie. Mam nadzieję, że zostanie mi to wybaczone i nie „znikną” punkty za wykonanie :-)


Podsumowanie

Zasadniczo jestem zadowolony z projektu, mimo że nie jest idealnie wykonany. Do wad estetycznych można zaliczyć montaż czujników, który w obecnym czasie nie mógł zostać inaczej wykonany, oraz ten nieszczęsny microswitch, ale obecna prowizorka sprawuje się dobrze, więc źle nie jest.

Zanim wymyśliłem całą ideę tego czujnika, chciałem ambitnie podejść i zbudować czujnik z ekranem na HD44780, ale uznałem, że to byłoby tak ekstrawaganckie rozwiązanie, że aż niepraktyczne i pozbawione sensu. Na co komu ekran LCD w czujniku oświetlenia??? Sądzę, że w dobry sposób wykorzystałem możliwości ATtiny 13, projekt z końcowego założenia miał być prosty jak………. włącznik światła, co chyba mi się udało.

Obecny sterownik oświetlenia potrafi to co powinien umieć i mam nadzieję, że jeśli wykonanie i kod Was nie porwały to chociaż sama idea to uczyniła.

Cieszę się, że wyrobiłem się w czasie i mogłem zaprezentować mój pierwszy sensowny projekt DIY i mam nadzieję, że wstydu sobie nie przyniosłem. Sądzę, że jest to dobry przykład w jaki sposób można wykorzystać optoelementy i DIY z nimi staną się popularniejsze.

Pozdrawiam,
Tomek


Źródła 




8 komentarzy:

  1. Proszę popracować nad dźwiękiem w filmikach i grafiką. Rozumiem, że najważniejszą częścią są artykuły, nie design, lecz niektóre filmiki niemiło się ogląda.

    OdpowiedzUsuń
  2. Jak wykonałeś napis na PCB (chodzi o Twój podpis), bo nie mam pojęcia jak to zrobić a chciałbym nanieść własny tekst na płytkę.

    OdpowiedzUsuń
  3. Wszystko wykonywałem metodą termotransferu. Podpis został naniesiony razem ze ścieżkami a następnie wytrawiony. :)

    OdpowiedzUsuń
  4. Małe usprawiedliwienie: używanie _delay_ms zdecydowanie nie jest optymalną opcją na eliminację drgań styków, ale tutaj "zablokowanie" mikrokontrolera na chwilkę nie jest problematyczne.

    OdpowiedzUsuń
  5. Czy ktoś mi może pomóc i powiedzieć czemu po zmontowaniu i zaprogramowaniu tego sterownika układ zlicza osoby wychodzące a nie wchodzące? Światło zapala się jeśli wejdzie liczba osób taka sama jak wyszła a zapalenie światła następuje ze zwłoką która jest ujęta w programie. Programowanie nie jest moją mocną stroną.

    OdpowiedzUsuń
  6. Ten komentarz został usunięty przez autora.

    OdpowiedzUsuń
  7. mam ten sam problem co Marcin S.

    OdpowiedzUsuń