Programowanie Arduino Pro Mini za pomocą USB Mini

wtorek, styczeń 25, 2011 0:56 by netmaniac | Filled in arduino, dla początkujących, howto

Każdy, kto robił projekt oparty na Arduino, wie, że przychodzi taki pomysł do głowy, że chciałoby się, aby Arduino było znacznie mniejsze niż podstawowa płytka.

Szybko powstały różne płytki, które oferują zgodność z Arduino ale są znacznie mniejsze. Jedną z takich jest produkowany przez SparkFun Arduino Pro Mini. Obecnie ma ono na pokładzie ATmega328 a rozmiar całej płytki to 33 mm x 18 mm. Występuje ono w dwóch wersjach. Pierwsza jest działa na obniżonym napięciu 3.3V i kosztem niższego taktowania (8 MHz) oferuje mniejsze zużycie prądu. Druga jest kopią funkcjonalną Arduino – działa na 5V i jest taktowana 16 MHz.

Jeśli rozmiar płytki jest taki niewielki to czego brakuje? Otóż brakuje konwertera USB/Serial. Dlatego do programowania musimy mieć dodatkowe urządzenie – konwerter USB/Serial TTL (dla osłody – brak tego układu na płytce oznacza niższą cenę samego Mini).

Jednym z konwerterów USB Serial w ofercie Nettigo jest Arduino Mini USB. Ponieważ połączenie i programowanie Pro Mini sprawia czasem na początku kłopoty – przedstawiam małe HOWTO:

Manualne programowanie

Po resecie urządzenia mniej więcej przez jedną sekundę aktywny jest bootloader Arduino. Oczekuje on na dane na Serialu i jeżeli rozpozna dane binarne – transmisja zostanie zapisana w pamięci Flash i uruchomiona. Dlatego najprostszy sposób to podłączyć Arduino Mini USB i Pro Mini w następujący sposób:

  • połączyć masy USB Mini z Pro Mini (GND z GND)
  • Zasilanie z USB Mini (+5V) do Vcc na Pro Mini
  • RX z USB Mini do RX1 na Pro Mini
  • TX z USB Mini do TX0 na Pro Mini

Wyjścia na USB Mini nie są opisane, więc tutaj jest schemat poglądowy wyprowadzeń (gniazdo USB jest z lewej strony rysunku):

Wyprowadzenia USB Mini

Wyprowadzenia USB Mini

Rzeczywiste podłączenie można podejrzeć na tym zdjęciu:

Układ do ręcznego resetu przy programowaniu

Układ do ręcznego resetu przy programowaniu

Szkic należy najpierw skompilować (ikonka z trójkącikiem) a następnie nacisnąć przycisk reset na Arduino Pro Mini i jednocześnie przycisk upoloadu w Arduino IDE (trzeba pamiętać o wyborze właściwej płytki w menu Tools/Board) . Diody TX i RX na USB Mini powinny zacząć migotać i szkic po chwili powinien już być na Pro Mini.

Automatyczny reset (Automatic Reset lub Software Reset)

Jednak zwykłe Arduino już od długiego czasu można programować naciskając Upload w IDE bez konieczność ręcznego resetowania płytki. W wypadku płytek Mini, które ze względu na swoje małe rozmiary często są w trudno dostępnych miejscach, takie rozwiązanie ma niewątpliwą przewagę nad ręcznym resetowaniem.

Aby skopiować to zachowanie większego Arduino wystarczy wyjście RTS na USB Mini (oznaczone 3) połączyć z którymś wejść RST na Pro Mini:

Automatyczny (programowy) reset Arduini Pro Mini

Automatyczny (programowy) reset Arduini Pro Mini

Tutaj użyłem sond z Bus Pirate, jako że ani do Pro Mini ani do USB Mini nie miałem przylutowanych goldpinów. Od teraz wystarczy tylko nacisnąć Upload w Arduino IDE i już Pro Mini po krótkiej chwili ma na sobie nowy szkic.

Modem komunikacji radiowej XBee XB24B

czwartek, styczeń 13, 2011 0:55 by sprae | Filled in arduino, howto

