Programowanie AtTiny85 przez Arduino UNO

Zastosowanie ‚normalnej’ płytki Arduino jest najczęściej najszybszym sposobem na stworzenie prototypu. Uniwersalny przepis brzmi:

  • Weź Arduino UNO, płytkę stykową, kilka kabelków połączeniowych,
  • Wepnij projektowany układ na płytce stykowej (tzw ‚pająk’),
  • Otwórz nowy szkic w środowisku Arduino IDE, dodaj biblioteki, wpisz kod,
  • Podepnij Arduino kable USB do komputera, zapisz na niego nowy kod,
  • Podepnij Arduino do płytki stykowej (zasilanie i logikę),
  • Gotowe do testowania!

Jednak gdy trzeba się zmieścić w ciasnej obudowie, a część peryferiów Arduino nie jest potrzebna w docelowym rozwiązaniu – zamiast Arduino można pomyśleć o czymś znacznie mniejszym.

attiny85_04Wyrzekając się eleganckiej płytki, bagażu obsługi USB, stabilizatora, gniazd wyprowadzeń pinów i mas z każdej strony, całej tej uniwersalności – możemy znacznie zredukować rozmiar końcowego produktu.

Poznajcie AtTiny85 – mikrokontroler z firmy Atmel. Czym różni się od zamontowanego na Arduino UNO R3 AtMega328p? A przede wszystkim – jak go zaprogramować?

Co to jest Arduino?

Zacznijmy od sedna sprawy: czym właściwie jest Arduino? W ogólnym zarysie, Arduino składa się z dwóch zasadniczych części:

  • Kontrolera, wyprodukowanego przez firmę Atmel, pochodzącego z rodziny AVR/AtMega,
  • Płytki PCB, na której osadzono sam kontroler oraz zestaw dodatkowych komponentów, gniazd i wyprowadzeń portów.

Kontrolery (czy też mikrokontrolery) Atmela AtMega były z nami od lat. Bawiłem się nimi jeszcze na studiach (czytaj: więcej niż 20 lat temu, na zmianę z ’51). Nie są więc żadną nowością. Używanie ich nigdy nie było specjalnie skomplikowane – nawet dla… początkującego inżyniera lub studenta elektroniki:) Pod pojęciem „niespecjalnie skomplikowane” ukrywa się tu konieczność posługiwania się programatorem, tajemna wiedza jak go podłączyć, ustawić fusy, jakie kwarce dodać itp. Do tego dochodziły przedziwne i egzotyczne języki programowania, gdzie nie było ‚setup()’ ani ‚loop()’ – co gorsza, środowiska programowania, które nie można było obsłużyć myszką.

Arduino znacząco zmieniło tą sytuację.

Dzięki wszystkim dodatkom na płytce Arduino UNO, używanie kontrolera Atmel stało się bardzo wygodne. Dodatkowy czip umożliwił komunikację z komputerem po porcie USB. Bootloader w pamięci kontrolera, odpowiedzialny za ładowanie Waszych programów z komputera do AtMega, sprawił, że osobny programator nie jest już wymagany.

Specjalnie zaprojektowane (i darmowe!) środowisko graficzne Arduino IDE znacznie ułatwiło pisanie programów.

Dodatkowy stabilizator na płytce, wyprowadzenie portów kontrolera na gniazda pinowe – dzięki takiemu zestawowi, kontrolery Atmela może używać praktycznie każdy bez specjalnego przygotowania inżynierskiego.

Oczywiście każde uproszczenie prowadzi do pewnych ograniczeń. Wychodzą one na wierzch najczęściej, gdy decydujemy się opuścić utarte ścieżki. Wtedy okazuje się, że np. bootloader zajmuje wcale nie taką małą część pamięci, wprowadzane przez niego opóźnienie przy starcie – irytuje, przydałby się inny zegar niż ten, który jest zamontowany na płytce a stabilizator mógłby być mocniejszy.

Dodatkowo, Arduino ma swój gabaryt.

