środa, 20 marca 2013

Programowanie AVR cz. 9: Mierzymy temperaturę.

Co prawda w zamierzeniu miał to być obszerny artykuł na temat pomiaru temperatury przez układ mikroprocesorowy na bazie ATmegi 48P, ale po dłuższych przemyśleniach doszedłem do wniosku, że o wiele lepiej będzie po prostu pokazać schemat układu i listingi programów, z niewielkim, niezbędnym komentarzem.

Mając do dyspozycji mikrokontroler ATmega 48P możemy zbudować prostu termometr na co najmniej dwa sposoby. Pierwszy z nich może się opierać na odczytywaniu temperatury z wewnętrznego sensora, jednak aby uzyskać w miarę zadowalające wyniki, należy przeprowadzić kalibrację - szczegóły znajdziecie w specjalnie tej tematyce poświęconym dokumencie, dostępnym na stronach firmy Atmel.
Poniższy listing pokazuje, jak możemy wykorzystać wewnętrzny sensor (wyniki wyświetlane są na "szeregowym" LCD mojej produkcji):

Kalibracji dokonałem z grubsza, nie dysponując ani możliwością uzyskania znacznej różnicy temperatur, ani też dobrym termometrem wzorcowym. Zauważmy, że z wbudowanym czujnikiem temperatury komunikujemy się w taki sam sposób, jak z przetwornikiem analogowo-cyfrowym; jest to jakby dodatkowy kanał ADC.

Drugi sposób, o wiele ciekawszy, polega na wykorzystaniu zewnętrznego, scalonego czujnika temperatury. Na rynku znajdziemy wiele tego typu układów - najciekawsze z nich to układy, z którymi mikrokontrolery komunikują się za pomocą magistral I2C czy 1Wire, jednak w moim termometrze zastosowałem układ scalony analogowy LM35DZ. Ta wersja pozwala na pomiar temperatur w zakresie od 0 do 100 st. C, czyli nadaje się doskonale do zastosowań typu indoor. Wartość napięcia, na którą układ konwertuje temperaturę otoczenia (właściwie jest to temperatura jego obudowy), przetwarzana jest przez przetwornik analogowo-cyfrowy mikrokontrolera i prezentowana przez szesnaście diod LED, przy czym dla zbyt niskich i zbyt wysokich temperatur przewidziana jest specjalna sygnalizacja - osobne, pulsujące LED-y (PWM). Dodatkowo wyniki pomiarów można śledzić na opcjonalnym LCD.
Diody LED są sterowane za pomocą dwóch ekspanderów magistrali I2C (PCF8574P), dzięki czemu obsługa wyświetlania wyników realizowana jest przez dwa wyprowadzenia mikrokontrolera (stały problem: jak rozszerzyć liczbę wejść/wyjść mikrokontrolerów).
Oto schemat układu:


i listing programu:

Schemat, dla poprawy czytelności, nie zawiera wartości zastosowanych elementów biernych, oto więc spis:

  • C1, C2: 22pF - 33pF
  • C3, C4, C5: 100nF
  • C6: 10μF
  • L1: 10μH
  • R1 - R18: 220Ω
  • R19: 10kΩ
  • R20, R21: 330Ω
  • R22, R23: 4,7kΩ
  • LED1 - LED18: zestaw dowolnych diod elektroluminescencyjnych

Przedstawione rozwiązanie z wielu względów nie jest optymalne - jakoś szczególnie go nie dopracowywałem - weźmy choćby pobór prądu przez szesnaście święcących diod...
Jednak efekt ciekawy, szczególnie, gdy dobierzemy różnokolorowe diody dla poszczególnych przedziałów temperatur.

sobota, 16 marca 2013

RaspberryPi: kwestia zasilacza.