W życiu każdego entuzjasty elektroniki i programowania (zwanego z angielska geekiem) najwięcej radości dają gadgety, mające potencjalnie ogromne możliwości, których wykorzystanie zależy tylko od nas.
Po godzinach spędzonych na zabawie i testowaniu możliwości XBee, mogę szczerze powiedzieć, że jest on jednym z takich urządzeń.

Czym jest XBee?

XBee to modem radiowy z interfejsem szeregowym i dodatkowymi pinami, które możesz wykorzystać we własnym zakresie. Modem taki pozwala przesyłać dane bez pomocy kabla z prędkościami od 1200 do 230400 bitów na sekundę w paśmie 2.4 Ghz (czyli tym samym co WiFi). Modem zasilany jest napięciem 3.3 V. Dostarczany jest w postaci małej płytki drukowanej.

Read the rest of this entry »

Hallotron – czujnik pola magnetycznego

czwartek, grudzień 2, 2010 11:36 by markal | Filled in arduino

Hallotron to inaczej czujnik pola magnetycznego wykorzystujący efekt Halla. Ten efekt polega w skrócie na występowaniu różnicy potencjałów w przewodniku znajdującym się w polu magnetycznym.

CS3144E dostępny w sklepie Nettigo jest hallotronem w obudowie TO-92UA. Składa się ze stabilizatora napięcia, generatora napięcia Halla, wzmacniacza różnicowego i przerzutnika Schmitta. Wyjście typu otwarty kolektor. Dokładną specyfikację można znaleźć w karcie katalogowej, w sekcji Pliki.

Budowa wewnętrzna czujnika:

Budowa wewnętrzna czujnika Halla

Z zewnątrz natomiast wygląda to tak:

Wyprowadzenia czujnika

Nie sugerujcie się oznaczeniami – to całkiem inny układ, ale w tej samej obudowie. Po prostu nie miałem możliwości zrobienia porządnego zdjęcia w trybie makro ;) .

Czujnik podaje na wyjściu dwie wartości: VOH bliską napięciu zasilania i VOL bliską zeru. Stan wysoki występuje na wyjściu, gdy nie ma pola magnetycznego, a ściślej mówiąc, gdy pole wokół czujnika jest zbyt słabe, żeby przekroczyć wartość progową. Kiedy natężenie pola magnetycznego odpowiednio wzrośnie, napięcie na wyjściu spadnie prawie do zera. Układ wróci do poprzedniego, wysokiego stanu dopiero, gdy natężenie pola zmniejszy się, przy czym wartość progowa dla zmiany L->H jest niższa, niż dla H->L. Najlepiej zilustrować to wykresem:

Zmiana napięcia wyjściowego

Taki przebieg napięcia wyjściowego to tzw. histereza. A dlaczego nie ma po prostu jednego progu przełączania? W takim wypadku, gdyby natężenie pola było akurat bliskie temu progowi napięcie wyjściowe migotałoby podczas niewielkich jego zmian.

A tak, gdy pole magnetyczne osiągnie wartość BOP, wówczas nastąpi przełączenie ze stanu wysokiego na niski. Aby nastąpiło przełączenie w stan wysoki wartość natężenia pola magnetycznego musi spaść poniżej BHP, które jest mniejsze od BOP.

Dlatego przy natężeniu o zbliżonej do BOP wartość, następuje przełączenie w stan niski i nie ma efektu migotania, który miałby miejsce gdyby przełączenie między stanami odbywało się niezależnie od kierunku przy wartości BOP.

Najprostsza aplikacja

Hallotron ma oczywiście wiele ambitnych zastosowań, chociażby w obrotomierzu, niemniej ja ograniczę się do przedstawienia najprostszego z możliwych – diody LED włączanej za pomocą magnesu.

W związku z tym, że czujnik daje na wyjściu dwa poziomy napięć, aż się prosi, żeby podłączyć go do jednego z cyfrowych pinów Arduino. W tym celu jak zwykle trzeba zadeklarować pin jako wejście, w funkcji setup() wpisując:

pinMode(hallPin, INPUT)

