PIC24USBでUSBシリアルに挑戦 (2)サンプルソースを動かしてみる

まず、回路図を比較してみる。後述の通り、PIC24FJ256GB106を使うボードのターゲットはPIC24F Starter Kitである。こいつの回路図はMicrochip社のWebサイトで入手できた。PIC24USBとの主な差分は、

  • Starter Kitのクロックは、PIC18F67J5(デバッグ用のPICか?こいつのクリスタルは12MHzとなっている。)から供給されているので、周波数がよくわからない。一方で、PIC24USBのクリスタルは16MHz。
  • Starter Kitには32kHzのクリスタルがついている。
  • Starter KitはPGEC2/PGED2にICSP端子がつながるようになっているが、PIC24USBはPGEC1/PGED1にICSP端子がつながるようになっている。

であった。さらにソースを一通り眺めてみた。

  • 「main.c」からは「HardwareProfile.h」がインクルードされている。
  • 「HardwareProfile.h」を見ると、PIC24FJ256GB106を選択すると「Hardware Profile – PIC24F Starter Kit.h」がインクルードされることがわかる。
  • 「Hardware Profile – PIC24F Starter Kit.h」をみると、91行目で「PIC24F_STARTER_KIT」がdefineされる。
  • 再び「main.c」を見ると、213行目でCONFIGビットの設定が記述されていることがわかる。
    _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
    _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV3 & IOL1WAY_ON)

    CONFIG1は、JTAG禁止、コードプロテクトOFF、ライトプロテクトOFF、Clip-on Emulatorイネーブル、ウォッチドッグタイマOFF、さらに「ICS_PGx2」でPGEC2/PGED2とICSP端子をシェアする設定になっているので、ここを「ICS_PGx1」に変更する必要がありそう。
  • CONFIG2はTwo Speed Start UpがOFF、Clock Switch & Monitorが両方OFF、OSCO端子機能はRC15、HS oscillator、Primary oscillarot w/ PLL、RPレジスタへの書込み制限無しで、さらに「PLLDIV_DIV3」はオシレータの周波数が12MHzの時の設定だから、ここは「PLLDIV_DIV4」へ変更が必要と思われる。
  • 再び「Hardware Profile – PIC24F Starter Kit.h」をみると、95行めから122行目でデモボード上のLEDやスイッチに関する入出力の記述がある。

ということがわかった。

そこで、「HardwareProfile – PIC24F Starter Kit.h」の94行めから123行めのLEDとSWのマクロ定義の中身を適当に修正する。ポート読出し用は0か1固定、ポート書込み用は中身を空にすることにした。この状態だと、「main.c」のProcessIO()関数の中身によれば、入力されたASCIIコードに1を足したものをエコーする(つまり、AをタイプするとBを表示する)プログラムとなるようだ。

修正してコンパイルしたところ問題なくコンパイルが通ることが確認できた。

これをPICkit2で書き込んでリセット解除すると、新しいCDCクラスのデバイスとして認識され、「USB Device – CDC – Basic Demo」フォルダの下の「inf」フォルダ内のinfファイルをインストールすると、COM12ポートが生成された。TeraTermでCOM12を開いて、キーを入力すると、期待通りタイプしたキーのASCIIコードに1を足した文字が表示された。

ATmegaとのシリアル通信~AVRLibのtimerのテスト