Przypuszczam, zresztą chyba dość trafnie, że znakomita większość z nas, użytkowników RaspberryPi, zasila swoje urządzonka z prostych zasilaczy impulsowych (przetwornic, jak kto woli), dostępnych za kilkanaście do kilkudziesięciu złotych w marketach czy serwisach aukcyjnych. Albo kupionych wcześniej, jako element wyposażenia innych urządzeń - tak jest np. w moim przypadku, kiedy zauważyłem, że do zasilania RPi doskonale się nada ładowarka do czytnika.
Urządzenia te spełniają najczęściej podstawowe założenia dotyczące wydajności pożądanej przez RPi (napięcie 5V, pobór prądu około 750mA) - tabliczki znamionowe jak jeden mąż mówią, że będzie na wyjściu 5V z maksymalną wydajnością prądową do 1A. I zwykle dają radę. Ja jednak dawno, dawno temu straszyłem, że sam sobie zrobię zasilacz do maliny. I owszem, zrobiłem, ale z wyżej wymienionego powodu zmienił się target - układ został zaadaptowany do zasilania moich prototypów i eksperymentów mikroprocesorowych. Oprócz 5V daje też 3,3V (bo miałem kiedyś zamiar pobawić się wyświetlaczami graficznymi wydłubanymi ze starych komórek :)), ma wydajność do 1A (dla wyjścia 3.3V jest to 800mA przy założeniu, że nie korzystamy jednocześnie ze źródła napięcia 5V), można go zasilać z dowolnego zasilacza zewnętrznego dającego napięcie do 12V (choć wytrzymał też 14V; szybko natomiast można się przekonać, że tzw. zasilacze uniwersalne typu bazarowego, z regulowaną wartością napięcia wyjściowego, mają dość ostre przekłamania w tabliczkach znamionowych...), posiada zabezpieczenie przed zmianą polaryzacji zasilacza zewnętrznego i gustowną lampkę sygnalizującą działanie. Całość, zgodnie z wytycznymi geekowskiego stylu, przymocowana do stabilnej podstawki, ale bez obudowy.
Jednej rzeczy wszak zapomniałem - otóż scalone stabilizatory napięcia (tzw. regulatory napięcia) bardzo łatwo i szybko się pocą, szczególnie, gdy dużo od nich wymagamy... Nie popełniłem radiatora! Gdy podłączyłem do tego zasilacza malinę, myślałem, że 7805 po prostu spłynie z płytki...
Dziś nadrobiłem zaległości - stabilizator 7805 otrzymał elegancko wymodelowany radiator wielowarstwowy z puszki po piwie (bezalkoholowym, serio!), a cały układ znalazł się w zasięgu wiatraczka odzyskanego ze starego komputera (znalazłem w szafce radiator z coolerem - po rozmiarach wnioskuję, że z 486 :)). Innymi słowy mam teraz full-wypas zasilacz laboratoryjny, któremu nie straszne jest wpuszczanie w maliny ;)
Przy okazji znalazłem całkiem wydajny zasilacz 9V/1A ze starego routera - sprawdza się świetnie, nie "siada" przy obciążeniu np. maliną.
Dlaczego piszę o zasilaczu ciągłym własnej produkcji, podczas gdy impulsowe, dostępne w markecie, są tanie i jakby co, to można zrobić sobie zapas? Otóż dużo większe zaufanie mam do własnej produkcji zasilacza, nawet jeśli nie jest to lekki układ impulsowy. Miałem okazję spalić kiedyś takiego impulsaka - to, co zobaczyłem w środku, daje do myślenia :) Czasem po prostu szkoda nawet maliny.

Gwoli ścisłości - nie mam nic przeciwko technice impulsowej. Po prostu zasilacze marketowe są podłej jakości.

RaspberryPi: serwer wydruku.

I to by było na tyle - więcej pisać nie trzeba, bo też i filozofii specjalnie w tym nie ma... Ale jakby ktoś potrzebował, służę uprzejmie.

Od jakiegoś czasu zastanawiam się nad zakupem serwera wydruku, nawet mógłby pracować z drukarką wyposażoną w łącze równoległe (moja akurat ma i USB i Centronicsa), niestety ciągle blokuje mnie cena - jak na niewielki stopień komplikacji i niezbyt zaawansowaną technologię ciągle za wysoka, nawet w przypadku printserverów LAN-owskich. Wczoraj, grzebiąc bezmyślnie w internetach, natknąłem się na artykuł poświęcony malinie i gdzieś na początku przeczytałem, że ludzie robią z RaspberryPi przeróżne ustrojstwa, w tym centra multimedialne, serwery wydruku... I tu dostałem nagłej eureki... Przecież malina u mnie się ostatnio nudzi, a drukarkę udostępniam laptopowi żony przez komputer stacjonarny, który musi być włączony itd., a jest to - jak na porządną stacjonarkę przystało - kobyła i bomba energetyczna... A RaspberryPi, zasilany z zasilacza impulsowego, żrącego niewiele energii, sprawdziłby się w roli serwera wydruku wręcz doskonale.
Oto, co zrobiłem.
Na początku zaktualizowałem Raspbiana:

