Arduino
電子工作
AVR
IoT
ArduinoISP

Arduino LeonardoをAVRライタにした話

Arduino UNOがAVRライタになるのか!

Arduino UNOが壊れた!

はい。

Arduino LeonardoをAVRライタにする

もともとArduinoは学習用だったりテスト用として考えていたので、あのボードをそのまま自作の何かに組み込むのは寸法的にきついなあと最初から思っていて、いずれはライタを買って全部自分で実装しようと思っていました。そしていろいろArduinoを触っていくうちに

  • Arduino UNOがAVRライタとして動作することを知る
  • 早速試す
  • 壊す

を数分のうちに行いました。残ったのはLeonardoのみ。UNOでできるんだったらLeonardoでもサクっといけるでしょ的なノリでやってみたら結構ハマったのでその記録を書いていきます。

意外と情報量が少ないLeonardoライタ

そもそもleonardoは1台しかないので比較はできませんが、UNOと同様の手順ではどうやってもこのようなエラーが出て書き込みが成功しませんでした。

avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding

エラー内容がアバウトすぎる…。

残念ながら日本語の情報にたどり着くことはありませんでしたが、いろいろと調べた末やっとのことでAuduinoIDEの設定ファイルの編集とスケッチの変更でLeonardoを書き込み装置としてマイコンへ書き込むことができました。

環境

Windows10 Home
Arduino IDE 1.8.5
Arduino Leonardo 純正品(互換品でもおそらく可能)

目標

Arduino LeonardoをAVRライタにする
ATmega328PへArduinoのプログラム(.ino)を書き込む
(おまけ)Atmel Studioで書き込み
(おまけ2)別のAVRマイコンへの書き込み

UNOで作るArduinoISPとの相違点

UNOはISCPのピンがD11-13から引き出せますが、Leonardoでは基盤のロゴの下あたりにあるピンからでないと使えません。
ArduinoIDEのファイル→スケッチ例→11 ArduinoISPのスケッチはそのままでは使えないので少し編集する必要があります。

重要

UNO互換品使ったほうがいいです。

準備するもの

パーツ類

ブレッドボードor何かしらの基盤
基盤を使う場合は2.54ピッチのユニバーサル基盤かICソケットの嵌まる基盤(とにかくマイコンが刺されば何でも良いです)
10kΩの抵抗
RESETプルアップ用
ジャンパーピン(メス-オス)
ICSPを取り回すのに悲痛です。なければ最悪ハンダでもいいかもしれません。
ジャンパーピン(オス-オス)
通常のを数本。ホチキスの芯のような小さいサイズがあるとマイコンへの接続にとても便利です。
AVRマイコン
ATmega328P 同じシリーズの8P/48P/88P/168Pはピン配置は同じなのでなんでもいいです。

ソフト

Arduino IDE
1.8.5

ステップ1 配線

準備した抵抗やジャンパワイヤを使って配線します。

mesupin.png

オス-オスの場合
pinvccgnd.png

どちらも動作するので手持ちと相談で。

基本の配線はこれだけです。

ソフト側の設定

ボード情報を追加する

ファイル→環境設定→追加のボードマネージャのURLの項目に

https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json

を追加します。

新しいビットマップ イメージ (2).png
カンマ区切りで入力するか、右側の四角いアイコンをクリックすると一行単位で追加できます。

ついでに「より詳細な情報を表示する」のところにもチェックを入れておくといいでしょう。

ツール→ボードを開き、一番上のボードマネージャを開きます。
検索部分に「core」など入力すると追加したボード情報をインストールできるので、MiniCore,MicroCoreをそれぞれインストールしてください。
新しいビットマップ イメージ (2).png

ボード情報の追加はこれで完了です。

LeonardoにArduino ISPを書き込む

ArduinoIDEを起動し、ファイル→スケッチ例→11.Arduino ISPを選んでスケッチを開いてください。
70行目あたりにあるピンの設定を変更します。

// Configure which pins to use:

// The standard pin configuration.
#ifndef ARDUINO_HOODLOADER2

#define RESET     10 // Use pin 10 to reset the target rather than SS
#define LED_HB    11
#define LED_ERR   12
#define LED_PMODE 13

こんな感じです。
RESETの設定は必須で、場合によってはSSなど利用できないものが指定されてることがあるので要確認です。
それ以降の3つは放置でも構いません。