同様に、AVRlibのタイマーのテストを行いました。修正箇所は、

  1. プロジェクトディレクトリの global.h のCPU動作周波数を8MHzに修正
  2. プロジェクトディレクトリの Makefile のROM書込みに関する部分を追加変更前は、
    ########### change this lines according to your project ##################
    #put the name of the target mcu here (at90s8515, at90s8535, attiny22, atmega603 etc.)
    # MCU = atmega8515
    MCU = atmega163
    # MCU = atmega323
    # MCU = atmega161
    # MCU = atmega128

    変更後は、

    ########### change this lines according to your project ##################
    #put the name of the target mcu here (at90s8515, at90s8535, attiny22, atmega603 etc.)
    # MCU = atmega8515
    # MCU = atmega163
    # MCU = atmega323
    # MCU = atmega161
    # MCU = atmega128
    MCU = atmega88
    
    # FUSE BIT for ATMEGA88/168(default is E=0x01/H=0xDF/L=0x62)
    EFUSE = 0x01
    HFUSE = 0xDF
    # LHUSE = 0x62
    LHUSE = 0xe2
    
    # WRITER parameter
    WRITER = -c avrispmkII -P usb
    WRITER_MCU = m88
    
    #directory of AVRLib
    AVRLIB = /(適切に・・・)/avrlib
  3. 同じく Makefile のソースファイルに関する部分を変更
    変更前は、

    #put your C sourcefiles here
    # Here you must list any C source files which are used by your target file.
    # They will be compiled in the order you list them, so it's probably best
    # to list $(TRG).c, your top-level target file, last.
    
    SRC = $(AVRLIB)/buffer.c $(AVRLIB)/uart.c $(AVRLIB)/rprintf.c $(AVRLIB)/timer.c $(TRG).c

    変更後は、

    # put your C sourcefiles here
    # Here you must list any C source files which are used by your target file.
    # They will be compiled in the order you list them, so it's probably best
    # to list $(TRG).c, your top-level target file, last.
    
    SRC = $(AVRLIB)/buffer.c $(AVRLIB)/uart.c $(AVRLIB)/rprintf.c $(AVRLIB)/timerx8.c $(TRG).c
  4. 同じく Makefile の依存関係に関する部分を変更
    変更前は、

    timer.o : timer.c timer.h global.h

    変更後は、

    timer.o : timerx8.c timerx8.h global.h

結局、タイマー周りの修正が要る、ってことですね。
これで一応シリアルの表示上は動いている(ポーズもそれっぽく掛かっている)気がするのですが、PWM出力の方は出ていないようです。
この辺はまた今度にすることにします。

ATmegaとのシリアル通信~AVRLibの導入

ATMEGA88を使うことにしたのですが、シリアル制御を一から作るのも面倒くさい、ということで、ちょっと古いようですが、AVRLibを試してみることにしました。

まず、ZIPファイルをダウンロードしてきて、展開します。
環境変数AVRLIBに avrlib のディレクトリ位置を(avrlibの名前を)設定して、rprintf のサンプルディレクトリに移動。
makeすると、makeはされるのですが、ATmega163用にmakeされてしまいます。
今回のターゲットはATmega88なので修正を試みます。

現状の修正箇所は、

  1. サンプルプログラムの makefile の MCU の定義
    「MCU=atmega88」に書き直します。
  2. サンプルプログラムの makefile の AVRLIB の設定
    環境変数ではなく、ここで記述してみます。(未検証)
    AVRLIB = /(ほげほげ)/AVR-PROJ/avrlib
  3. サンプルプログラムの makefile の SRC の設定
    timer.c を使うとレジスタ定義が異なるので、timerx8.c に変更
  4. サンプルプログラムの makefile の終わりの方の依存関係(dependencies)の修正
    「timer.o : timer.c timer.h global.h」を「timer.o : timerx8.c timerx8.h global.h」に修正
  5. global.h の F_CPUの値の修正
    現状、7372800 が選択されているが、内蔵8MHzを使用するので、8000000に修正
    サンプルプログラムのプロジェクトディレクトリにも global.h がいるので、そちらも直す。
  6. 最近のGCCならCOFファイルはなくても大丈夫だったような気がするので、avrproj_make の「all :」の依存ファイルから $(TRG).cof を削除
  7. どうせなら書込みまでやってしまいたいので、avrproj_make の最後に

    ###### BLOCK 12) make instruction to delete created files ######prog: all
    avrdude $(WRITER) -p $(WRITER_MCU) -F -U flash:w:$(TRG).hex -U eeprom:w:$(TRG).eep -U efuse:w:$(EFUSE):m -U hfuse:w:$(HFUSE):m -U lfuse:w:$(LFUSE):m

    を追加。(このままだと拡張ヒューズビット無しのCPUに書くとき困るけど、とりあえずそのままで・・・)

  8. 同じくサンプルのmakefileに

    # FUSE BIT for ATMEGA88/168(default is E=0x01/H=0xDF/L=0x62)
    EFUSE = 0x01
    HFUSE = 0xDF
    # LHUSE = 0x62
    LHUSE = 0xe2# WRITER parameter
    WRITER = -c avrispmkII -P usb
    WRITER_MCU = m88

    を追加