sudo apt-get update 
sudo apt-get upgrade

następnie zainstalowałem pakiet oprogramowania CUPS:

sudo apt-get install cups

Razem z pakietem zasadniczym pociągnęło się oczywiście wiele innych, potrzebnych i szalenie ważnych. CUPS to oprogramowanie dostarczające systemom uniksowym funkcjonalność drukowania, współdzielenia i udostępniania drukarek w sieci. Dodatkowo mamy możliwość administrowania drukarkami czy kolejką wydruku przez przeglądarkę WWW. Aż dziw bierze, że takie cudo tworzy głównie firma ogrodnicza...

Po zainstalowaniu pakietu trzeba jeszcze, dla wygody, dodać swojego usera do grupy administratorów wydruku:

sudo usermod -a -G lpadmin nazwa_użytkownika

i - żeby dać sobie możliwość zarządzania drukarkami z innych komputerów w sieci (przez przeglądarkę właśnie), należy nieco zmienić plik konfiguracyjny /etc/cups/cupsd.conf. Mój plik konfiguracyjny na malinie wygląda tak (pogrubiłem linie dopisane lub zmienione przeze mnie):

#
# "$Id: cupsd.conf.in 9407 2010-12-09 21:24:51Z mike $"
#
# Sample configuration file for the CUPS scheduler.  See "man cupsd.conf" for a
# complete description of this file.
#

# Log general information in error_log - change "warn" to "debug"
# for troubleshooting...
LogLevel warn

# Deactivate CUPS' internal logrotating, as we provide a better one, especially
# LogLevel debug2 gets usable now
MaxLogSize 0

# Only listen for connections from the local machine.
Port 631
#Listen localhost:631
Listen /var/run/cups/cups.sock

# Show shared printers on the local network.
Browsing On
BrowseOrder allow,deny
BrowseAllow all
BrowseLocalProtocols CUPS dnssd

# Default authentication type, when authentication is required...
DefaultAuthType Basic

# Web interface setting...
WebInterface Yes

# Restrict access to the server...

  Order allow,deny
  Allow all

# Restrict access to the admin pages...

  Order allow,deny
  Allow all

# Restrict access to configuration files...

  AuthType Default
  Require user @SYSTEM
  Order allow,deny
  Allow all

# Set the default printer/job policies...

  # Job/subscription privacy...
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default

  # Job-related operations must be done by the owner or an administrator...
 
    Order deny,allow

    Require user @OWNER @SYSTEM
    Order deny,allow

  # All administration operations require an administrator to authenticate...
 
    AuthType Default
    Require user @SYSTEM
    Order deny,allow

  # All printer operations require a printer operator to authenticate...
 
    AuthType Default
    Require user @SYSTEM
    Order deny,allow

  # Only the owner or an administrator can cancel or authenticate a job...
 
    Require user @OWNER @SYSTEM
    Order deny,allow
 
    Order deny,allow

# Set the authenticated printer/job policies...

  # Job/subscription privacy...
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default

  # Job-related operations must be done by the owner or an administrator...
 
    AuthType Default
    Order deny,allow
 
    AuthType Default
    Require user @OWNER @SYSTEM
    Order deny,allow

  # All administration operations require an administrator to authenticate...
 
    AuthType Default
    Require user @SYSTEM
    Order deny,allow

  # All printer operations require a printer operator to authenticate...
 
    AuthType Default
    Require user @SYSTEM
    Order deny,allow
 
  # Only the owner or an administrator can cancel or authenticate a job...
 
    AuthType Default
    Require user @OWNER @SYSTEM
    Order deny,allow
 
    Order deny,allow
 
#
# End of "$Id: cupsd.conf.in 9407 2010-12-09 21:24:51Z mike $".
#