Gdy skomponujemy wszystkie elementy układu, napiszemy i przetestujemy na prototypie całe oprogramowanie, w ostatecznej aplikacji warto użyć… samego kontrolera. W gotowym projekcie, z rozwiązanym zasilaniem, wykorzystaniem pinów i zidentyfikowaną wymaganą funkcjonalnością – może okazać się, że większość ‚gratów’ dodawanych przez Arduino nie jest już potrzebna. Istnieje wtedy możliwość przesiadki na coś bardziej zgrabnego. Zamiast całej płytki Arduino, możecie użyć samego kontrolera. Może to być AtMega328p – który napędza Arduino UNO R3. Możecie jednak pójść o krok dalej i – jeżeli projekt na to pozwala – zredukować cały blok sterowania do … 8-nóżkowego AtTiny85.

O co chodzi z tym bootloaderem?

Kontrolery jak AtMega mają wbudowane kilka rodzajów pamięci:

  • Pamięć programu (flash),
  • Pamięć EEPROM,
  • Pamięc operacyjną,

Każda z nich służy do czego innego. W pamięci programów przechowywane są programy, które kontroler wykonuje. Pamięć ta nie znika po wyłączeniu zasilania. Pamięci tej nie możecie jednak wykorzystać bezpośrednio w swoim programie – np. zapisać w niej dane. Do zapisywania danych służy EEPROM. Jeżeli np. chcecie zapamiętać wyniki zebranych pomiarów – możecie wysłać je do EEPROM. EEPROM również nie znika po wyłączeniu zasilania. Trzecia z pamięci – RAM – to pamięć, w której wykonują się programy – na przykład trzymane są wartości zmiennych. które wykorzystujecie w programie. Ta pamięć jest ulotna, tzn. znika po wyłączeniu zasilania.

Teraz interesuje nas pamięć programów (flash) – czyli ta, w której nagrywane są programy. Gdy tworzycie szkic w Arduino IDE, specjalne narzędzie (kompilator, linker) tłumaczą je na postać zrozumiałą dla kontrolera i wysyłają na kontroler. I to właśnie bootloader „odbiera” Waz program po stronie kontrolera i zapisuje go w pamięci.

Ostatecznie, w przypadku Arduino, w pamięci flash znajdują się 2 programy: bootloader i ten, który właśnie napisaliście i załadowaliście.

W konsekwencji:

  • Środowisko Arduino IDE będzie mogło zaprogramować Wasze Arduino przez USB tylko wtedy, gdy na kontrolerze jest odpowiedni bootloader; na szczęście jest on tam umieszczany fabrycznie,
  • Gdy zasilacie płytkę Arduino (albo ją restartujecie), zawsze pierwszy uruchamia się bootloader i sprawdza, czy „ktoś” nie chce podesłać mu nowego programu; tym „ktosiem” jest środowisko programowania Arduino IDE (chociaż nie koniecznie),
  • Jeżeli Arduino IDE chce wysłać nowy program na kontroler musi najpierw zrestartować kontroler (żeby uruchomił się bootloader).
  • Bootloader odbiera nowy program i zapisuje go w miejsce poprzedniego; w pamięci kontrolora nie może być więc więcej niż jeden szkic użytkownika (i bootloader),
  • Jeżeli bootloader nie wykryje, że środowisko chce załadować nowy program – uruchamia ten, który jest już w pamięci;
  • Zanim bootloader „odpuści” sobie czekanie na nowy program – mija trochę czasu; programy na Arduino nie startują więc natyczmiast – najczęscie po ok. 3 sekundach.

Jest wiele różnych bootloader’ów, tutaj chodzi o ten przeznaczony dla płytek Arduino – możecie nazywać go bootloader Arduino. Inny, o którym pisałem już na blogu, to np. micronucleus z Digisparków.

ICSP?!

Załóżmy teraz, że w pamięci kontrolera nie ma bootloadera. Nie nagrano go w fabryce, uległ uszkodzeniu lub sami go nadpisaliśmy (zdara się:)).

