ArduinoでPICマイコンに書込む~OpenStickLite(PIC18F14K50)編~

ジョイスティック自作用ツールキットOpenStickは元々PIC18F2550(又は2553)を採用していました。このマイコンは28pinで、DIPパッケージだと結構大きい部類になります。
そこで先日PIC18F14K50を使用したOpenStickLiteをβリリースしました。こちらは20pinなので入力ピン数は少なくなりますが、これでも大抵の用途には事足りると思っています。
価格もこちらの方が大幅に安くてすみます。

OpenStickもOpenStickLiteもUSBからプログラムを書き込む為のブートローダを使用しています。 電源投入時(またはリセット時)の条件設定によりブートローダが書き込みモードで立ち上がります。この状態で書き込みツール「MybootOS」を使うとUSBポート経由でプログラムを書き込める訳です。

この種の話題でいつも問題になるのがブートローダ自体はどうやって書き込むかという事です。 ブートローダでブートローダを書き込む事はできないので、通常はそのマイコン専用のライター(PICKit3など)を使用します。
しかし皆がライターを持っているわけではありません。 そこでArduinoを使ってPIC18F2550にブートローダを書き込む実験を過去に行い、問題なく書きこむ事ができました(下記を参照ください)。

今回はArduinoからPIC18F14K50にブートローダを書き込んでみます。これが可能になればOpenStickLiteを安価に使用できます。

まずここの資料でPIC18F14K50の書き込み仕様を調べます。 大体はPIC18F2550と同じですが微妙に違うところがあります。一番問題なのはPGD,PGC端子が耐圧3.3Vという記述です。 PIC18F2550の時はArduinoUNOを用いて5Vで駆動していました。特にPGDは双方向なのでレベル変換は面倒です。 よって今回は3.3V版ArduionoProMiniを用いることにします。
またスケッチには若干のWAITタイムの変更と書き込みイネーブルONのコードを追加しました。
スケッチ→PICWrite18F14K50.ino

書込み電圧は006Pの積層乾電池(9Vの四角いやつ)を用いる事にします。先の資料によると書込み電圧の上限は9Vという事なので、新品の電池だと定格を超える可能性がありダイオード一本で電圧を下げました(使い古した電池だとそのまま繋いで大丈夫です)。

回路

ArduinoProMiniはUSBシリアル変換回路を内蔵していないので、外部にFT232RLの変換回路を接続し、Arduino/PIC18F14K50に供給する3.3V電源もFT232RL内臓のレギュレータから取っています。
PIC18F14K50の電源-GND間のコンデンサは当初0.47μFを使いましたが、PIC18F14K50に電源を投入した瞬間にArduinoProMiniから反応が無くなる事がありました。恐らくFT232RLの3.3V出力が瞬間的にダウンする為と思われ0.22μF(実際には0.1μ×2本)に変更しました。 

PIC14K50WriteByArduinoProMiniSch

PIC18F14K50へArduinoProMiniで書き込む回路図。

参考までにUSBシリアル変換は次の回路です(最近の電子工作には何かと登場しますね。一家に一台FT232RLです)。
FT232RLは3.3Vのレギュレータを内蔵しており、これをVCCIO端子に入力する事で3.3Vレベルで使用できます。この回路ではスイッチを設けて5Vと3.3Vを切り替える様にしています。
但しレギュレータから取れるのは50mAまでなのであまり大きくはありません。

USBSerial

FT232RLによるUSBシリアルインターフェース

PIC18F14K50WriteByArduinoProMini

Arduino ProMiniで書き込み中。
横のFRISKケースはUSBシリアル変換です。

書込み手順

PIC18F2550の時に書いた内容とほぼ同じです。
※前回同様TeraTermの「貼り付けの行間遅延設定」を50mS程度にしておく必要があります(書込み時間待ちの為です)。

<PIC18F14K50にブートローダを書込む手順>

  1. まずPIC18F14K50の3.3V電源と9V電池は切り離しておく。
  2. Arduino IDEを立ち上げこのスケッチを書込む。
  3. TeraTermをシリアルモードにしてArduinoに接続する。
    シリアル設定:9600bps,8bit,パリティ無し,stop=1,フロー制御=none
    改行コードは送信・受信共にCRにする。
    また、「設定」→「その他設定」メニューの「コピーと貼り付け」タグを選び、「貼り付けの行間遅延」を50mS程度にしておく。
  4. 接続するとTeraTerm上に以下のメニューが表示される。
    r  <start address> <count>: read from PIC
    e : all erase
    w : write to PIC
    v : verify
  5. ここでPIC18F14K50に3.3V電源→9V電池の順で供給する。
  6. 必要に応じ’r’コマンドで現在書かれている内容を確認する。たとえば・・・
    r 0 0×100<CR>
    と入力すると、FLASHメモリの0番地から0FF番地の内容を表示する。
    消去済ならCODEエリア全ての内容がFFになっているはずである。
    (消去チェック機能はないので、どちらにしても次の消去コマンドを実行しておくべきです)
  7. 消去済みでない場合はeコマンドで消去する。
    ALL Erase <y/n>?と効いてくるのでyを入力する。
    このコマンドはチップ全体を消去する(一瞬で終わります)。
  8. ‘w’コマンドで書込む。w <cr>を入力すると’Send me intelhex text’と表示されるので、ここでIntelHEXファイルを送る。この際、上に書いた理由でコピペで貼り付ける方法で送る。 たとえばブートローダのHEXファイルである’Bootloader18F14K50.hex’をメモ帳等で開いて全域をコピーした後、Teratermの画面上に貼り付ける。
    (前に書いた様に「ファイル」→「ファイル転送」メニューからの送信だと取りこぼしが発生する)
  9. エラーなく書き込みが完了したら’v’コマンドでベリファイを行う。方法は’w’コマンドと同じで、v<cr>入力後IntelHEXテキストを貼付けるとFlashメモリを読出して比較する。  エラーが出なければ正常に書き込めた筈である。
  10. 9V電池→3.3V電源の順で切り離し、TeraTermの接続を切りArduinoのUSBケーブルを抜く。

やっぱりArduinoUNOでやってみる。

と、ここまでで書き込みが出来たのですが、やっぱり3.3V版Arduinoは少数派で手元にない場合もあると思われ、メジャーなArduino UNO等でも書けると何かと便利です。 この場合5Vで動作するArduinoと3.3Vで動作するPIC18F14K50の間をどう繋ぐかが問題です。ArduinoからPIC18F14K50へ一方的に入力するPGC信号は単に抵抗分割で問題ありません。一方PGD信号は双方向なのでまじめにレベル変換器を入れると結構面倒な事になります。しかし3.3VのHレベルはArduinoはHと認識してくれる筈と期待しPGDも単純抵抗分割で試してみました。

PIC14K50WriteByUNOsch

ArduinoUNOでPIC18F14K50に書き込んでみる回路図。

実験風景・・・

ArduinoUNOで書き込み

ArduinoUNOで書き込み。UNOは直接USBケーブルを繋げるのですっきりします。

特に問題なく書けました。これが手っ取り早いです。
気をよくしてFritzingでも回路を書いてみました。

PIC14K50WriteByUNO_ブレッドボード

Fritzingでも描いてみた。

 

各ファイル 

※PIC18F14K50用ブートローダは上記バイナリセットかソースのどちらにも収録しています。※言うまでもないとは思いますが、同様の実験をされて万一デバイスが壊れたりしても責任は持てませんので、そこんとこはよろしくお願いいたします。

 

ArduinoでPICマイコンに書込む~その3~

先日の「ArduinoでPICマイコンに書込む」ではMCLR端子の電源として12Vのスイッチング電源を用いたが、今回は9V電池(006Pという四角いやつ)で試してみた。
PIC18F2550の規格上は「VDD+4V~12.5V」の範囲となっており、VDDが5VならばMCLRには9Vの印加で書き込めるはずだ。

やってみたところ特に問題なく消去/書込み/ベリファイができた。
これが一番手軽な書込み方法かもしれない。

PIC write with Arduino AND 006p BATTERY

Arduinoと9V電池を使用したPICマイコンへの書込み

 

ArduinoでPICマイコンに書込む~その2~

先日ArduinoをPICライター代わりにした事を書いた。その際、書込みモードに設定するために外部電源から12Vを印加したが、今回は5Vのみで書き込んでみた。