W repozytoriach Raspbiana znajduje się wersja 1.5.3 pakietu CUPS (to dla jasności, gdyby były jakieś niezgodności co do zawartości pliku konfiguracyjnego). Załączyłem plik w całości, żeby można było go sobie po prostu skopiować i wkleić, bez grzebania i dopisywania.

Po zmianie pliku konfiguracyjnego przestrzeliwujemy usługę:

sudo service cups restart

i z poziomu przeglądarki wchodzimy na adres:

http://adres_ip_mailny:631

Interfejs jest szalenie prosty i intuicyjny, więc zakładam, że każdy poradzi sobie ze skonfigurowaniem swojej drukarki - jednak przed tą czynnością należy drukarkę podłączyć do RPi i włączyć jej zasilanie :). CUPS znajdzie zapewne kilka różnych drukarek (to ze względu na zainstalowane sterowniki), jednak wybrać musimy tę fizyczną, przez nas posiadaną - to oczywiste.
Po skonfigurowaniu drukarki jako współdzielonej i udostępnianej, możemy na dowolnej platformie systemowej (Linux, Windows, MacOS itp.) wybrać/dodać sobie serwowaną przez malinę drukarkę sieciową, używając adresu:

http://adres_ip_maliny:631/printers/nazwa_drukarki

np. w moim przypadku wygląda to tak:

http://192.168.1.2:631/printers/Samsung_ML-2010

I to wszystko! Sprawdźmy jeszcze - choćby za pomocą rcconf - czy CUPS jest uruchamiany automatycznie z systemem i serwer wydruku gotowy.
Rozwiązanie działa niezależnie od tego, czy używamy sieci LAN, czy WiFi.

niedziela, 10 marca 2013

RaspberryPi: odbiór informacji lokalizacyjnych oraz aktualnego czasu z modułu bezprzewodowego GPS (Bluetooth).