gdzie hallPin oznacza numer cyfrowego pinu Arduino – ja wybrałem 8. Jeśli już jesteśmy przy konfiguracji wejścia, kolejną konieczną do zrobienia rzeczą będzie podciągnięcie go do zasilania przez wewnętrzny rezystor. Jeśli tego nie zrobimy, wejście będzie wisiało w powietrzu, zbierając zakłócenia objawiające się migotaniem diody. A więc zaraz po poprzedniej linijce dodajemy:

digitalWrite(hallPin, HIGH);

Jako wyjście wybieramy inny cyfrowy pin, przy czym najlepiej 13-ty, bo tam większość modeli Arduino ma dołączoną diodę LED. Reszta kodu nie wymaga chyba dłuższego komentowania – wejście jest odczytywane w pętli, a wyjście ustawiane w zależności od jego wartości. Cały program prezentuje się następująco:

const int hallPin = 8;
const int ledPin = 13;

int hallState = 0;

void setup(){
  pinMode(hallPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(hallPin, HIGH);
}

void loop(){
  hallState = digitalRead(hallPin);

  if (hallState == HIGH){
    digitalWrite(ledPin, LOW);
  }
  else{
    digitalWrite(ledPin, HIGH);
  }
}

Schemat połączenia (bardziej dla zasady, bowiem nie ma tu raczej żadnych niejasności):

Schemat połączeń

Zewnętrzna dioda LED jest opcjonalna, o ile nasz model Arduino ma wbudowaną. W przeciwnym wypadku musi być podłączona, jak pokazano. Rezystor ograniczający prąd można zupełnie bezpiecznie pominąć.

Tak wygląda złożony w praktyce, jakże skomplikowany, układ:

Układ zmontowany w praktyce

A tak działa:

Jak widać, wypróbowałem dwa magnesy i różnica w zasięgu czujnika jest widoczna. Nie miałem niestety magnesu neodymowego, ale podejrzewam, że wtedy czujnik reagowałby z dużo większej odległości. Co do strony czujnika, do której należy zbliżać magnes – nie ma to znaczenia, a przynajmniej nie jest zauważalne.

JSON na Arduino

piątek, listopad 19, 2010 13:07 by netmaniac | Filled in arduino

Wyszła wersja 1.0 biblioteki aJSON, czyli wsparcie do parsowania i tworzenia obiektów w JSON. Każdy kto chce podłączać system oparty na Arduino do internetu do jakiegoś API doceni wygodę jaką oferuje ta biblioteka.

Nadaje się głównie na Arduino Mega oraz na te z ATmega328 (ze względu na zużycie pamięci).

LoL shield jako prosta gra z Arduino

piątek, listopad 12, 2010 15:41 by netmaniac | Filled in arduino, dla początkujących

Gdy tylko w moje ręce wpadł shield LoL czyli Lots of LEDs (jak to przetłumaczyć próbowałem to wyszło DoD – Dużo Diód), wiedziałem co chciałem zrobić. Są one dostępne w wersji z diodami czerwonymi lub zielonymi. Różnica jest tylko w kolorze cała reszta jest identyczna.

Ale najpierw trzeba było go zmontować. Wyglądało to na męczące zadanie. Wbrew pozorom zlutowanie prawie 130 diód, które są w tym zestawie nie jest ani takie trudne ani takie męczące. Mnie zmontowanie całości zajęło około 2h, wliczając w to pomoc ze strony bardzo uczynnego 4.5 latka :) Opis na stronie autora jest bardzo dokładny i ułatwia montaż znakomicie.

Wyświetlacz 9×13 którym jest LoL shield to całkiem sporo. Co prawda oddajemy prawie wszystkie wyjścia cyfrowe z Arduino, ale do wyświetlania tekstów – całkiem, całkiem. Aha – zostają nam dwa wolne wyjścia cyfrowe D0 i D1 bo na nich jest serial. Jeżeli mamy już układ którego nie trzeba debugować (he he) to w sumie te dwa wyjścia są do wykorzystania.

Ze względu na to, że brak jest wolnych wyjść cyfrowych więc shield jako taki nie ma złączy, dla wejść analogowych jest wyprowadzone po jednym złączu w formie pola do lutowania. Wyjątkiem są A4 i A5 które są dodatkowo wyprowadzone na krawędź shielda. Dlaczego? Bo A4 i A5 to są piny wykorzystywane przez I2C. A I2C świetnie się nada do komunikacji z wyświetlaczem, który znajduje się gdzieś dalej.

Ale ja nie chciałem wyświetlać tekstów, od razu wiedziałem, że chcę zrobić jakąś bardzo prostą grę. Arkanoid raczej nie (Circuloid’owi rynku nie będę odbierał :) ) więc z klasyków zostają albo Space Invaders, albo Pong. Ale ja wybrałem klona Spy Hunter ;) Pamiętacie tę muzyczkę? Art of Noise, theme z Peter Gunn. Tutaj w trochę innym wykonaniu:

Ale wróćmy do LoL. Biblioteka do LoL jest banalnie prosta w użyciu najpierw LedSign::Init(); a potem można używać LedSign::Set do ustawiania/gaszenia diód. Funkca Set ma trzy argumenty współrzędną x, y oraz wartoś 0/1 odpowiednio gaszącą lub zapalającą wybraną diodę. Dlatego pisząc naszą grę można się skupić na samym game play :) zamiast na żmudnym wyświetlaniu…

A na poważnie – potrzebujemy jakiegoś kontrolera do gry. Mój wybór padł na DYI kontroler czyli:

  1. płytkę stykową BB-400
  2. dwa przyciski
  3. trzy rezystory 10k
  4. trochę zworek

Jak to działa? Z rezystorów robimy dzielnik napięcia, między rezystory wpinamy przełączniki, które zwierają do masy jeden lub dwa rezystory. Analog 0 podpinamy między dwa rezystory (w naszym przykładzie między R3 i R2). I tak jeżeli zewrzemy (wciśniemy) S2 wówczas odczyt z A0 będzie 0 – bo ten punkt został zwarty do masy. Jeżeli S2 jest zwolniony a S1 wciśnięty, wówczas A0 będzie wskazywało około 512 – połowa napięcia Vcc gdyż mamy dwa rezystory 10k i mierzymy między nimi napięcie. R1 jest w tym przypadku zwarty do masy z obu stron więc ‘nie bierze udziału’ w naszym układzie. Gdy oba przyciski nie są wciśnięte, wówczas odczyt powinien wynieść około 680 – 2/3 napięcia Vcc (dzielnik napięcia 10k/20k).

Tak po prawdzie, zamiast jednego rezystora można wykorzystać wbudowany w ATMega328 rezystor pull-up na wejściu cyfrowym, ale w tym przykładzie początkowo było więcej przycisków zaplanowanych (tak właśnie jest zrealizowany odczyt z przycisków w LCD shieldzie) i jakoś ten rezystor dodatkowy został w breadbordzie…

Końcowy rezultat wygląda mniej więcej tak:

DIY kontroler gry

DIY kontroler gry

A tutaj schemat i rysunek z Fritzinga, jeśli ktoś potrzebuje sobie zrobić podobny:

Schemat kontrolera

Schemat kontrolera

Rysunek fizycznych połączeń kontrolera

Rysunek fizycznych połączeń kontrolera

Uzbrojeni w wiedzę jak działa kontroler możemy spróbować napisać prostą funkcję odczytującą:

void checkKey() {
  int static prev = 1023;
  
  int r = analogRead(0);
  
  if (r < 20 && prev > 20) {
    key = 1;
  } else if (r >= 20 && r < 530 && (prev < 20 || prev > 530 )) {
    key = -1;
  }
  
  prev = r;
}

Wartość prev jest używana do określenia czy zmienił się odczyt. Słowo kluczowe static powoduje, że zmienna jest inicjalizowana na 1023 tylko za pierwszym wywołaniem funkcji. W następnych wywołaniach wartość prev jest taka jak w momencie zakończenia poprzedniego wywołania.

Odczytujemy wartość z A0 i jeżeli jest bliska zeru i a poprzednio była inna to znaczy, że wciśnięto jeden klawisz. W przeciwnym razie jeżeli wartość jest w okolicy 512 (well, nie przekracza 520, bo 30 trudno uznać za w okolicy 512 ;) ) i jednocześnie poprzednia wartość nie była w tym zakresie to wciśnięto drugi klawisz. Trzecia opcja nic nie robi.