まず5V書込み(Low Voltage ICSP)を実行するにはコンフィグビットのLVPを’1′にセットしておく必要がある。 PIC18F2550の工場出荷時設定はLVP=’1′なので問題ないが、ブートローダを書込むと’0′に変更してしまうので一旦ブートローダを書込むと5Vモードでは変更できなくなってしまう(LVPビットは12Vモードでなければ変更できないのだ)。

また、LVP=’1′の場合、通常動作時にRB5端子(PRMと兼用)をGPIOとして使用できなくなる。この端子はLにしておかなければ正常動作しないので、OpenStickとして動作させる場合IN16が使用不可となる(デジタル入力端子が一つ減る)。

これらの制約はあるが、12V印加が不要なのは便利かもしれない。

実験開始

まず書込むべきブートローダファイルをLVP対応に変更しなければならない。 具体的には’20M-18f2550.hex’の最後から8行目あたりにある次の記述「:010006008178」を「:010006008574」に変更し、’20M-18f2550LVP.hex’というファイル名で保存した。

次に回路を変更する。12V印加回路は取り除き、Arduinoの10番ピンをPGM、11番ピンをMCLRに接続した。

PICwriteLVPsch

5V書込み(LVP-ICSP)用回路図

Arduinoのスケッチを5Vモード仕様に変更した。

あとは12Vを印加しない事以外、前回と同じ手順で(先程つくったLVP版)ブートローダの書き込みを行なった。

なお先程書いた通りPIC18F2550をLVP=’1′状態で使用する場合はPGM端子(RB5)をLに接続する必要があるので、OpenStickの回路を変更してGNDと接続しなければならない。
あとはいつも通り、OpenStick基板上のModeスイッチを押しながらリセットする事でブートローダが起動し、MyBootOSツールでOpenStickファームウェアを0×800番地から書込み、OpenStickConfigツールで作成した定義ファイルを0×4000番地から書込むとジョイスティックコントローラとして動作した。

この方法での弱点はRB5をGPIOとして使用できなくなる事であるが、そこまでデジタル入力を使う事は少なく、むしろOpenStick基板を変更するのが面倒な事が一番問題かもしれない。
また上にも書いた通り一旦通常のブートローダを書込むとLVP=’0′(5Vモード使用不可)になり5Vモードでは消去すらできず、12Vモードでしか変更できないので注意が必要である(但しそもそも5VモードではLVPを変更できないので最初から5Vモードだけを使うなら間違って使用不可にしてしまう心配はない)。
このあたりの管理を間違うとハマるかもしれない。

・Arduinoのスケッチ(5V書込み版)
・ブートローダ(LVP=’1′版)

 

ArduinoでPICマイコンに書込む

MakerFaireOpenStickを展示していると、「Arduinoでできないの?」と聞かれる事がある。
しかしArduinoでは(Leonardo等の一部を除き)USBとは仮想シリアルで接続しており、HIDデバイスを実現しにくいのだ。 しかもPIC18F2550で製作するのと比べて値段も高い。

PICでなくてArduinoを使いたい理由のひとつとしてはPICライタが必要という点であろう。
OpenStickの場合、あらかじめPIC18F2550のFlashメモリにブートローダを書込んでおくのだが、その為にPICライタが必要になる。しかし一般的なライターであるPICKit3秋月電子でも¥4500する。
こんな自作ライターを使っていた時もありましたが最近のPCはプリンタポートが無いし・・)

昨今、PICライタよりもArduino基板の方がよっぽど浸透しているだろう。
OpenStickをArduinoに移植するのは難しいが至る所に存在するArduinoを使ってPIC18F2550にブートローダを書込む事ならできそうな気がする。という事で実験を行った。

PIC18F2XXXにプログラムを書込む方法はマイクロチップテクノロジー社のこの資料に書いてあった。 このマイコンでは書き込みモードに設定する為に12Vを印加するHigh Voltage ICSPモード(以下12Vモードと呼ぶ事にする)と、5V電源のみで済むLow Voltage ICSPモード(以下5Vモード)がある。 但し5Vモードを使うには制約があり、コンフィグ設定のLVPビットに’1′が書かれていなければならない。新品購入時、LVPビットはデフォルトで’1′なのだが、ブートローダを書込むと’0′になってしまう。 5Vモードだけだと一度書き込んだら書き換えができないという事になるので、今回は外部電源を使って12Vモードで書込む事にした。