Kolega na swoim blogu wspomniał parę dni temu o synchronizacji zegara RaspberryPi z sygnałem czasu przekazywanym przez satelity systemu GPS (http://guzik.net.pl/blog/2013/03/mobilne-raspberry-pi/). Wystarczyło :-)
Bawiąc się "Mailną" zapomniałem (no jak mogłem???) właśnie przekształcić ją w komputerek-nawigację, choć może to zbyt mocne określenie. Chodzi o to, żeby RaspberryPi przekonać do współpracy z bezprzewodowym modułem GPS Nokia LD-3W. Z takiej współpracy mogą wyniknąć dwie korzyści (co najmniej):
  • ciągle aktualizowany odczyt informacji o lokalizacji;
  • synchronizacja zegara "Maliny" z czasem satelitarnym (poprzez ntp; RaspberryPi nie ma RTC z podtrzymaniem bateryjnym - jeśli ktoś chce, to kolega, będący autorem linkowanego wyżej bloga, opisał pokrótce, jak dodać taki sprzętowy zegar).
Mając współrzędne i masę innych, ciekawych informacji dotyczących położenia, puszczając wodze fantazji i dodając odrobinę kreatywności, można wręcz stworzyć sobie całkiem niezły komputer nawigacyjny (tym razem już nie przesadzam!). Kto wie, być może spróbuję podziałać w tym kierunku?
W każdym razie musimy zacząć od zgrania ze sobą RaspberryPi i LD-3W. Przede wszystkim musimy - oprócz modułu GPS - zaopatrzyć się w jakiś w miarę dobry "dongiel" Bluetooth na USB. Dlaczego ważna jest jakość i jak ją ocenić... Może po prostu zasugerujmy się źródłem (miejscem zakupu) i ceną. Problem jest właśnie w tym, że wiele modułów Bluetooth niezbyt jest elastycznych jeśli chodzi o pracę w dosyć skomplikowanych warunkach (bo będziemy czytać dane o lokalizacji i informacje o czasie, a to dla jednego z moich dongli, aukcyjnego, za parę złotych nabytego, okazało się ponad jego siły).
Dongla podłączamy do uruchomionej wcześniej "Mailny", mając na pokładzie jak najświeższą wersję Raspbiana. Najpierw sprawdzamy jednak, czy został zauważony przez system. Powinniśmy zobaczyć na liście nasze urządzenie - oczywiście rozpoznamy je po nazwie i z ogromną przyjemnością zauważymy informacje o trybie HCI:


Teraz musimy Raspbiana zaopatrzyć w oprogramowanie, które będzie nam niezbędnie potrzebne. O ile pakiet ntp jest najprawdopodobniej zainstalowany, to o resztę musimy zadbać sami. Doinstalujmy więc bluez (i pewnie od razu otrzymamy informację, że cała reszta narzędzi do obsługi Bluetooth zostanie dołożona; jeśli nie, to oczywiście wyszukujemy w np. aptitude wszystkie niezbędne składniki i doinstalowujemy), gpsd, gpsd-clients i python-gps (reszta pójdzie z automatu).
Mając wszystkie komponenty programowe w gotowości, zaczynamy właściwą zabawę. W sumie nie ma się co tutaj rozwodzić, ot po prostu:

  1. Sprawdzamy adres MAC naszego urządzenia:

    hcitool dev

  2. Wyszukujemy moduł GPS (musimy go włączyć i umieścić w zasięgu "Maliny", czyli maksymalnie do 10 metrów):

    hcitool scan

  3. Komenda z punktu 2. poda nam też nazwę urządzenia, więc bez problemu rozpoznamy nasz moduł GPS spośród wielu pozostających w zasięgu urządzeń. Mając adres MAC modułu GPS możemy sprawdzić, jakie usługi udostępnia, przede wszystkim zaś sprawdzić port BT, na którym moduł udostępnia łącze szeregowe (klasyczny RS):

    sdptool browse 11:22:33:44:55:66

    gdzie 11:22:itd. to adres MAC GPS-a.
    Niestety, w przypadku mojego modułu LD-3W komenda ta nie zwróciła żadnej informacji, dlatego też przyjąłem, że łącze szeregowe jest dostępne na porcie 1 (ok, wziąłem to z doświadczenia, które zdobyłem bawiąc się pisaniem programu pokazującego moje położenie na mapie...).
  4. Numer portu, jak również adres MAC i nazwa modułu przydadzą się nam podczas edycji pliku

    /etc/bluetooth/rfcomm.conf

    - musimy też zdecydować, czy port szeregowy dla urządzenia BT będzie tworzony manualnie, czy też automatycznie przy starcie systemu.
    Nie podaję tutaj przykładu konfiguracji - plik ten zawiera domyślne wartości z obszernymi wyjaśnieniami; wystarczy dosłownie wpisać w odpowiednie miejsca trzy wspomniane rzeczy, żeby wszystko elegancko hulało.
  5. Teraz rzecz chyba najważniejsza, czyli sparowanie ze sobą "Maliny" i modułu GPS. Po wpisaniu tych komend (tutaj trzeba sobie podwyższyć uprawnienia jeśli nie pracujemy na koncie roota):

    bluez-test-adapter discoverable on
    bluez-simple-agent hci0 11:22:33:44:55:66


    najpierw uczynimy naszą "Malinę" widoczną w przestrzeni Bluetooth, a następnie zostaniemy poproszeni o podanie PIN-u w celu uzyskania dostępu do modułu GPS. W przypadku mojej Nokii są to cztery zera, ale bywa różnie (RTFM!!!).
    11:22:itd. - to adres MAC modułu.
    Pamiętać należy, że po zmianie dongla Bluetooth, parowanie trzeba powtórzyć.
  6. Tworzymy port szeregowy do komunikacji z modułem:

    rfcomm bind rfcomm0

  7. ...i jeśli nic dziwnego się nam nie przytrafiło, to za pomocą klasycznej komendy testującej:

    cat /dev/rfcomm0

    możemy już pobierać dane z GPS w formacie NMEA (czyli średnio dla nas czytelne).
  8. Za pomocą polecenia:

    dpkg-reconfigure gpsd

    konfigurujemy demona gpsd, podając mu wspomniany w pkt. 7. port szeregowy jako źródło danych GPS oraz - dla potrzeb ntp - ekstra parametr "-n"; reszta propozycji konfiguracyjnych kreatora zostaje bez zmian.
  9. Zaglądając w manuala gpsd:

    man gpsd

    dowiadujemy się, jaki linie dopisać do pliku:

    /etc/ntp.conf

  10. Po tych zmianach przestrzeliwujemy demona gpsd, a następnie ntp. 
Wszystko powinno zacząć pięknie działać - czyli odczyty czasu:


oraz współrzędnych (i wielu innych, ciekawych informacji) - tutaj efekt komendy cgps -s:


Podsumowując zatem...


Okazuje się, że pogodzenie ze sobą RaspberryPi i bezprzewodowego modułu GPS nie jest specjalnie ciężkim wyzwaniem. Jak wspomniałem na wstępie, warto zainwestować w dobrej jakości dongla GPS.
Niestety, jest jeszcze jedna strona medalu... Otóż wszystko pięknie działa, jednak próba rebootowania "Maliny", czy wyłączenia, kończy się efektem "kernel panic" powodowanym przez podsystem Bluetooth (trzeba restartować wyłączając zasilanie - może da się z klawiatury, ale ja pracuję via ssh). Zresztą podobny efekt uzyskać można wyciągając dongla BT z gniazdka USB. Być może jest to problem używanych przeze mnie dongli (trzy różne egzemplarze, tylko przy jednym - tym dziadowskim - kilka razy mi się system nie sypnął), a być może kwestia zasilania urządzeń USB przez "Malinę", albo problem jądra systemu. W każdym razie da się to obejść ubijając ręcznie, przed restartem lub zatrzymaniem systemu, po kolei ntp, gpsd i bluetooth.

Zachęcam do eksperymentów i dzielenia się doświadczeniami :)