とすることで、rprintfのテストを実施が通るようになりました。(サンプルプログラムの方の global.h を修正し忘れていて、通信速度がおかしく、しばらく悩んでしまいました・・・)

無事にシリアル通信が通るようになりました!

 

秋月ZigBeeモジュールの先にAVRをつなぐ

XBeeによって、リモートUARTの環境を構築、ループバック動作を確認できたので、その先のコントローラとして、AVRをつないでみることにしました。AVRにしたのは、Linux環境で閉じた開発ができるからということと、手持ちに ATmega88 が何個か転がっていた(PIC24FJ64も転がっていますが・・・)からです。

Zigbee子機をもう少し大きめのブレッドボードに移植し、ATmega88と同居させました。
・・・といっても、写真では見えないですね。書込みは AVRISPmkII で行っています。
ISP用の端子6本は写真右側に写っているブレッドボード用の自作アダプタを介してその下のATmega88につながっています。

その他、シリアル通信用の端子をXBeeとの間で接続しました。

このATmega88に対してシリアルでコマンド/ステータス通信をさせるようにしていきます。

LinuxでFTDIのFT232RLを使う(3) X-CTUをWINE経由で使う

もっとダイレクトにX-CTUをWINEで使っている方がいるようなので、試してみました。

  1. X-CTUのインストーラに実行権限を付ける
  2. X-CTUのインストーラをWINE経由で実行させ、インストールを行う。
  3. WINEに仮想COMポートを認識させるため、デバイスファイルへのシンボリックリンクを貼る
    「 ln -s /dev/ttyUSB1 /home/tom/.wine/dosdevices/com11」として、Windowsから見たCOM11を作成する。
  4. X-CTUを起動する。
  5. Windowsであれば、全てのCOMポートを勝手に検出してくれますが、WINEでは上手くいきません。そこで、X-CTUの「PC Setting」の項目で、「Add User Com Port」のところにポート番号(上記のCOM11の場合は「11」)を入れて、「Add」を押してポートの存在を教えてやります。
  6. 『Test/Query』を実行する

で接続確認ができます。しかし、残念ながら、Modem Configuration のタブはファームウェアが見つからないとかで、ダウンロードを試みるのですが、それでもみつからないということで、動作しませんでした。ま、ターミナルが動くだけでもずいぶん助かりますので、よしとします。

LinuxでFTDIのFT232RLを使う(2) ターミナルソフト編

続いて、通信ターミナルです。
通信ターミナルは、Minicomを使ってみることにしました。例によってSynapticからインストールします。
Minicomはモデムでの通信用のソフトなので、そのまま起動するとモデムを初期化しようとします。
そこで、minicom -s で設定画面に入り、モデム初期化文字列を全て消去します。
その後、設定ファイルを保存するのですが、/etc/minicom の下に保存しようとするため、このディレクトリのパーミッションを開けておきます。保存されたファイルを以下に示します。

$ cat minirc.dfl
# Machine-generated file – use “minicom -s” to change parameters.
pu port /dev/ttyUSB1
pu baudrate 9600
pu minit
pu mreset
pu mdialpre
pu mdialsuf
pu mdialpre2
pu mdialsuf2
pu mdialpre3
pu mdialsuf3
pu mconnect
pu mnocon1
pu mnocon2
pu mnocon3
pu mnocon4 VOICE
pu localecho Yes
$

ただ、ポートは場合によって変わるので、dmesgなどで確認した後変更が必要です。

これで一応、XBeeをコントロールすることはできるのですが、改行の処理は今ひとつ上手くいきません。
まあ、動作しているかどうかの確認くらいはできますが・・・。

LinuxでFTDIのFT232RLを使う(1) ドライバ編

ZigBeeモジュールであるXBeeが動き始めたのですが、できればこれをLinuxマシンに接続して動かしたいと思っています。すなわち、秋月のFT232RLモジュールをLinuxで使いたいのです。