Do szczegółów dlaczego tak zrobiłem jeszcze wrócę.

Teraz – wyświetlacz.

Drogę przechowuję w tablicy road – ma ona tyle wierszy ile jest linii na wyświetlaczu, a w każdym wierszu przechowuję lewą i prawą krawędź drogi (ich współrzędną). Dla uproszczenia całości założyłem, że droga rysowana zawsze ma stałą szerokość, więc w sumie możnaby przechowywać tylko jedną stronę i dodawać/odejmować aby uzyskać drugą współrzędną. Arduino jednak ma na tyle pamięci aby przechować obie. Zresztą dzięki temu łatwiejsze będzie w przyszłości zrobienie na przykład zwężeń drogi.

Jak już droga będzie wygenerowana to musimy ją przesuwać. Służy do tego prosta funkcja shiftRoad:

void shiftRoad() {
  for (int i=MAX-1;i > 0; i-- ) {
    road[i][LEFT] = road[i-1][LEFT];
    road[i][RIGHT] = road[i-1][RIGHT];
  }
}

I tak gdy już zostanie przesunięta droga, dla kompletu potrzebujemy funkcji losującą drogę, która pojawia się na szczycie:

void createRoad() {
  int r = random(0,3);
  switch(r) {
    case 0:
      road[0][LEFT] = road[1][LEFT]-1;
      break;
    case 1:
      road[0][LEFT] = road[1][LEFT]+1;
      break;
    case 2:
      break;
  };

  if (road[0][LEFT] < 0 )
    road[0][LEFT] = 0;
    
  if (road[0][LEFT] > 4 )
    road[0][LEFT] = 4;
    
  road[0][RIGHT] =  road[0][LEFT] + 4;
  
  Serial.print(road[0][LEFT]);
  Serial.print(", ");
  Serial.println(road[0][RIGHT]);
}

Musimy upewnić się, że nam droga nie ucieka z wyświetlacza, dlatego sprawdzamy czy lewa krawędź nie jest za daleko. Jeśli jest, poprawiamy i na końcu wyliczamy gdzie jest prawa krawędź.

Zmienna car przechowuje współrzędną samochodu. I teraz możemy wrócić do wartości którą dostajemy z checkKey – jest to po prostu przesunięcie o ile ma się zmienić położenie samochodu. Gdy żaden klawisz nie został wciśnięty, jest to zero.

Przed przesunięciem gasimy diodę oznaczjącą pozycję samochodu. Potem przesuwamy samochód ( car += key ) i kasujemy wartość key, tak aby przy następnym wywołaniu moveCar nie przesuwać dalej samochodu.

Pozostaje sprawdzić czy czasem nie wpadliśmy na bandę i jeśli tak to zrobić efektowne boom() a jeśli się mieścimy w drodze – wyświetlamy samochód w nowym miejscu.

Teraz tylko wyświetlić drogę:

void displayRoad(){
  for(int i=0; ifor (int j=0; j<9; j++) {
      LedSign::Set(i,j,0);
    };
    //skip drawing line on edge when initializing
    if (road[i][LEFT] >= 0) {
     LedSign::Set(i,road[i][LEFT],1);
     LedSign::Set(i,road[i][RIGHT],1);
    }
}
}

I co jeszcze? Przy starcie musimy jakoś ładnie narysować drogę i dać graczowi chwilę na zorientowanie się gdzie jest. Ta sama procedura jest wykorzystywana po wypadku do odrysowania całego ekranu, stąd swojska nazwa startAgain:

void startAgain() {
  LedSign::Init();
  for (int i=0;i<= MAX; i++) {
    for (int j=0; j<9; j++) {
      LedSign::Set(i,j,0);
    };
    road[i][LEFT] = -1;
    road[i][RIGHT] = -1;
  };
  delay(1000);
  
  road[0][LEFT] = random(0,4);
  road[0][RIGHT] = road[0][LEFT]+4;
  for(int i=0;i< MAX-1; i++) {
   createRoad();
   shiftRoad();
   displayRoad();
   delay(i*20);
  }
  car = road[MAX-1][LEFT]+2;
  key = 0;
  moveCar();
  delay(1000);

};

