středa 18. listopadu 2015

ArduinoISP s NANO - levný USB programátor pro Atmel AVR mikrokontroléry

Úvod

Naprogramovat mikrokontrolér je v podstatě jednoduchá věc. Potřebujete vlastně jen programátor, tedy kus hardware, který dokáže komunikovat s daným mikrokontrolérem a nahrát do něj program. Programátor komunikuje s počítačem prostřednictvím programovacího softwaru, který umí přečíst soubor s skompilovaným programem a přez vhodné rozhraní ho poslat programátoru, který ho potažmo nastrká do mikrokontroléru.

   V případě dnes tolik rozšířeného Arduina je hardwarový programátor vlastně integrován přímo do samotného Ardunia a nahrávání programu probíhá přímo z arduinovského vývojového prostředí, většinou přes USB rozhraní.

Když jsem před lety začínal s programováním  mikrokontrolérů Atmel AVR, nebylo to tak jednoduché a úspěšné prošlapání cestičky od programovacího software přes hardwarový programátor a náležitou konfiguraci obojího, až po úspěšné nahrání prvního programu byla zásadní překážka, kterou musel každý adept tohoto umění na počátku své kariéry překonat.  Ta moje cestička, kterou jsem od té doby až dosud používal  byla založena na velmi pěkném a intuitivním programovacím prográmku PonyProg a hardwarovém programátoru založeném na paralelním portu (LPT), běžně tehdy rozšířeném na většině stolních počítačů a i na některých laptopech.

Jenže pokrok jde nezadržitelně dopředu. Paralelní porty jsou doslova na vymření i na stolních počítačích, na noteboocích je už prostě nenajdete.  Kromě toho, můj oblíbený PonyProg také nestíhá krok s dobou a v současnosti nepodporuje jednak modernější programátory komunikující pomocí USB, a dále celou řadu novějších mikrokontrolérů. Takže ač nerad byl jsem přinucen prošlapat si cestičku novou. A vzhledem k tomu, že jsou moje mikrokontrolérové aktivity stále veskrze nekomerční, snažil jsem se to udělat zalevno.

Nová Varianta:  AVRDUDE + Arduino NANO + ArduinoISP

Malé a laciné Aruduino NANO se stalo základem celé řady mých nedávných projektů. Umí takřka to samé co větší UNO včetně USB komunikace (formou virtuálního COM portu) takže v malém balení je doslova vše co je zapotřebí pro menší mikrokontrolerové projekty. Přiznám se, že kupuji levné čínské klony, které se dají pořídit pod 100 korun.  Aby byla věc ještě trochu jednodušší, přímo v arduinovském vývojovém prostředí je k dispozici příklad programu pro využítí arduina jakožto harwarového programátoru pro AVR mikrokontroléry. Lze ho najít pod: File>Examples>ArduinoISP.  V poznámkách v tomto prgramu je popsané i zapojení jednotlivých pinů pro připojení Arduina k mikrokontroléru. To celkem výrazně zjednodušuje situaci. Jedinou drobnou komplikací je, že PonyProg se s takovýmto programátorem neumí dohodnout. Tedy přinejmenším jsem zatím nenašel způsob jak by spolu komunikovali. Takže bylo zapořebí také použít jiný programovací software.  A zde přichází na scénu AVRDUDE. Je to trošku ironie. AVRDUDE je totiž na jednu stranu velmi pokročilý software, který komunikuje s velkým množstvím různých programátorů (včetně toho vyrobeného z Arduina) a umí naprogramovat asi všechny dostupné AVR mikrokontroléry (včetně XMega řady), na druhou stranu je to doslova dinosaurus, který se spouští a ovládá přez příkazovou řádku.  Já sice ledacos pamatuji, včetně dob, kdy PC měla POUZE  příkazovou řádku a mám i dlouhou zkušenost s unixem takže mě v tomto směru jen tak něco nerozhodí, ale na druhou stranu nejsem skalní programátor ani systémový administrátor abych se na příkazové řádce vyskytoval příliš často.  AVRDUDE má docela spoustu různých nastavení, kterými se člověk musí prokousat aby ta věc skutečně fungovala. Trvalo mi to jedno celé odpoledne a tak tyto řádky píšu s nadějí, že a) mi osvěží paměť až to budu dělat příště b) případně poslouží někomu dalšímu pokud se  s podobným problémem bude potýkat.