LED_HB
HeartBeatの意味です。PWM機能のあるピンを指定するとライタが生きている場合にゆったりと点滅を繰り返します。

LED_ERR
何らかのエラーにより書き込みできなかった場合に点灯します。

LED_PMODE
プログラムを書き込んでいるときに点灯します。実際に書き込みを行うと高速で点滅します。

書き込むときは当然IDEの出力画面を見れば書き込みしたかエラーが出たかはわかりますが、こんな機能もあるので使いたい人はどうぞ。自分は書き込み用の基盤を作って光らせてますがなんだかそれっぽい感じが出て好きです。

以降の行にも同じようなものがありますがそちらは触らなくて大丈夫です。

編集が終わったら別の名前を付けて保存しておきましょう。そしてこれを普段通りLeonardoにアップロードします。

プログラマーの設定

UNOならここまでくればあとは書き込むだけですが、Leonardoの場合はprogrammerの変更も必要になります。
まずは先程開いた環境設定の下の方にある「以下のファイルを編集すれば~」の下にあるパスを確認します。
aa.png
まずはこのフォルダまで開いてください。もしユーザーフォルダの中にAppDateが見当たらない場合はエクスプローラーの表示→隠しファイルにチェックを入れると見えるようになります。

preferences.txtが見えたらそれをスルー、その階層にあるPackages→arduino→hardware→avr→1.6.21まで移動してください(深い…)

その中にprogrammers.txtというファイルがあるかと思うのでそちらを開きます。
最終的なパスは(デフォルトでインストールしている場合)

C:\Users\ユーザー名\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\programmers.txt

こんな感じになると思います。

ここにleonardo用のISPの設定を追記します。場所はArduino as ISPの下あたりがいいようです。
まずは以下の行を探します。

arduinoasisp.name=Arduino as ISP

ここから空行までの数行がArduino as ISPの設定になっているので、その直後あたりに以下を挿入します。

arduinoispleo.name=Arduino as ISP (Micro/Leonardo)
arduinoispleo.communication=serial
arduinoispleo.protocol=arduino
arduinoispleo.speed=19200
arduinoispleo.program.protocol=arduino
arduinoispleo.program.speed=19200
arduinoispleo.program.tool=avrdude
arduinoispleo.program.extra_params=-P{serial.port} -b{program.speed}

英語アレルギーなので何故下にする必要があるかまでは読めませんでしたが、多分わかりやすさ重視だと思うので別に一番上でもいいと思います。(動かなかったら指定通りの場所に移動すればいいでしょう。)

Arduino as ISPというのはArduinoをAVRライタにしたときに選ぶ書き込み装置ですが、leonardoの場合どうやっても上述したstk500が無反応みたいなエラーで書き込めませんでした。
この設定では(program.)protcolにarduinoを指定しているのでこれが成功の鍵だと思いました。

また.nameには好きな名前を付けられるのでお好みで変更してください。

編集後はIDEを再起動すると読み込まれるようになります。

ArduinoIDEで書き込み

ここからようやく書き込み作業を行います。
その前にスケッチの用意ですが、arduinoの方言でプログラミングをする場合一番必要になるのがマイコンのピン配置ですね。これは「マイコン名 ピン配置」などでググればarduinoユーザーの作った大量の情報が出てくるので一例だけ載せておきます。(拾い物です)
ATmega328P系全般
Atmega168PinMap2.png

めんどくさい人用↓

void setup(){
  pinMode(9,OUTPUT);
  }
void loop(){
  digitalWrite(9,HIGH);
  delay(1000);
  digitalWrite(9,LOW);
  delay(1000);
}

スケッチを用意したら先程追加したボード設定の下の方にatmega328があると思うのでそちらを選んでください。
guy.png

ボード
画像のようにボードを選びます。ここではATmega328を。選択すると普段arduinoを選んでいるときとは違いいろいろな項目が増えます。
Bootloader
よくわかりません。はいでもいいえでも変わらないので好きな方を選んでください。はいにするとbootloaderも書き込むのかなよくわからない。
Variant
該当するものを選びます。328Pの場合はそのまま328P/328PAを。
BOD
リセットレベル。電源電圧がこの電圧以下(未満?)になったらリセットがかかる的な感じですがデフォルトの2.7Vでいいと思います。(よくわかってない)
Clock
動作周期です。nhz internalとexternalがあり、前者は内部発振、後者は外部発振を使う設定になります。外部発振はクリスタル発振子などが必要になります。とりあえず書き込むことが目的で速度は求めないので1Mhz internalを選びましょう。externalのものを選ぶと外部発振なしでは上書きできなくなります。
Compilerなんとか
わからないのでこのままでいいです。最適化の設定らしいです。
シリアルポート
Leonardoを接続しているポートを選びます。

ボードの設定は以上。

書き込み装置の設定

q3r.png
試行錯誤してたらアホみたいに設定が増えましたが気にしないでください。

先程設定したArduino as ISP(Leonardo/Micro) を選びます。
もし見当たらない場合はIDEの再起動を試してみてください。

書き込み実行

普通の書き込みを行おうとするとエラーがでるので(leonardoを書き込み装置にしているのにleonardoに書き込もうとしてしまう)
このように書き込み装置を使って書き込む もしくはショートカットキーで書き込んでください。

faf.png

書き込みが完了すれば成功です。お疲れ様でした。
失敗した場合は以下を確認してください。


マイコンがちゃんと刺さっていない
結構あります。足が折れそうなのでそっと刺すのではなく、逆にへし折るくらいの勢いでボードに押し込みます。

ピンが違う
配線図とピンをしっかり確認してください

よくあるエラー

avrdude: Device signature = 0x000000
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

ピンがちゃんと刺さっていない場合に出るエラーです。ピン配置と接続をよく確認してみてください。

avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding

programmerがここで追加したものではなくもともとあったやつになってます。

コンパイル時にエラーが出る場合、ボード選択を間違えている可能性があります。

また、ピンの接続も問題ないのにどうしてもうまくいかないときはボードを「Arduino/Genuino UNO」もしくは「Arduino/Duemilanove or Diecimila」を選択してみてください。実質328Pみたいなもんです。

おまけ Atmel Studioでの書き込み

せっかく生のAVRに書き込むんだからarduinoの全部のせ特盛みたいなコードではなく直接書きたいですよね。おまけではAVR開発用のAtmel Studioを使ってこれまで作ってきたLeonardoライタを書き込み装置として使う方法を紹介します。

書き込み設定のためにいろいろなパスが必要になるので、一旦ArduinoIDEの環境設定で「詳細な情報を~」のコンパイルと書き込みにチェックを入れてマイコンへの書き込みを行ってください。その際に出るログが必要になります。

中の動き

Arduinoは中ではavrdudoという書き込み用のプログラムを使って書き込みを行っています。

まずArduinoIDE側で実際のところ何をしているかというと、各種ソフトウェアへ渡すための引数の設定をGUIから簡単に行えるようにしているだけです。
コンパイルはavr-gccというavr向けのCコンパイラへ適切な引数を付けて渡しているだけですし、書き込みはavrdudoという書き込みソフトへ適切な引数を渡して書き込みを行っています。

簡単にいうとArduinoでマイコンに書き込めたということは、他のソフトからでも(なんならコマンドラインから直接でも)avrdudoをArduinoと同じ設定で使えば書き込めるということです。もちろんコンパイルする部分もavr-gccにArduinoと同じ引数を与えればコンパイルが可能です。要するに面倒な入力内容を全部(それもいろいろな設定を簡単に変更できるよう)自動化してくれるツールがArduinoということですね。

当然Atmel Studioやその他開発環境からavrdudoやavr-gccをArduinoIDEの設定どおりに呼び出せば、同じ結果が得られるのは道理だということになります。

外部ツールとしてLeonardoを設定

Atmel Studioを起動し、Tools→External Toolsを選択します。
gyg.png

まずはこの書き込みに使用する設定の名前を入力します。ライタ、ターゲットになるマイコンでそれぞれ設定する必要があるらしいのでそれを踏まえてつけると良いでしょう。

次のcommandにはArduinoIDEの書き込み時に表示されるavrdudoのパスを入力します。別途avrdudoを入れてそれを使おうとしたらエラーがでたので、既に成功しているarduino同梱のものを(パスは長くなってめんどくさいですが)使うのがいいでしょう。

まずはArduinoIDEでの書き込み時のログをさかのぼり、白文字からオレンジ文字になる境目のあたりを探します。
白文字の最終行にはprogrammers.txtを編集したときに見た覚えのあるパスが並んでいるのでおもむろに一行まるまるコピーします。アホみたいに長いですが気にしないでおきましょう。

多分こんな感じのものが書いてあるので、とりあえず適当なエディタにでも貼り付けておいてください。

C:\Users\ユーザー名\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9/bin/avrdude -CC:\Users\ユーザー名\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b19200 -Uflash:w:C:\Users\ユーザー名\AppData\Local\Temp\arduino_build_376871/Blink.ino.hex:i

これの最初の部分、 

C:\Users\ユーザー名\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9/bin/avrdude

これがcommandになります。以降は全て引数です。一応windowsでは.exeを省略してもちゃんと動きますが、心配な方はavrdudo.exeなんかにしてcommandへコピペしましょう。

それ以降の引数について(長いので分割します)
順番はArduinoのログ通りに進みますが、ここで指定する場合は前後しても問題ありません。オプションについての詳細は以下。

Usage: avrdude.exe [options]
Options:
  -p <partno>                Required. Specify AVR device.
  -b <baudrate>              Override RS-232 baud rate.
  -B <bitclock>              Specify JTAG/STK500v2 bit clock period (us).
  -C <config-file>           Specify location of configuration file.
  -c <programmer>            Specify programmer type.
  -D                         Disable auto erase for flash memory
  -i <delay>                 ISP Clock Delay [in microseconds]
  -P <port>                  Specify connection port.
  -F                         Override invalid signature check.
  -e                         Perform a chip erase.
  -O                         Perform RC oscillator calibration (see AVR053).
  -U <memtype>:r|w|v:<filename>[:format]
                             Memory operation specification.
                             Multiple -U options are allowed, each request
                             is performed in the order specified.
  -n                         Do not write anything to the device.
  -V                         Do not verify.
  -u                         Disable safemode, default when running from a script.
  -s                         Silent safemode operation, will not ask you if
                             fuses should be changed back.
  -t                         Enter terminal mode.
  -E <exitspec>[,<exitspec>] List programmer exit specifications.
  -x <extended_param>        Pass <extended_param> to programmer.
  -y                         Count # erase cycles in EEPROM.
  -Y <number>                Initialize erase cycle # in EEPROM.
  -v                         Verbose output. -v -v for more.
  -q                         Quell progress output. -q -q for less.
  -l logfile                 Use logfile rather than stderr for diagnostics.
  -?                         Display this usage.

設定ファイルの指定

-CC:\Users\ユーザー名\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9/etc/avrdude.conf

なにやら設定ファイルらしいのでこのままにします。-CC:\の部分が悪さをするので-C C:\のようにドライブ文字とオプションの間にスペースを入れておきます。

ターゲットとライタの指定
```
-v -patmega328p -carduino -PCOM6 -b19200

```-v```(詳細情報の出力) ```-p```対象のマイコンの種類(専用の書き方もあるようです) ```-c```(小文字) 書き込み装置の指定。 ```-p```COMポートの指定。お使いのLeonardoが接続されているポートを選びます。 ```-b```ボーレートの指定。arduinoでいうシリアル通信速度みたいなやつですね。
基本的にCOMポートの編集のみで残りはこのままで問題ありません。どうしても気持ち悪いと思う方はオプションと引数の間にスペース入れておきましょう。

書き込みファイルの指定

-Uflash:w:C:\Users\ユーザー名\AppData\Local\Temp\arduino_build_376871/Blink.ino.hex:i

この
-U```オプションでは書き込むファイルを指定しています。このログではArduinoのBlink.inoを書き込んだのでそれが書かれていますが、実際には今開いているファイルを書き込みたいので、この部分はまるまる変更します。

-U flash:w:$(ProjectDir)Debug\$(TargetName).hex:i 

\$(ProjectDir)は現在開いているプロジェクトのフォルダ、$(TargetName)はファイル名になります。

一応Debugビルドのhexファイルを指定していますが、Releaseビルドにしたい場合はそちらを選ぶといいでしょう。

これらを全て連結して

-C C:\Users\ユーザー名\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b19200 -U flash:w:$(ProjectDir)Debug\$(TargetName).hex:i

これをAugmentのところに貼り付けます。
下のUse windowにチェックを入れてOKを押すと外部ツールとしての登録が完了します。

書き込みファイルの作成