<今回の回路図>

PIC write schematic

今回の実験に使用した回路図

MCLR端子に外部から12Vを与えている。デバイスの規格でここの電源はVDD+4V~12.5Vの範囲となっており、12V電源のままで入力可能な筈だが上限値に近いので、念のためダイオードで少し電圧を落とした。 ArduinoはUNOを用い、+5V,GNDのほかは8ピンをPGC、9ピンをPGDに接続した。PGDは双方向なので念の為3.3KΩを挿入したが、デバッグ完了後はダイオードも抵抗も直結で問題なく動作した。

PIC Writer with Arduino

ArduinoでPICライター

PC側はTeraTermでArduinoに接続し、キーボードからコマンドを入力して操作する。
プログラムの書込みおよびベリファイは’w'コマンドに続いてIntelHEXのデータをテキストとして送る。 Arduino UNOのRAMは2KBしかないので全部を蓄えてから書込む事はできず、IntelHEXデータを1行ずつ読んでは書込みを繰り返すのだが、ArduinoとPC間のシリアル通信ではフロー制御を行っていないため、一気にデータを送ると書込みが間に合わず取りこぼしが発生してしまう(この場合パリティエラーとなる)。 この対策としてTeraTermの「貼り付けの行間遅延」設定を増やしておく必要があった(こちらの環境では行間遅延が20mSだと取りこぼしが発生し、50mSだとOKだった)。 なお、この関係でTeraTermからIntelHEXデータを送る際はコピペで送る必要があり、これを「ファイル」→「ファイル転送」メニューで送ると行間遅延が加わらないらしく取りこぼしが発生した。

結果として下記の方法で書き込み/読み出しができ、更にOpenStickを使ってジョイスティックコントローラとして動作させる事ができた。

<PIC18F2550にブートローダを書込む手順>

  1. まず12V電源はOFFにしておく。
  2. Arduino IDEを立ち上げこのスケッチを書込む。
  3. TeraTermをシリアルモードにしてArduinoに接続する。
    シリアル設定:9600bps,8bit,パリティ無し,stop=1,フロー制御=none
    改行コードは送信・受信共にCRにする。
    また、「設定」→「その他設定」メニューの「コピーと貼り付け」タグを選び、「貼り付けの行間遅延」を50mS程度にしておく。
  4. 接続するとTeraTerm上に以下のメニューが表示される。
    r  <start address> <count>: read from PIC
    e : all erase
    w : write to PIC
    v : verify
  5. ここで12V電源をONにする。
  6. 必要に応じ’r'コマンドで現在書かれている内容を確認する。たとえば・・・
    r 0 0×100<CR>
    と入力すると、FLASHメモリの0番地から0FF番地の内容を表示する。
    消去済ならCODEエリア全ての内容がFFになっているはずである。
    (消去チェック機能はないので、どちらにしても次の消去コマンドを実行しておくべき)
  7. 消去済みでない場合はeコマンドで消去する。
    ALL Erase <y/n>?と効いてくるのでyを入力する。
    このコマンドはチップ全体を消去する。
  8. ‘w’コマンドで書込む。w <cr>を入力すると’Send me intelhex text’と表示されるので、ここでIntelHEXファイルを送る。この際、上に書いた理由でコピペで貼り付ける方法で送る。 たとえばブートローダのHEXファイルである’20M-18f2550.hex’をメモ帳等で開いて全域をコピーした後、Teratermの画面上に貼り付ける。
    (上に書いた様に「ファイル」→「ファイル転送」メニューからの送信だと取りこぼしが発生する)
  9. エラーなく書き込みが完了したら’v'コマンドでベリファイを行う。方法は’w'コマンドと同じで、v<cr>入力後IntelHEXテキストを貼付けるとFlashメモリを読出して比較する。  エラーが出なければ正常に書き込めた筈である。
  10. 12V電源をOFFにした後、TeraTermの接続を切りArduinoのUSBケーブルを抜く。

Arduinoのスケッチ
ブートローダ(千秋ゼミさんへのリンク)

※言うまでもないと思いますが、試される方は自己責任でお願いします。
(特に12Vを印加する端子を間違ったりすると・・・ああ)
※コマンド入力のエラーチェックはあまり詳しく行っていません。

 

http://www.hoihoido.com/rudder/index.html