Miesięczne archiwum: Listopad 2015

Dioda i PWM, czemu świeci nierówno?

Sterując diody PWM, łatwo dojść do wniosku, „że coś jest nie tak”. Chodzi o jasność diody. Otóż zmieniając stopień wypełnienia, nietrudno odnieść wrażenie, że zmianę jasności widać tylko przy pierwszych krokach, potem dioda świeci już niemal bez zmian.

Czy tak jest naprawdę?

Nie do końca. Problem nie leży w diodzie ale w ludzkim oku. A dokładniej to w mózgu. Nasze mózgi są nieliniowe, i taka sama zmiana jasności przy niemal nie świecącej diodzie jest o wiele bardziej przez nas zauważana niż gdy poziom jasności jest wysoki.

Niech za ilustrację posłuży film. Dioda z prawej jest sterowana „od zera” do maksimum i z powrotem za pomocą prostej pętli:

  for (int = 0; i < 256; i++) {
    analogWrite(9, i);
    delay(25);
  }
  for (int = 255; i >= 0; i-) {
    analogWrite(9, i);
    delay(25);
  }

Po początkowym rozjaśnieniu, w zasadzie nie widzimy zmian w jasności. Natomiast doda z lewej zachowuje się inaczej. Film trochę to przekłamuje ale patrząc bezpośrednio, prawie cały czas widać stopniową zmianę jej jasności.

Jak to jest możliwe, czy to jakiś inny PWM?

PWM jest ten sam, jednak z korekcją. Wiedząc, że czułość naszego oka ma taki kształt:

odbierana jasność

to można skorygować trochę PWM. Jak? Tak by skok wypełnienia o jedną jednostkę skutkował mniej więcej takim samym skokiem odbieranej jasności. Co to znaczy? Że rozdzielczość nam spadnie. Przy skoku z 1 na 2 rzeczywistego wypełniania PWM na Arduino na drugim końcu musimy skoczyć z 235 do 255 by zachować jednakowy skok odbieranej przez oko jasności. Dlatego nasz nowy analogWrite bedzie miał tylko 32 kroki zamiast 256.

Jak to dokładnie skorygować? No tutaj już nie będę ukrywał – posłużyłem się gotowcem znalezionym w sieci (https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/), tam znalazłem gotową tablicę, która służy za źródło korekty. W załączeniu użyty kod programu: https://gist.github.com/netmaniac/8be83f2e66ae25e949f1

Kluczowa jest tablica CIEL8, która zawiera poziomy PWM jakich trzeba użyć by z każdym krokiem dostać względną jasność zmieniała się równo. Jest to kod przeniesiony ze Arduino IDE 1.0 – podejrzewam, że można zrezygnować z makra CIELPWM na rzecz zwykłego indeksu w tablicy, ale skoro działa ;)

Biblioteka RadioNRF24 działa też na Arduino

tinyBrd

Jedną z zalet tinyBrd jest prosty, intuicyjny interfejs do NRF24L01. Dzięki temu wysyłanie i odbieranie danych jest bardzo proste. Dotąd biblioteka Radio była włączona w skład Nettigo tinyBrd Core, czyli rozszerzeniu Arduino IDE wspierającego programowanie tinyBrd.

Ponieważ otrzymywaliśmy takie prośby, przenieśliśmy bibliotekę Radio na Arduino UNO. Zmian praktycznie nie trzeba było wprowadzać, poza kilkoma organizacyjnymi.

Po pierwsze – w zarządcy bibliotek w Arduino IDE jest już biblioteka Radio (służąca do obsługi modułów FM), więc chce on nam nadpisywać uparcie nasze Radio, nawet to z tinyBrd Core, więc zmieniliśmy nazwę biblioteki na RadioNRF24. W konsekwencji zmienił nazwę globalny obiekt – dotąd korzystaliśmy np z

  Radio.begin(address, 100);

Po zmianach będzie to:

  RadioNRF24.begin(address, 100);

Reszta interfejsu – bez zmian. No, tylko na Arduino musisz podać piny CSN i CE podczas inicjalizacji. Dla pinów 8 i 7 nowy init będzie tak wyglądał (na tinyBrd jest po staremu bo tam CSN i CE są na stałe wybrane):

  RadioNRF24.begin(address, 100, 8, 7);

Biblioteka do Arduino na razie tylko na GitHubie: https://github.com/nettigo/RadioNRF24 Zip do wygodniejszego instalowania w przygotowaniu, jak również przykłady z opisem. Na szybko – kod do zobaczenia tutaj. Podłączenie modemy NRF do UNO wg schematu:

Podłączenie Arduino i NRF24L01

Podłączenie Arduino i NRF24L01

Wysyłanie poleceń z Raspberry do tinyBrd

Dotychczas tinyBrd wysyłało przez NRF24L01 dane do Raspberry. Zarówno gdy testowaliśmy jakość połączenia jak i gdy wysyłaliśmy dane z DS18B20. Tym razem na warsztat weźmiemy odwrotny przykład.

Plan jest następujący: Raspberry będzie wysyłało żądanie odczytu stanu wejścia analogowego w tinyBrd a po otrzymaniu stanu będzie wysyłać polecenie zapalenia odpowiedniej ilości diod podłączonych do tinyBrd.

Plan jest znany, to może pokażemy co wyszło finalnie:

Pierwsze podejście do implementacji jest takie: RPi wysyła pakiet z jednym bajtem o wartości 99, co znaczy ‚podaj mi stan wejścia analogowego’, tinyBrd odeśle wtedy wartość.

Raspberry odbierze dane od tinyBrd i wyśle dwa bajty do tinyBrd, pierwszy to 102 (taką wartość ma polecenie zapal diody) a drugi ile diod ma zostać zaświeconych. tinyBrd odbierając komendę 102, zaświeci tyle diod ile będzie podane w drugim z bajtów.

Proste?  Wartości ‚komend’ zostały wybrane arbitralnie, teraz omówię szczegóły.

Czytaj dalej