Ekran jest czyszczony i droga jest generowana wiersz po wierszu z rosnącym opóźnieniem – ponieważ za każdym razem odrysujemy całość, więc wygląda to jakby droga ‘zjeżdżała’ z góry.

Funkcji boom nie muszę specjalnie opisywać, jest to próba narysowania prostego ‘wybuchu’.

Wyjaśnić jeszcze trzeba zawartość loop():

void loop(){
  if (loopCntr++ == 20) {
   shiftRoad();
   createRoad();
   displayRoad();
   moveCar();
   loopCntr = 0;
  } else {
    checkKey();
  };
  delay(10);
};

W każdym przebiegu sprawdzamy czy nie został naciśnięty klawisz. Jeżeli nawet został naciśnięty na chwilę, zostanie to zapisane w key. Klawisz nie musi być naciśnięty w momencie gdy jest odświeżany widok, tylko w każdym przebiegu jest wywoływany checkKey a ewentualny wynik jest zapisywany w zmiennej key.

W co 20stym przebiegu nie sprawdzamy klawiszy tylko:
przesuwamy drogę (shiftRoad)
dodajemy brakującą część na górze (createRoad)
rysujemy aktualny wygląd drogi (displayRoad)
sprawdzamy czy trzeba zmienić położeni samochodu i czy mieści się wsh drodze (moveCar)

Manipulując wartości przy której rysujemy drogę (20) oraz opóźnieniem w każdym przebiegu możemy regulować ‘responsywność’ i szybkość gry.

A jak wygląda całość?

Aha – chiptune w tle jest z komputera (dla klimatu) a nie Arduino :)

Pozostaje ściągnąć kod całości, który jest udostępniony tutaj.

Jak podłączać przyciski (pushbutton, tact switch)

środa, listopad 10, 2010 0:05 by netmaniac | Filled in arduino, dla początkujących

Przyciski (buttony, pushbuttony, tactswitche) są powszechnie stosowanym elementem z Arduino. Jednak czasem dla początkujących irytujące jest właściwe ich podłączenie – część nóżek jest zwarta ze sobą. Wsadzenie przycisku w złej orientacji powoduje, że nie działa. Dlatego kilka słów jak je podłączyć.

Mamy przykładowy przycisk:

Przycisk

Przycisk. Jaki jest każdy widzi.

Jak widać ma on cztery wyprowadzenia. Są one połączone w dwie pary a przycisk dokonuje zwarcia pomiędzy tymi parami. Które wyprowadzanie są połączone na stałe? Może to zdjęcie pomoże to zapamiętać:

Połączone wyprowadzenia

Połączone wyprowadzenia

Do kompletu zdjęcie z naniesionym symbolem:

Przycisk ze schematem

Przycisk ze schematem

Jest teraz jasne, że właściwa orientacja podczas wsadzania w płytkę stykową jest niezbędna. Obrócenie przełącznika o 90 stopni spowoduje wieczne zwarcie, przycisk będzie zworką i nie będzie spełniał swojej roli.

Dla pełnej jasności przykład przycisku w rzeczywistym układzie:

Układ z przyciskiem

Układ z przyciskiem

A tak wygląda z dorysowanym schemat (prawie jak wąsy na plakacie ;) )

Układ z jego schematem

Układ z jego schematem

Rolą tego przełącznika jest zewrzeć rezystor do masy. O tym jak odczytywać wciśnięcie przycisku można na przykład zobaczyć w poście ‘Familiada‘.

A wpis opisujący dokładnie powyższy układ już w trakcie opracowywania :)

Hackerspaces

czwartek, październik 28, 2010 9:48 by netmaniac | Filled in przegląd sieci

Były próby uruchomienia hackerspace w Warszawie, na razie jednak nie ma żadnego tutaj (ogólnie, w Polsce nie ma).

A czym się zajmują hackerspaces tam gdzie są? A to na przykład obejrzyjcie sobie te dwa filmiki (kolejne wkrótce):

Jak ktoś więcej chce zobaczyć, niech odwiedzi stronę PumpingStation: One (HS w Chicago)