NUTS and BOLTS aneb jak na to:

A) Zapojení Arduina a propojení s mikrokontrolérem:
AVR mikro se programuje pomocí SPI seriové komunikace.  Potřebuje následující vodiče pro komunikaci mezi prográmátorem a mikrokontrolérem:
Vcc ... napájecí napětí (+5V)
GND ... zem
SCK ... hodinové synchronizační pulzy
MOSI ... Master Out Slave In signál
MISO ... Master In Slave Out signál
RESET ... uzemněním tohoto vodiče přejde mikrokontrolér do programovacího módu.

Celkem tedy 6 vodičů.  Ty jsou v Arduinu NANO připojeny k následujícím digitálním pinům:

NANO                      Atmel AVR*
----------------------------------------------
+5V                            Vcc
GND                           GND
D10                             RESET
D11                             MOSI
D12                             MISO
D13                             SCK
-----------------------------------------------

*pozice jednotlivých pinů na konkrétním AVR mikrokontroléru je třeba dohledat v katalogovém listu.



Mimochodem stejné piny jsou použity i pro Arduino UNO. 

Kromě toho se doporučuje připojit tři LED diody s předřadnými odpory (cca 200 - 1000 Ohm) na piny D7, D8, D9.  Ty sice nejsou nezbytně nutné pro funkci programátoru, dávají však jistou vizuální zpětnou vazbu o jeho stavu:
D7 se rozsvítí, když programátor zrovna komunikuje s mikrokontrolérem.
D8 se rozsvítí když dojde k chybě.
D9 rytmicky poblikává jako indikace, že program běží (tzv. heartbeat, neboli tlukot srdce).



Program běží i bez těchto diod, ale není vidět zda něco opravdu dělá. Můžete je vynechat, když budete mít komunikaci bezpečně vyzkoušenou.   

DÁLE PŘIPOJTE KONDENZÁTOR 10uF ČI VÍCE MEZI RESET (PIN28) ARDUINA A ZEM. TO ZABRÁNÍ RESETOVÁNÍ ARDUINA BĚHEM ZAHÁJENÍ KOMUNIKACE S AVRDUDE. TENTO KONDENZÁTOR JE VŠAK TŘEBA PŘIPOJIT AŽ POTÉ, CO JSTE NAHRÁLI ArduinoISP SKETCH DO ARDUINA. Tedy přinejmenším buďte připraveni tam tento kondenzátor dát v případě problémů s resetováním Arduina při komunikaci mezi AVRDUDE a Arduinem, viz. chybové hlášky níže. Údajně některá NANO se resetují, jiná nikoli. To moje se resetovalo, přidal jsem kondenzátor a problém zmizel. 
 
B) ArduinoISP sketch a AVRDUDE konfigurace.
Program (sketch) ArduinoISP jsem do Arduina NANO nahrál bez větších problémů, použitá verze Arduino IDE je 1.6.6 (11/2015).

AVRDUDE jsem do Windows (W7) musel nahrát ačkoli Arduino někde vnitřne AVRDUDE také používá.  Nejjednodušší je instalovat kompletní balík utilit pod názvem WinAVR, který lze stáhnout na sourceforge. AVRDUDE se spouští z příkazové řádky, je tedy zapotřebí spustit terminálové okno napsáním příkazu CMD do okénka start v levém dolním rohu Windows.
Abyste zjistili, zda je program nainstalovaný, stačí na příkazový řádek napsat: avrdude (bez jakýchkoli parametrů) program by měl vrátit stručný help s výpisem nastavitepných parametrů programu. Pro úspěšnou komunikaci mezi AVRDUDE a programátorem (+ mikrokontrolérem) jsem potřeboval nastavit následující parametry:

-p ... označení programované součástky. Např. pro Atmel Mega8 je hodnota m8
-c ... označení programátoru: pro Arduino s ArduinoISP sketchem je hodnota arduino
-P ... označení portu na kterém programátor komunikuje. Je třeba vložit správnou hodnotu portu,
         na kterém máte rozpoznané vaše NANO. Např. lze zjistit v tools v Arduino IDE.