Nie ma więc programu, który będzie odbierał nasze szkice i zapisywał je we flashu kontrolera. W konsekwencji – nie zaprogramujecie go z poziomu Arduino IDE. Przy takiej próbie, w okienku wyników zobaczycie pewnie coś jak:

Nie ma strachu – są inne możliwości zaprogramowania AtMega. Można na przykład użyć ICSP: In-Circuit Serial Programming (programowanie szeregowe w układzie).

ArduinoUNO ma aż 2 interfejsy ICSP: do programowania kontrolera (328P) i AtMega16u2 odpowiedzialnego za komunikację po USB
ArduinoUNO ma aż 2 interfejsy ICSP: do programowania kontrolera (328P) i AtMega16u2 odpowiedzialnego za komunikację po USB

ICSP to programowanie kontrolerów (np. Atmel’a) poprzez ich port SPI (Serial Programming Interface). W ten sposób jakby bezpośrednio wpisujemy nowy program do pamięci flash kontrolera, bez pośrednika jakim był bootloader. W pamięci flash jest tylko stworzony przez nas program. Plusy? Więcej pamięci na programy, szybki start. Minusy? Brak bootloadera sprawi, że Waszą płytkę nie będzie można bezpośrednio zaprogramować przez Arduino IDE – chociaż nadal można go użyć do pisania programów. Do wgrania programu na kontroler będziecie potrzebowali programatora ICSP. Programator ICSP możecie kupić jako osobne urządzenie – np. USBASP2. Podłączacie go z jednej strony do portu USB a z drugiej – do samego kontrolera.

USBASP2
USBASP2

W roli ICSP możecie też użyć Arduino UNO.

Przedmiotem tego tekstu jest właśnie programowanie kontrolera, na którym nie ma bootloadera, a pomocą Arduino UNO. Użyję tu trochę innego kontrolera niż ten montowany w Arduino UNO: AtTiny85. Kontroler ten nie ma fabrycznie wgranego bootloadera Arduino – w roli ICSP użyjemy Arduino UNO. Podłączymy je do AtTiny tak, żeby UNO zadziałało jak programator ICSP. Dzięki takiemu układowi, dalej będziemy mogli używać Arduino IDE. Wystarczy napisać program, wcisnąć jeden przycisk – a UNO zaprogramuje nam AtTiny. Do roboty.

AtTiny85

Spójrzcie na niego: ma tylko 8 nóżek:

AtTiny 85 - piny (pobrano z instrukcji)
AtTiny 85 – piny (pobrano z instrukcji)

Do uruchomienia wystarczy podłączyć Vcc i Reset do zasilania, GND do masy:

AtTiny85 - podłączenie
AtTiny85 – podłączenie

Zauważcie, że większość pinów ma podwójne funkcje:

  • Generacja PWM: 2,3, 5, 6,
  • Przetwornik A/C: A1 (pin 7), A2 (pin 3), A3 (pin 2),
  • Porty uniwersalne: pin 2 (PB3), pin 3 (PB4), pin 5 (PB0), pin 6 (PB1), pin 7 (PB2).

Oto porównanie możliwości układów:

AtTiny85/DIP8 AtMega328/DIP28 (osobno) AtMega328 w UNO
Pamięć kodu 8kB 32kB 32kB – bootloader
Pamięć zmiennych 512B 2048B 2048B
Pamięć EEPROM 512B 1024B 1024B
Częstotliwość 20MHz 20MHz 16MHz
Napiecie pracy 1.8-5.5V 1.8-5.5V 5V USB lub 7-12V (Vin)
Liczba GPIO 6 23 14 uniwersalnych + 6 analogowych wejść

Arduino jako programator

Poniższy sposób oparłem na tekście z bloga: High-Low Tech.

Przy stosowaniu kontrolerów typu AtTiny problemem był zawsze.. programator. W płytkach Arduino rozwiązano to dodając możliwość komunikacji po USB. Dzięki dodatkowemu bootloaderowi w pamięci flash kontrolera (który oczywiście pomniejsza miejsce dostępne dla kodu programu), wyeliminowano konieczność używania wyspecjalizowanego programatora ISP. Podłączając Arduino do komputera za pomocą kabla USB, zasilamy je jednocześnie uzyskując możliwość programowania i podglądania portu szeregowego.

Jeżeli chcecie użyć Arduino w roli programatora AtTiny, musicie połączyć je następująco:

Pin Arduino Pin AtTiny85
5V 8: Vcc
GND 4: GND
D10 1: Reset
D11 5: MOSI
D12 6: MISO
D13 7: SCK

Dodatkowo potrzebny będzie większy kondensator (np. 10uF) wpięty między pin Reset (+ kondensatora) i masę (-kondensatora). Powstrzyma on Arduino od resetowania się po załadowaniu nowego kodu.

Na płytce stykowej:

attiny85_00

Lub na płytce shield’owej:

attiny85_05Wykorzystałem tu podstawkę typu ZIFF. Umożliwia ona łatwy montaż/demontaż AtTiny z programatora.

Arduino IDE dla AtTiny85

Do pisania programów pod AtTiny85 możecie użyć tego samego środowiska Arduino IDE.

26 Marzec 2016: kompilacja dla AtTiny85 kończy się porażką pod Arduino IDE 1.6.6. Pomogło uzupełnienie do najnowszej 1.6.8.

Uzupełnijcie teraz Arduino IDE o obsługę AtTiny85:

  • Uruchomcie Arduino IDE,
  • Z menu wybierzcie Plik/Preferencje
  • Kliknijcie przycisk znajdujący się za polem „Dodatkowe adresy URL”; otworzy się okienko:
    Clipboard01
  • W okienku wpiszcie adres:

    Zatwierdźcie ok na tym okienku i okienku preferencji
  • Przejdźcie teraz do menu „Narzędzia/Płytka” i wciśnijcie „Menedżer płytek”…
    Clipboard02
  • W otwartym okienku „Menedżer płytek”, odnajdźcie na liście „attiny” i kliknijcie przycisk „Instaluj”:
    Clipboard03
    Zamknijcie okienko klawiszem „Zamknij”.
  • Zanim zmienicie ustawienia: otwórzcie przykład Pliki/Przykłady/Arduino ISP.
  • Podłączcie do komputera Arduino UNO, które będzie używane jako programator.
  • Zaprogramujcie to UNO szkicem ArduinoISP.
  • Otwórzcie nowy projekt
  • Na liście płytek pojawi się AtTiny:
    Clipboard04
    Pojawią się Wam teraz dodatkowe elementy w menu:
    Clipboard06
  • Dla AtTiny85 wybierzcie: Procesor/ATiny85, Clock: 1MHz internal
  • Wybierzcie programator: Narzędzia/Programator/Arduino as ISP

Podłączcie AtTiny85 do Arduino UNO jak powyżej. Teraz jesteście gotowi do pisania swoich szkiców.

Pamiętajcie o wgraniu szkicu ArduinoISP na Arduino, które będzie programatorem.

Programowanie

Dzięki rozszerzeniu Arduino IDE o wsparcie dla AtTiny85, następujące komendy powinny działać:

  • pinMode()
  • digitalWrite()
  • digitalRead()
  • analogRead()
  • analogWrite()
  • shiftOut()
  • pulseIn()
  • millis()
  • micros()
  • delay()
  • delayMicroseconds()

Rozkład pinów:

attiny85_pins

Przykładowe komendy będą odwoływać się do pinów AtTiny85:

W programie Pin fizyczny AtTiny
digitalWrite(3, HIGH); Ustaw fizyczny pin 2 na wartość wysoką
digitalWrite(4, LOW); Ustaw fizyczny pin 3 na wartość niską
analogWrite(1, 127); Wygeneruj sygnał PWM na fizycznym pinie 6 o stopniu wypełnienia 50%
analogWrite(0, 255/4); Wygeneruj sygnał PWM na fizycznym pinie 5 o stopniu wypełnienia 25%
analogRead(A1) Odczytaj wartość napięcia na fizycznym pinie 7
analogRead(A3) Odczytaj wartość napięcia na fizycznym pinie 2

Musicie jednak zdać sobie sprawę z tego, że nie wszystkie biblioteki działające np. z Arduino UNO, będą działać z AtTiny85. Rozszerzenie gwarantuje poprawne działanie biblioteki SoftwareSerial. Poza nim kod musicie pisać sami, lub zaopatrzyć się w bibliotek specyficzne dla AtTiny85.

Przykład: blink

Pamiętajcie żeby Arduino IDE skonfigurowane było dla AtTiny! Upewnijcie się, że Narzędzia>Płyta wskazuje AtTiny.

Do fizycznego pinu 2 (D3) podłączcie rezystor 360Ω a do niego krótszą nóżkę LED. Drugą nóżkę LED podłączcie do zasilania.

attiny85_01Szkic:

LED będzie rytmicznie mrugać.

Przykład: port szeregowy

Dzięki wypisywaniu danych na porcie szeregowym możecie zobaczyć, co się dzieje w Waszym programie. Do AtTiny podłączcie przejściówką UART-USB:

  • GND przejściówki do GND AtTiny,
  • 5V przejściówki do Vcc AtTiny,
  • RX przejściówki to pinu D3 AtTiny (fizyczny 2),

attiny85_02Otwórzcie nowy szkic. Dodajcie do niego bibliotekę SoftwareSerial (Szkic>Dodaj bibliotekę>SoftwareSerial). Zaprogramujcie następujący szkic:

Wyjście z przejściówki możecie zobaczyć z użyciem Putty (Windows). Dla linuxa jest prościej:

Przykład: wejście analogowe

Wgrajcie kolejny program:

Uruchomcie konsolę szeregową, zobaczycie coś jak:

Kolejne linijki zawierają wyjście z przetwornika analog/cyfra na pinie A2 (fizyczny 3). A teraz podłączcie do niego 3.3v z Arduino UNO. Wyjście natychmiast się zmieni:

Pin zareagował. Możecie przeliczyć sobie 674 na wartość zmierzonego napięcia korzystając z proporcji:

{{5v} \over {1021}}={{xv} \over {674}}

Stąd:

{xv} = {{674 \cdot 5v} \over {1021}}=3.3v

Ćwiczenie: uzupełnijcie program tak, żeby sam przeliczał wyjście z A2 na wolty.

Fizyczny pin 3 wykorzystałem tu podwójnie: jako wejście rx konsoli szeregowej (D4) i jako wejście konwertera analog/cyfra A2. To nie jest najlepsza praktyka, zrobiłem tak jedynie dla ilustracji.

Przykład: generacja PWM

Teraz wygenerujemy sygnał PWM:

  • Na pinie D1: sygnał 50%,
  • Na pinie D0: sygnał 25%.

Kod wygląda następująco:

Przebiegi wywołane na oscyloskopie:

attiny85_03

Dodatkowo: odczytywanie fuse bitów

Za pomocą Arduino grającego rolę programatora ISP można odczytywać fuse bity AtTiny. Wystarczy podłączyć taki programator Arduino z wpiętym AtTiny, do portu USB (podobnie jak przy programowaniu przez Arduino IDE) oraz użyć avrdude, np:

Źródła

8 komentarzy do “Programowanie AtTiny85 przez Arduino UNO”

    1. Witam,
      cieszę się, jeżeli coś się przyda. Właśnie siedzę nad programatorem HighVoltage do AtTiny – już niedługo pojawi się na stronie:)
      Pozdrawiam,
      Arek

Dodaj komentarz

Proszę dodaj swój komentarz. Pamiętaj, żeby nie podawać żadnych danych osobowych.