Arduino ISPを使ってATmega8/168Pにbootloaderを書き込む

ATMEGA168/328用マイコンボード(I/Oボード): マイコン関連 秋月電子通商-電子部品・ネット通販を3枚ほど買ったので、Arduino互換機を作ることにした。
秋月でチップ:ATmega8とATmega168Pを購入したが、このままではArduinoとして使えない。bootloaderを書き込む必要がある。
Arduino開発環境の[Tools]-[Burn bootloader]というメニューアイテムを見ると分かるが、ATmegaにbootloaderを書き込むための手段には幾つか選択肢がある。普通は、手持ちの、あるいは、自作したprogrammerを使ってbootloaderを書き込むのだが、最近「Arduino ISP」という選択肢が出来た。手持ちのArduinoをprogrammerにしてATmegaにbootloader書き込むというわけで、余分な出費が無くて良い。

Arduino ISPについてはArduino - ArduinoISPに詳しく書いてある。僕はこのドキュメントの一番下の章にある「Circuit (targeting an AVR on a breadboard)」の手法を採用した。
ただし、ドキュメント通りにはいかない場面が幾つかあったので記録しておく。
開発環境はMac上のArduino 0022、Arduino Duemilanoveである。

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

ドキュメントに従って、ArduinoISPスケッチを手持ちのArduinoにuploadし、ブレッドボードに配置したATmega8と接続した。
Arduino開発環境の、[Tools]-[Board]から「Arduino NG or older w/ ATmega8」を選択し、[Tools]-[Burn bootloader]で「w/ Arduino as ISP」をクリックするとATmega8に対してbootloaderの書き込みが実行されるはずである。

しかし、僕の環境では「avrdude: stk500_getsync(): not in sync: resp=0x15」というエラーメッセージが出て書き込みは失敗した。

ArduinoのAuto Reset機能がISPとしての挙動の邪魔をしているらしい。解決方法は2つあり、Auto Reset機能を無効にするよう(ISPとしての)Arduinoを改造するか、bootloader書き込みを行っているソフトウェア:avrdudeを改造するかである*1。僕は、Auto Reset機能を無効にする手段を選択した。

ArdunoのAuto Reset機能を無効にするには、Arduino Playground - DisablingAutoResetOnSerialConnectionによると最も簡単な方法として、RESETピンと5Vピンの間に110Ωから124Ωの抵抗を挟めば良いとある。僕は手持ちの330Ωの抵抗を3つ用意して110Ωを挟んだ。

再度、[Tools]-[Burn bootloader]で「w/ Arduino as ISP」をクリックすると無事にbootloaderが書き込まれたことを示すメッセージが出た。Arduino - Bootloaderによれば、bootloaderを書き込んだATmegaは19番ピン*2に接続したLEDを点滅させるので、あらかじめLEDを繋いでおくとbootloaderが書き込まれたことを確認し易い。

avrdude: Expected signature for ATMEGA168 is 1E 94 06

同じ環境でATmega168Pにもbootloaderの書き込みを行おうと、Arduino開発環境の、[Tools]-[Board]から「Arduino Diecimila, Duemilanove, or Nano w/ ATmega168」を選択し、[Tools]-[Burn bootloader]で「w/ Arduino as ISP」をクリックしたところ、bootloaderの書き込みは失敗した。

僕の環境では、「avrdude: Expected signature for ATMEGA168 is 1E 94 06」というエラーメッセージが出た。更にそのエラーメッセージの下には、Double checkをしろとか-Fオプションを付けろとか書いてある。

もしかしたら、僕が買ったチップがたまたま不良品だったのかもしれないということも考えた。どうやら、arvdudeのオプションに-Fを付けてverify checkを無視すればbootloaderを書き込めるかもしれないようだ。と考えが至ったところで、Arduinoの開発環境が呼び出すarvdudeが参照するファイル:/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/arvdude.confを見てみると、168Pのセクションが無いことに気付いた。168と168Pの、チップのシグニチャが異なるのでエラーが出ていたというわけだ。

m168pセクションが追加されたarvdude.confは公開されている。ホームページ移転のお知らせ - Yahoo!ジオシティーズにあるavrdude.confをダウンロードして /tmp/ に置いた。

arvdudeの呼び出しの際のオプションを変えれば良いのだが、Arduino開発環境からどうにかすることは諦め、端末からarvdudeを直接叩くことにした。arvdudeはArduino開発環境に同梱されているものをそのまま使う。

$ cd /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/atmega
  # ここにATmega168/328用bootloaderがある
$ AVR=/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr
  # Arduino開発環境に含まれるAVRツールのルートディレクトリ
$ $AVR/bin/avrdude -C /tmp/avrdude.conf -p m168p -P /dev/tty.usbserial-A7006SSA -c avrisp -b 19200 -F -U flash:w:ATmegaBOOT_168_diecimila.hex
  # 書き込みが行われていることを示すメッセージなどがずらずら出る

これでbootloaderの書き込みは成功する。19番ピンに接続したLEDが点滅しているのを確認した。スケッチの書き込みの際は、Arduino開発環境はチップのシグニチャではなくチップに書き込まれたbootloaderのシグニチャを見るので、boardの指定は168のままで良いらしい。

スケッチのupload

ドキュメントにあるように配線を繋ぎかえる。[Tools]-[Board]の選択が正しいことを確認する。

そして、ドキュメントにも書いてあるし、絵でもそうなっているのだが、忘れてはならないことがある。「Remember to remove the microcontroller from the Arduino board!」:日本語で書くと、「ISPにしているArduinoのチップを抜くのを忘れるな」

*1:Arduino Playground - MegaISPに詳しい。これはMacLinux環境で起こる問題らしい。

*2:Arduinoの13番ピンに対応する。Arduino - PinMapping参照。