-b ... baudrate pro komunikaci mezi PC a Arduinem. Pro ArduinoISP je standartně 19200.
-U ... specifikace operace <memtype>:r|w|v:<filename>:format. Zde <memtype> je typ paměti která se
         má číst/zapisovat (např. programová paměť je "flash"). Druhý parametr znamená:
          r...read, w...write, v...verify.
         <filename> je  jméno souboru, ze kterého se čte, případně kam se zapisuje.
          format specifikuje formát tohoto souboru, zatím jsem tesoval pouze s hodnotou i což
          znamená binární .hex formát.

Vše dohromady - následující příkaz byl schopen přečíst obsah programové (flash) paměti u AVR Mega8 mikrokontroléru a zapsat ji do souboru dudetest.hex:

avrdude -p m8 -c arduino -P com10 -b 19200 -U flash:r:dudetest.hex:i

Podobně zapsání programu ze souboru filename.hex do programové paměti kontroléru provedeme příkazem :
avrdude -p m8 -c arduino -P com10 -b 19200 -U flash:w:filename.hex:i

C) Nastavení kontrolních bitů mikrokontroleru:
Kontrolní bity, takzvané "fuses" umožňují nastavení některých parametrů procesoru, jako kupříkladu typ a rychlost systémových hodin. Pro jejich nastavení pro konkrétní procesor je potřeba prostudovat důkladně katalogový list daného chipu. Konkrétnní AVR kontrolér může mít až tři kontrolní byty.označené v AVRDUDE jako hfuse, lfuse a efuse. V příkladu který tu uvádím jsem v přenastavoval lfuse pro ATtiny26 procesor pro změnu rychlosti vnitřních systémových hodin. Spodní 4 bity určují rychlost vnitřních hodin (1...1MHz, 2 ... 2MHz, 3 ... 4MHz, 4 ... 8MHz) Horní 4 bity přitom musí být zachovány na hexadecimální hodnotě E (1110 binárně). AVRDUDE příkaz, který tyto bitty nastaví pro 4MHz vnitřní hodiny pak bude:


avrdude -p t26 -c arduino -P com10 -b 19200 -U lfuse:r:0xe3:m

parametr m na konci příkazu je z immediate. Místo aby AVRDUDE četl data ze specifikovaného souboeru, přečte si přímo hodnotu specifikovanou místo jména souboru na příkazové řádce (v tomto příkladu hexadecimální hodnotu 0xe3). To je velmi praktické právě pro zapisování do fuses, kde se zapisuje jediný byte a bylo by zbytečné kvůli tomu tvořit soubor s jedinou hodnotou.
   Nakonec slovo varování: ke kontrolním bitům je třeba přistupovat s patřičným respektem. Jejich neuvážené přepsání na jinou hodnotu může způsobit, že mikrokontrolér přestane fungovat jak má. Například, když změníme nastavení z vnitřích hodin na vnější oscilátor, tak procesor nepoběží pokud nebude oscilátor s patřičnou frekvencí vskutku připojen. Takže si opravdu dobře přečtěte ty katalogové listy, než začnete měnit kontrolní bity.

D) chybové hlášky AVRDUDE
Napoprvé to samozřejmě nefungovalo a celkem dlouho mi AVRDUDE vracel chybovou hlášku:

stk500_getsync(): not in sync: resp=0x15 .

Zjistil jsem, že to je způsobené tím, že komunikace mezi AVRDUDE a Arduinem někdy způsobuje reset Arduina. Problém se dá vyřešit alespoň provizorně tím že se mezi pin RESET Arduina (pin28 u NANO) a zem (GND, pin29) připojí kondenzátor 10uF (či více, měl jsem v šuplíku 100uF elektrolyt tak jsem vyzkoušel ten a problém zmizel). Pozor pouze na to, že s tímto kondenzátorem nelze Arduino jednoduše naprogramovat, protože pak ho ani IDE není schopné zresetovat. Pokud chcete tedy v Arduinu změnit program, musíte kondenzátor opět dočasně odstranit.

další obvyklou chybou je:

stk500_getsync(): not in sync: resp=0x00 ,

která znamená, že programátor není schopen komunikovat s mikrokontrolérem. Většinou v důsledku špatného zapojení propojovacího kabelu. Zkontrolujte správnost zapojení.

Odkazy:
inspiraci a radu jsem nalezl v následujících zdrojích, autorům děkuji.

http://www.martyncurrey.com/arduino-nano-as-an-isp-programmer/

http://www.ladyada.net/learn/avr/avrdude.html

https://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduinoisp