3 października 2015

Sterownik LED RGB na Attiny13

W ramach mojej nauki programowania mikrokontrolerów postanowiłem nieco ulepszyć podświetlenie szklanej półki, która znajduje się w moich meblach. Już jakiś czas temu pokazywałem układ, który dotychczas realizował tą czynność. W zasadzie działanie układu polegało tylko
na załączeniu podświetlenia w nocy i wyłączeniu w dzień.
Układ ten można znaleźć TUTAJ. Postanowiłem stworzyć układ na mikrokontrolerze Attiny13, który będzie sterować diodą LED RGB. Na dodatek sam mikrokontroler będzie wyłączał zasilanie gdy osiągnie ono krytyczną wartość napięcia. Cały układ zasilany jest z pakietu trzech akumulatorków, które zostały połączone ze sobą szeregowo, co dało 3.6V i 1000mAh, akumulatorki są niklowo-wodorkowe. Akumulatorki są ładowane baterią słoneczną o napięciu znamionowy 5.5V oraz prądzie 120mAh.
Płytka sterownika RGB
Na chwilę obecną układ steruje jedną diodą LED RGB 5050. Docelowo maja być trzy sztuki. Maksymalny pobór prądu dla układu (kolory świecące na maxa) to 25mA. Jako, że Attiny13 nie posiada PWM'a na trzech nóżkach musiałem stworzyć je programowo. W mikrokontrolerze zostało załączone ADC, które służy do kontroli napięcia. Kontrola napięcia odbywa się na nóżce PB2 (drugi kanał ADC). Dzielnik napięcia został zbudowany na rezystorach R1 i R2 i jest przystosowany dla maksymalnego napięcia 5.5V - to właśnie przy tym napięciu na nóżce PB2 mikrokontrolera jest mniej więcej 1.1V (dokładność rezystorów), czyli napięcie odniesienia dla Attiny13. Gdy napięcie na tej nóżce wynosi 1.1V to ADC=1024, a więc 5.5V=1024, 2.8V=?, czyli ADC=2.8V*1024:5.5V=521 i taką wartość ADC (521) należy ustawić dla napięcia 2.8V. Wzięło się to stąd, że krytyczne napięcie dla jednego ogniwa to 0.9V, co daje 2.7V. A zatem układ wyłącza obciążenie przy ok. 2.8V. Całość w tym czasie pobiera tylko 0.5mA.
Przykładowe kolory uzyskane przez sterownik

Dla pokazu skorzystałem z mojego statku, który został wyfrezowany w szkle. Wygląda on na zdjęciach lepiej niż "kolorowy pasek" - szklana półka ;)

/*
 * main.c
 *
 *  Created on: 15-08-2014
 *      Author: Marek
 *      Site: elektro--hobby.blogspot.com
 */


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//diody LED
#define NIEB (1<<PB1)
#define ZIEL (1<<PB0)
#define CZER (1<<PB2)

//czujnik pory dnia
#define czujnik (1<<PB3)


volatile uint8_t NIEB_W, CZER_W, ZIEL_W; 
//zmienne przechowujące wartość 
//wypełnienia PWM (50 = 100% wypełnienia)
volatile uint8_t i = 0, stan_aku=1; //zmienne pomocnicze
volatile uint16_t opoznienie; //opóźnienia
volatile uint8_t odw_n, odw_c, odw_z; 
//rozjaśnianie i ściemnianie


volatile uint8_t jasnosc_nieb, jasnosc_czer, jasnosc_ziel; 
//jasność diod PWM

//funkcje
void low_v(void);
void rgb_ok(void);


int main (void) {

  //Ustawienie portów
  DDRB |= NIEB | ZIEL | CZER;
  PORTB |= czujnik;

 
  //Włączenie i ustawienia timera
  TCCR0A |= (1 << WGM01);      //tryb CTC
  TCCR0B |= (1 << CS01) | (1 << CS00);   //preskaler 64
  TIMSK0 |= (1 << OCIE0A);      
//odblokowujemy przerwanie timera 0

  
  //Włączenie i ustawienie ADC | 1.1V=1024
  ADMUX = (1<<MUX1) | (1<<REFS0);       //Kanał ADC2
  ADCSRA = (1<<ADEN) |(1<<ADPS2) | (1<<ADPS1);   
//ADC włączone, prescaler 64

 
  _delay_ms(10);

  //zapalanie 2 kolorów
  jasnosc_czer=30;
  jasnosc_ziel=15;

  sei();
 while(1){  //główna pętla


   //kontrola napięcia
   ADCSRA |=  1<<ADSC;      //Uruchomienie konwersji
   while(ADCSRA&(1<<ADSC));   // czekaj na koniec konwersji

   if(ADC<521){    //wył. przy ok. 2.8V
    stan_aku=0;
   }

   //Jesli stan niski to dzień
   if((PINB & czujnik)){

   if(1==stan_aku) rgb_ok();
   else low_v();

   } else {
    low_v();
    stan_aku=1;
   }


     //rozjaśnianie i ściemnianie
     if(31<=jasnosc_nieb) odw_n=1;
      if(0==jasnosc_nieb) odw_n=0;

     if(46<=jasnosc_czer) odw_c=1;
     if(0==jasnosc_czer) odw_c=0;

     if(41<=jasnosc_ziel) odw_z=1;
     if(0==jasnosc_ziel) odw_z=0;

 }
 
}

// Funkcja wykonywana w nocy
void rgb_ok(void){
 
  //jasność diod
   NIEB_W = jasnosc_nieb;
   CZER_W = jasnosc_czer;
   ZIEL_W = jasnosc_ziel;
}


//Wyłączenie układu - niskie napięcie aku.
void low_v(void){

 ZIEL_W=0;
 CZER_W=0;
 NIEB_W=0;
}


//Timer
ISR(TIM0_COMPA_vect) {

   i ++ ;
   opoznienie++;


  //PWM Programowy
  if(i < NIEB_W) PORTB|= NIEB;
  else PORTB&= ~NIEB;

  if(i < CZER_W) PORTB|= CZER;
  else PORTB&= ~CZER;

  if(i < ZIEL_W) PORTB|= ZIEL;
  else PORTB&= ~ZIEL;

  
  //max czas 65535
  if(10530==opoznienie){    //opóźnienie zmiany koloru

    if(0==odw_n) jasnosc_nieb++; //tryb auto dla led niebieskiej
    else jasnosc_nieb--;

    if(0==odw_c) jasnosc_czer++; //tryb auto dla led czerwonej
    else jasnosc_czer--;

    if(0==odw_z) jasnosc_ziel++; //tryb auto dla led zielonej
    else jasnosc_ziel--;

    opoznienie=0;  //reset opoznienia
  }

 }


Aby mikrokontroler mógł załączyć ponownie obciążenie musi zostać podany minus na nóżkę PB3. Taki stan podawany jest na nóżkę mikrokontrolera tylko wtedy, gdy świeci światło (słońce) na baterię słoneczną. Taka blokada nie dopuszcza do ponownego załączenia się półki - gdy spadnie obciążenie, na akumulatorku wzrośnie napięcie, co spowodowałoby ponowne załączenie obciążenia. Ta nóżka również informuje mikrokontroler o porze dnia.
Projekt płytki sterownika RGB


Jako tranzystory kluczujące zastosowałem BC337, co daje maksymalne obciążenie 500mA dla jednego kanału. Zadaniem diody prostowniczej D1 jest ograniczenie napięcia (spadek na diodzie 0.7V) na mikrokontrolerze. D2 blokuje cofanie się prądu na baterię słoneczną, bez niej przez noc przez baterię słoneczną płyną by prąd. Z kolei D3 służy również do ograniczenia napięcia na nóżce pomiarowej mikrokontrolera. Ponadto cała płytka została wyposażona w gniazdo ISP. Płytka ma wymiary (szer/wys) ~43mm/47mm. Otwory na śruby mocujące są przygotowane na wiertło 3.2mm.

Cały program zajmuje nieco ponad 500 bajtów, Attiny13 posiada pamięć flash o łącznej pojemności 1K, więc mamy jeszcze prawie połowę wolnej pamięci. Prąd pobierany przez układ można jeszcze obniżyć np. wyłączając timer, gdy akumulatorek jest rozładowany. W moim programie działa on cały czas.



Zapewne program idzie bardziej zoptymalizować, poprawić ale jak wspominałem wcześniej, układ powstał w ramach mojej nauki programowania ;) PWM opiera się na kodzie z tej strony. Zmienna "opóźnienie" odpowiada za prędkość zmiany kolorów. Z kolei pod opisem "rozjasnianie i sciemnianie" znajduje się kod, który odpowiada za przesunięcie kolorów względem siebie. Można ustawić stałe np. co 15 kroków (15, 30, 45). Wartość ta jest dodawana na początku programu w funkcji main dla dwóch kolorów. Można również ustawić, tak jak ja ustawiłem, czyli różne liczby (w moim przypadku: 31, 46, 41), takie ustawienie powoduje różne przesunięcia między sobą i można w ten sposób uzyskać dużo więcej kolorów. Na chwilę obecną tryb dzienny oraz niskie napięcie na akumulatorze korzystają z tej samej funkcji tzn. "low_V".

Schemat:
Schemat sterownika RGB


Podzespoły:

rezystory: R1=91K, R2=22K, R3=10K, R4,R5,R6=1K, R7=10K | kondensatory: C1=100nF, C2=10uF, C3=22uF (może być 10uF) | tranzystory: Q1,Q2,Q3= BC337 (lub inny NPN) | diody prostownicze: D1,D2,D3= 1n4007 | inne: Attiny13, wtyczki goldpin, gniazdo ISP,


Wzór ścieżek przygotowanych do naniesienia na płytkę PCB, opis, schemat.

Brak komentarzy:

Publikowanie komentarza

Aby uniknąć spamu, komentarze na blogu pojawiają się po zatwierdzeniu.