早速、FTDIのサイトを見てみると、Linux版のドライバも存在しています。そのコメント欄を見ると、「Included in 2.6.31 kernel and later」と書かれています。つまり、2.6.31以降のカーネルであれば初めから入っていそうです。

そこで、コンソールを開いて見てみると、

>$ uname -a
Linux atom 2.6.32-26-generic #48-Ubuntu SMP Wed Nov 24 09:00:03 UTC 2010 i686 GNU/Linux

ということで、2.6.32なので大丈夫そうです。
おそるおそる、Linuxマシンに挿してみると、

$ dmesg
[56118.520287] usb 1-7.3: new full speed USB device using ehci_hcd and address 4
[56118.618644] usb 1-7.3: configuration #1 chosen from 1 choice
[56119.069612] USB Serial support registered for FTDI USB Serial Device
[56119.069790] ftdi_sio 1-7.3:1.0: FTDI USB Serial Device converter detected
[56119.069853] usb 1-7.3: Detected FT232RL
[56119.069858] usb 1-7.3: Number of endpoints 2
[56119.069864] usb 1-7.3: Endpoint 1 MaxPacketSize 64
[56119.069869] usb 1-7.3: Endpoint 2 MaxPacketSize 64
[56119.069873] usb 1-7.3: Setting MaxPacketSize 64
[56119.070318] usb 1-7.3: FTDI USB Serial Device converter now attached to ttyUSB1
[56119.070362] usbcore: registered new interface driver ftdi_sio
[56119.070367] ftdi_sio: v1.5.0:USB FTDI Serial Converters Driver
$

ということで、ttyUSB1として認識されているようです。ただし、

$ ls -la /dev/ttyUSB*
crw-rw—- 1 root dialout 188, 0 2010-12-08 07:31 /dev/ttyUSB0
crw-rw—- 1 root dialout 188, 1 2010-12-08 23:06 /dev/ttyUSB1
$

となっているので、dialoutグループに自分のユーザ名が入っていないといけないようです。

ZigBeeモジュール通信テスト

秋月電子で買ってきたZigBeeモジュール(XBee)ですが、ようやく通信テストにこぎつけました。

まず、子機(写真では下側のXBee)に電源を供給するため、ニッケル水素電池から3.3Vを供給する子基板(写真では縦になっていてわかりにくいですが、スイッチと3.3Vのロードロップレギュレータとコンデンサ、ポリスイッチが載っているだけです)を作りました。そして以下のように接続しています。

  • XBeeの1ピンに3.3Vを供給
  • XBeeの2ピンと3ピンを接続(ループバック状態)
  • XBeeの10ピンをGNDに接続
  • XBeeの15ピンをLEDに接続
  • XBeeの20ピンはハーネスを挿してあるだけ(必要に応じてGNDにチョンチョン、とつなぐ)

親機(写真では上側のXBee)は単体でのテストから少し変えて、XBeeの13ピンをLEDに接続していたのを15ピンに変更することで、XBeeの動作状態が多少でもわかるようにしています。

20ピンは、こちらのページに記載のあった
  • プッシュスイッチ1回でネットワークへの参加。他のXBeeモジュールのLEDが1秒間高速点滅。
  • プッシュスイッチ4回で他のネットワークへ参加してしまった場合にネットワーク設定を消去してソフトリセットする。
のに使っています。
設定は、X-CTUを使って以下の設定を行いました。
  • 親機側のFunction Setを「ZIGBEE CORDINATOR AT」に変更して「WRITE」
    (これはネットワーク内に1台必要なのだそうです)
  • 両方のDH/DLパラメータを相手のシリアルナンバー(SH/DL)に変更して「WRITE」
