Arduino jako AVR programátor

Konečně se mi podařilo použít Arduino jako AVR programátor. Snažil jsem se o to od doby, kdy jsem si poprvé pořídil Uno, zkoušel jsem nejrůznější návody i vlastní řešení, bohužel doposud marně. Nedávno se na oficiálních stránkách Arduina objevily aktualizované informace, jak Uno použít k programování. V tomto článku sepíšu pár poznámek k celému postupu.

Naším cílem bude použít Arduino Uno jako programátor mikrokontrolérů z rodiny ATTiny a ATMega. Celý tento postup jsem ověřil na ATTiny13 a ATMega8U2.

Problém

Pokud zapnete Arduino IDE verze 1.0 a z nabídky File->Examples vyberete položku ArduinoISP, otevře se vám kód pro AVR programátor. Tlačítkem upload lze bez problémů přeložit a nahrát do Arduina. Pokud v tomto okamžiku Arduino připojíte k nějakému AVR mikrokontroléru a pokusíte se jej pomocí avrdude naprogramovat, dostanete chybové hlášení, které končí nějak takto:

avrdude: stk500_disable(): unknown response=0x12

Dlouhou dobu na internetu kolovaly nejrůznější fámy a zvěsti, proč tomu tak je a jak celý tento problém vyřešit.

Plošky RESET-EN umožňují softwarový reset Arduina.
Plošky RESET-EN umožňují softwarový reset Arduina.

Během řešení tohoto problému jsem si všiml, že avrdude před samotným programováním celé Arduino resetuje. To není správné chování, a proto jsem zkusil přerušit spojení na ploškách RESET-EN, které spojují reset ATMega328 s pinem PD7 na ATMega8U2. Zjednodušeně řečeno jsem vypnul možnost resetu Arduino přes USB.

Ani toto však nebylo řešení problému, navíc tento zásah do desky není zrovna elegantní :)

Řešení

Nedávno (necelý měsíc nazpátek) se na stránce Using an Arduino as an AVR ISP objevilo řešení.

Nejdříve je nutné změnit samotný kód ArduinoISP. Tento kód totiž na pinu D9 pulzuje LEDkou a tím dává najevo, že pracuje a je připraven. Toto pulzování obstarává funkce heartbeat(). Najděte ji a upravte dobu čekání z 40 ms na 20 ms (nebo i méně). Výsledek by měl vypadat takto:

void heartbeat() {
  if (hbval > 192) hbdelta = -hbdelta;
  if (hbval < 32) hbdelta = -hbdelta;
  hbval += hbdelta;
  analogWrite(LED_HB, hbval);
  delay(20);  // Původní hodnota byla 40.
}

Problém je v tom, že funkce heartbeat() se vykonává příliš dlouho a mikrokontrolér pak již nestíhá zpracovávat příchozí data. Zkrácením této doby se problém vyřeší.

Druhý problém jsem již popsal — avrdude vždy před samotným programováním resetuje Arduino. Řešení jsou možná dvě. Buď přerušíte spojení na ploškách RESET-EN nebo mezi piny RESET a GND připojíte elektrolytický kondenzátor o kapacitě alespoň 10μF/16V. První řešení je méně elegantní, protože pokud si budete v budoucnu chtít Arduino znovu naprogramovat, budete must plošky opět spojit. Doporučuji proto použít kondenzátor, pozor na jeho polaritu a maximální napětí.

Takže teď již máme v Arduinu nahraný kód ArduinoISP, mezi RESET-GND máme elyt. kondenzátor a k mikrokontroléru, který chceme programovat máme připojeno 6 vodičů (na straně Arduina):

  • VCC
  • GND
  • SCK (D13)
  • MISO (pin D12)
  • MOSI (pin D11)
  • SS (D10)

Na který pin vašeho mikrokontroléru tyto signály připojit najdete v datasheetu (na straně programovaného MCU), ale obecně to budou VCC, GND, SCK, MISO, MOSI a RESET.

Ještě můžete k Arduinu připojit LEDky k pinům D9, D8 a D7, které představují signalizaci heartbeat, error a programming. Jejich funkce je jasná z názvu.

Programování

Samotné programování je pak otázka správně zvolených přepínačů v avrdude. Před jakýmkoliv zápisem doporučuji provést test spojení následujícím příkazem:

$ avrdude -c avrisp \
> -P /dev/tty.usbmodem* \
> -b 19200 \
> -p kód_MCU

Tímto jsme řekli, že budeme používat programátor avrisp (používá protokol STK500) na portu /dev/tty.usbmodem* (platí pro Unixové systémy a může se mírně lišit na Macu a Linuxu ve Windows použijte port COMx). Rychlost komunikace je 19200 baudů. Na závěr ještě zvolte kód vašeho mikrokontroléru. Např. pro ATTiny13 je to t13 pro ATMega8U2 je to m8u2 pro ATMega328 by to bylo m328.

Pokud je vše správně zapojeno, měli byste nyní vidět něco jako:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.06s

avrdude: Device signature = 0x1e9389
avrdude: reading hfuse memory:

Reading | ################################################## | 100% 0.02s

avrdude: safemode: Fuses OK
avrdude done.  Thank you.

V opačném případě uvidíte nějaké chybové hlášení. Zkontrolujte zapojení vodičů (pozor na přehození MISO a MOSI), číslování pinů na mikrokontroléru nebo správný kód součástky.

Pro samotné programování pak slouží přepínač -U:

$ avrdude -c avrisp \
> -P /dev/tty.usbmodem* \
> -b 19200 -p kód_MCU \
> -U flash:w:soubor.hex

Syntaxe tohoto přepínače je snadná a intuitivní. Nejdříve zvolte s jakou pamětí chcete pracovat (flash, lfuse, hfuse, efuse, lock), potom jestli se bude číst nebo zapisovat (r, w), poté název souboru a volitelně i formát dat (h, m, i). Pro úplné naprogramování ATTiny13 například:

$ avrdude -c avrisp \
> -P /dev/tty.usbmodem641 \
> -b 19200 -p t13 \
> -U flash:w:soubor.hex \
> -U lfuse:w:0x7A:m \
> -U hfuse:w:0xFF:m

A to je vše. Tímto jsme úspěšně použili Arduino Uno jako ISP programátor.

Pokud ještě nemáte Arduino nebo sháníte plnohodnotný AVR programátor, můžete se podívat na nabídku v místním eshopu – Arduino Uno a programátor USBasp.