A, i jeszcze jedno: proszę pamiętać, że Bluetooth to "blutuf", nie "blutacz" ;D

piątek, 1 marca 2013

[Rozwiązanie] Samsung GT-C3322: "błąd logowania" i "błąd sieci" podczas próby skorzystania z wbudowanego klienta Twittera (i zapewne też Facebooka).

Parę miesięcy po zakupie telefonu Samsung GT-C3322 (czytaj o moich spostrzeżeniach z pierwszego dnia użytkowania), świetnie działająca dotychczas natywna (wbudowana) aplikacja kliencka Twittera nagle zaczęła - podczas próby zalogowania się w serwisie - wyrzucać komunikaty "Błąd logowania" i "Błąd sieci"... Po kilku godzinach prób z różnymi konfiguracjami, mieszaniem w koncie na Twitterze, zrobieniu sobie przerwy i zalogowaniu się (nieudanym oczywiście) po kilku dniach, w końcu dałem sobie spokój - i tak bez większych problemów używałem Twittera przez przeglądarkę (Opera Mini). Jednak co jakiś czas, łudząc się nadzieją, że coś się naprawiło, próbowałem się zalogować... Tiaaa...
Przedwczoraj jednak stwierdziłem, że nie może tak być, że telefon ma jakąś funkcjonalność, którą z przyjemnością bym wykorzystał, a ona jak na złość nie działa. Kombinowałem nawet, czy przypadkiem ekipa Twittera nie namieszała znowu w API, albo czy nie pomogłaby aktualizacja oprogramowania telefonu. Z tej ostatniej opcji nic nie wyszło, bo Samsung nie przygotował (jeszcze?) aktualizacji softu.
Koniec końców napisałem maila do supportu i konsultant doradził mi... zrobić twardy reset telefonu polecaniem/kodem:

*2767*3855#

Cóż, okazało się, że jest to właściwe rozwiązanie :)
Zanim jednak ktoś z Was spróbuje zadziałać w ten sposób, proponuję wykonać kopię bezpieczeństwa danych zapisanych w pamięci wewnętrznej telefonu (kontakty przede wszystkim!!!) - wystarczy użyć opcji Backup dostępnej w ustawieniach telefonu, a potem, przed resetem, usunąć z telefonu kartę pamięci. Wiem, że niby nic się nie powinno przydarzyć, ale czasem warto dmuchać na zimne.
Po resecie przywracamy sobie wszystko, synchronizujemy kalendarz (chyba, że używamy tylko lokalnego - to wtedy odtwarzamy z backupu), doinstalowujemy usunięte apki, konfigurujemy telefon - i już!

Z tego, co wiem, podobny problem mają użytkownicy Facebooka. Zdaje się, że "moje" rozwiązanie powinno pomóc i w tym przypadku.