これで、以降は電源ONでつながるようになりました。この状態なら、1対1接続であれば以降はXBeeの存在を意識することなく使えることになります。
さらに、X-CTUのRangeTestを使って、到達距離を確認してみました。当方は鉄筋コンクリートのマンション住まい(いわゆる3LDKのごく普通の間取りです)で、PCのある部屋は共用通路側です。XBeeはベランダにおいて、太陽電池動作で温度や湿度、気圧などを遠隔で測ってみたい、と思って購入しましたので、まずベランダに子機側を置いて試してみました。間にあるものと言えば、専有部の壁、水回り(洗面所、風呂場)、和室の押入れ和室の窓などで、距離にして15メートルくらいでしょうか。結果としては、まったく通信できませんでした。
距離を短くして、リビングルームの近い側に置いたのですが、通る確率は10%くらいでやはりダメ。廊下を挟んで反対側の寝室のベッドの上では概ね通信できるのですが、それでもエラーが発生するような状態でした。この時の状態は、距離にして5メートルくらい。専有部内の壁〔おそらく薄いスチール+石膏ボードだったと思う〕が2枚ある感じです。親機側はPCがそばにあったり、LCDモニタが2枚すぐまん前にあったりして状態がよくないのですが、それにしても鉄筋コンクリート環境ではかなり通信距離は短いようです。
今度秋月電子に出かけたときには、送信出力の大きいXBeeProを入手したいと思います。
≪参考にしたページ≫
  • ボクにもわかる地上デジタル – 地デジ方式編 – ZigBee無線リモコン –

秋月ZigBeeモジュールとの接続テスト

なんとかブレッドボードに載るようになったXBeeですが、X-CTUを使ってモジュールとの接続テストを実施しました。

右側のXBeeはまだ何もつないでいません

XBeeの電源は3.3Vの50mA以下ですので、秋月電子のFT232RLモジュールから供給させることにしました。接続は以下の通りです。

  • XBeeの1ピン(VCC)とAE-UM232RLの19ピン(3V3)
  • XBeeの2ピン(DOUT)とAE-UM232RLの5ピン(RXD)
  • XBeeの3ピン(DIN)とAE-UM232RLの1ピン(TXD)
  • XBeeの10ピン(GND)とAE-UM232RLの24ピン(GND)
  • XBeeの12ピン(CTS#/out)とAE-UM232RLの10ピン(CTS#/in)
  • XBeeの13ピン(ON)を抵抗・LEDを通してGNDへ
  • XBeeの16ピン(RTS#/in)とAE-UM232RLの3ピン(RTS#/out)
  • XBeeの1ピン(VCC)とAE-UM232RLの24ピン(GND)

WindowsXPマシンにFT232RLのドライバは元々入っていましたので、PCに接続し、COMポートを確認して、Modem ConfigurationのタブでReadを押すと、以下のように設定情報を読み取ることができました。

このままモジュール間の接続テストを行いたいところですが、FT232RLの供給可能な電流は50mA、XBeeの消費電流は最大45mAです。電流容量が不足しており、1つのFT232RLから供給することはできませんので、ここまでとしました。

秋月でZigBeeモジュールを買ってきた!

土曜日に秋月電子に行ってきたので、先日から気になっていたXBeeモジュールを買ってきました。

通信相手がいなければ意味がないので2個買ってきました。
写真では見えないですが、2ミリピッチのコネクタも付いています。

XBeeとXBeeProの両方があったのでちょっと焦りましたが、送信出力の差のようですので、今回はProではないZigBeeの方を選択しました。
すでに調べていた通り、このモジュールは2ミリピッチのコネクタで外部と接続しますので、通常のユニバーサル基板やブレッドボードに搭載するには何らかの工夫が必要になります。定番は、スイッチサイエンスのピッチ変換基板なのでしょうが、実験は横着して直接半田付けしてしまうつもりでいました。
・・・が、秋月店内を見回していたら、2ミリピッチのユニバーサルボードがありました。そこでこれを使って、こんなものを作ってみました。

ガラスエポキシ基板どうしなので、2液混合のエポキシ系接着剤でガッチリ
固定できます。元の基板と変わらないくらいの強度が出ます。

見たまんまですが、2.54ミリピッチのユニバーサル基板を細く切り出し、半分に切った2ミリピッチのユニバーサルボードとエポキシ系の2液混合タイプの接着剤で接着しました。
そして2.54ミリピッチの部分にはピンヘッダを、2ミリピッチの部分にはZigBeeに同梱されているソケットを半田付けし、その間を1対1で接続してあります。

今日のところは疲れたのでここまでです。