Arduino UNO jako joystick

poniedziałek, październik 25, 2010 10:58 by netmaniac | Filled in arduino

Musiało nadejść. Jednym z nowych ficzerów Arduino UNO jest reprogramowalny układ odpowiedzialny za komunikację przez USB.

Joystick

Wirtualny joystick CC by http://www.flickr.com/photos/jon_knox/4711705430/

No, i na forum Arduino pojawił się przepis jak wgrać własny firmware na ten układ, na przykładzie joysticka. Czyli po wgraniu tego firmware Arduino po podłączeniu do komputera zostanie wykryte nie jako port szeregowy a jako joystick.

Chcę więcej wyjść cyfrowych!

środa, październik 20, 2010 22:50 by netmaniac | Filled in arduino

Arduino oferuje sporo wyjść cyfrowych, ale czasem chciałoby się ich mieć więcej… Jak podłączysz klawiaturę oraz LCD to dużo wolnego nie zostaje…

Dziś natknąłem się na proste rozwiązanie – EZ Expanedr shield. Shield korzysta z dwóch rejestrów przesuwnych 74HC595 aby ‘rozmnożyć’ wyjścia cyfrowe. Oczywiście rozmnożone wyjścia cyfrowe będą do użycia tylko i wyłącznie jako wyjścia (nie ma odczytu z takiego ekstra wyjścia).

EZ Expander CC by http://nootropicdesign.com/ez-expander/

Shield jak shield, ale jeżeli potrzebujesz więcej wyjść (diody LED?) to możesz wykorzystać samą bibliotekę EZ Expandera i dowolne rejestry przesuwne (74HC595 jak najbardziej może być :) ). Czyli podpiąć rejestry i z nich korzystać wysyłając wartości przez proste digitalWrite – zobacz dokumentację w sekcij ‘Advanced API usage’. Tego advanced nie należy się za bardzo bać :)

A z innych ciekawostek od nootropic to trzeba wymienić platformę video na Arduino – Hackvision. Korzysta ona z TVout – biblioteki do generacji obrazu przez AVRy (czyli Arduino też). A jeżeli chcesz się przekonać jak generować obraz z Arduino to zajrzyj do Sprae, który temat bardzo dokładnie opisał (Arduino jako karta graficzna – szukaj tam postów o takim temacie – w tej chwili 4 części) – na swoim kodzie nie od TVout.

Co właściwie mierzy analogRead() ?

niedziela, październik 10, 2010 21:25 by netmaniac | Filled in arduino, dla początkujących
Kable, kable...

Kable, kable...

Widzicie to kłębowisko? To się oficjalnie nazywa stanowisko testowe LCD kitów. Po prostu – po zlutowaniu partii, każdy trzeba podłączyć aby sprawdzić czy świeci i wyświetla jak należy. Mógłby to być jakiś głupawy tekst, ale to byłoby zbyt proste.

Dlatego wśród kłębu kabli jest ukryty czujnik temperatury MPC9700 (a raczej dwa) i na LCD wyświetla się po prostu odczyt z niego. Wczoraj w nocy jakoś mnie zaintrygowało temperatura jaką wyświetlało Arduino. Była za wysoka, zdecydowanie. Różnicę między 21 a 24 każdy z nas dobrze zauważy (zdjęcie zrobiono w innych warunkach termicznych :) ). A zrzucić tego na niedokładność pomiaru trudno, bo czujnik ma przecież dokładność +/- 2 st.

Ponadto, raz czy dwa w rozmowie z klientami słyszałem takie opinie, że pokazuje za dużo (czujnik, czujnik :) ). Dlatego zacząłem grzebać i próbować różnych rzeczy.

Jak działa przetwornik napięcia?

Przetwornik analogowo cyfrowy ADC jest dokładnie opisany w nocie katalogowej ATmega328 strona 250. W dużym skrócie: napięcie AREF jest napięciem zasilającym przetwornik DAC (podzielnik napięcia sterowany cyfrowo) którego wyjście jest podłączone do komparatora porównywającego je z napięciem wejściowym na danym wejściu analogowym. Napięcie z przetwornika DAC ‘startuje’ od zera i jest zwiększany aż osiągnie maksimum lub komparator wykaże przekroczenie poziomu sygnału badanego. Dzięki temu wiadomo jaką wartość ma badany sygnał.

Od razu rzuca się w oczy co wpływa na dokładność takiego pomiaru. Pierwsza rzecz to rozdzielczość (w bitach) przetwornika DAC – inaczej z jakim krokiem zwiększane jest napięcie do porównywania. ATmega328 ma 10-cio bitowy.

Druga wartość to napięcie AREF. Jeżeli liczba kroków jest określona (1023 bo 10 bitów) to wiadomo jakie napięcie przypada na krok. Jest to AREF/rozdzielczość. ATmega może korzystać z 3 różnych źródeł napięcia AREF. Może to być wewnętrzne źródło 1.1V (nie wiem jakiej dokładności), napięcie zasilania (około 5V) lub wartość podana na pin AREF.

Znajomość tej wartości jest konieczna tak aby móc przeliczyć odczyt cyfrowy z przetwornika na rzeczywistą wartość napięcia. Pomińmy na razie opcje korzystania z wewnętrznego źródła 1.1V oraz z podawania AREF własnoręcznie. Skupmy się na domyślnej wartość AREF – 5V.

Teraz kłania się nam podstawowa informacja o czujniki MCP9700 – czyli czułość. Wynosi ona 10mV/st C – dlatego jeżeli chcemy odczytywać dokładnie to co podaje czujnik to musimy znać dokładną wartość AREF.

Może na przykładzie

Odczyt z analogRead() dał nam 150. Myślimy że napięcie odczytane to 5/1024*150 = 0.7324 V. Jest to prawda, jeżeli AREF faktycznie wynosi 5V. A jeżeli ma naprawdę 4.9V? To wówczas prawdziwa wartość jaką oznacza odczyt 150 to: 0.7178V. Różnica – 14.6 mV. Dla czułości 10mV/C – prawie 1.5 stopnia!

A ile wynosi dokładnie ten AREF w domyślnym ustawieniu? Niby 5V, ale tak naprawdę Vcc (napięcie zasilania) podane na ATmega328.

Zaraz, powie ktoś, przecież Arduino ma na sobie regulator napięcia na 5V, więc taka duża różnica nie powinna występować. Prawda. Ale tylko jeżeli zasilamy Arduino przez gniazdo zasilania, a nie przez USB!

Jak wiadomo, standard USB mówi, że napięcie zasilania wynosi 5V, więc regulator napięcia nie działa, napięcie z kabla USB idzie prosto do ATmega. A regulator napięcia nie działa, bo żeby dostarczyć regulowane 5V to musi dostać więcej aby mieć z czego regulować, więc nie ma technicznej (prostej) możliwości regulacji zapewniającej 5V jeśli napięcie zasilania to też 5V.

Inaczej mówiąc jesteśmy zdani na to co komputer podaje na USB. I tutaj właśnie zostałem zaskoczony, bo mój notebook na porcie USB najwyraźniej podaje 4.9 V zamiast równych 5V.

Finalnie – przez to odczyt w moim przypadku był zawyżony o te 1.5 stopnia.

Ale, jeżeli skorzystać z analogReference(INTERNAL); to rezygnujemy z górnych zakresów odczytu (bo maksymalny odczyt to 1.1V czyli po przeliczeniu na temperature (1.1-0.5)/0.01 = 60 stopni) na rzecz zwiększenia dokładności odczytu (1.1/1024 = ok 1mV, tj 0.1 C) . Jeszcze raz uwaga – zwiększenie dokładności odczytu nie pomiaru :)

To tyle w dużym skrócie jeżeli chodzi o to co naprawdę mierzy analogRead. Ażeby wyjaśnić czemu na zdjęciu jeden odczyt to 18 stopni a drugi 20 – nie jest to jakaś magia związana z analogRead – jeden z czujników MCP to wersja A a drugi bez A w numerku. Ten z A (dołączony do Starter Kitu jak i sprzedawany samodzielnie) ma dokładność odczytu +/i 2 a bez A +/- 4 stopnie).