File→New→Projectを選びます。
ataa.png
いろいろ出てきますがGCC C Executableを選びます。C++もarduino語も使えるみたいなのであとで試してみたいですね。
ataaa.png

するとチップを何にするか聞かれるので328Pを探します。
ata2.png

これでOKを押すとなんやかんやとプロジェクトが作られmain.cが作られるので、それを以下のように編集します。

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRD = 0b11111111;
    PORTD = 0b111111111;
    char led=0;
    /* Replace with your application code */
    while (1) 
    {
        PORTD ^= 1;
        _delay_ms(1000);
    }
    return 0;
}

よくあるLチカコードです。ピンを調べるのがあれなのでもうDピン全部点滅させます。Dピンはマイコンの左上の2本め(2番ピン)から下へ数本までが大体DピンなのでここらへんにLEDをつなげておきましょう。

コンパイル

現在開いているのはmain.cで、コンパイルするとmain.hexが作られます。外部ツールで設定した書き込みファイルにはこのmain.hexを指定しているのでまずはコンパイルからです。これは面倒ですがソースを編集したら必ず行わなければならないので気をつけてください(何度かそれで「書き込めてない!!!!」とか騒いでました)
VSやecripse等のIDEと同じように再生ボタンやらF5も機能しますが、これを使うとコンパイルからデフォルトのライタで書き込みまで行おうとしてエラーが出るので、おとなしくコンパイルのみにしておきます。Leonardoをデフォルトの書き込み装置にする設定は今の所わかりません(あまり調べてない)

Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

こんなのがログに出てくれば成功してます。

書き込み

コンパイルまで終わり、エラーがないことを確認します。上のコードでは何やらWarningがいくつかでますが、Warningってことは要するにErrorではないということです(強気)

ここまできたらあとは書き込むだけです。Toolsを選ぶとExterbal Toolsの上に先程追加したLeonardoの名前が出てくるので、これをクリックすると書き込みが行われます。
ただし成否まで細かく教えてくれないので、最初のうちはArduinoのログと照らし合わせて成功したか失敗したかを判別してみてください。
書き込めようが書き込めなかろうが
avrdude.exe done. Thank you.

こんなこと言ってさよならします。
ログを良く見てファイルサイズ的なものが書かれてたりすれば成功しています。

以上でLeonardoをAVRライタとして使うための作業は終わりです。
おつかれさまでした。

おまけ2

ちょっとした工作をするのに328Pではオーバースペックですね。逆に大規模なデータを扱ったり入出力を扱う場合は328Pでは物足りないかもしれません。
その場合は新たにボード情報を追加し、データシートを参照して接続するピンを調べることで多くのマイコンに書き込みを行うことができるようになります。

たとえばもっと小さくて安いやつでよければAttiny13(50円,8pin)
328Pほどではないけどもうちょっと欲しい場合はATtiny2313(180円,20pin)、328Pじゃ弱すぎるぜという場合は1284P(750円,40pin)など
※いずれも2018/6時点の秋月電子の価格

ボード情報についてはここにいろいろとあるので、目的のものを選んでインストールしてください。
Arduino for other Chips

またICSPの接続については、各マイコンのデータシートを見ながらそれに合わせて接続します。
LeonardoのISCPピンはこちら
ICSP
5のリセットは死んでいます。

最初に上げた画像
mesupin.png

この例では
ボード上の10 RESET(白)
ICSP-1 MISO(緑)
ICSP-2 or ボード上の5V +VCC(赤)
ICSP-3 SCK(黄)
ISCP-4 MOSI(橙)
ICSP-6 or ボード上のGND(黒)
となっています。(別の色の場合は適宜読み替える)

atmega-pins.png
このデータシートと配線を照らし合わせると、例えばATmega328P側の7,20がVCCで赤、8,22がGNDで黒となっていることがわかります。

MISO,MOSI,SCKも同様で、配線はこのように「ライタ側のピン」と「マイコン側のピン」をあわせて接続することで正常に動作するようになっています。
pins.png

これさえわかればもう簡単ですね。
例えばAttiny13なら
tiny13pins.png

このような配置になっているので、
tiny13-wire.png

1にリセット(白)と抵抗
4にGND(黒)
5にMOSI(橙)
6にMISO(緑)
7にSCK(黃)
8にVCC(赤)

このような配線をすれば接続できることになります。