Raspberry Pi 2 Model B に WiFi、AD変換ICでアナログ入力

投稿日:
とりあえず無線LANにする

 Raspberry Pi、線がダラダラつながっているのは面倒くさいから、メインのifをWiFiにしてみたい。たまたま、Raspberry Piと相性がいいと言われるUSBのWiFiアダプタ「PLANEX GW-USNano2」というのをかなり前から持っている。

 USBポートにとりあえずこれを挿入し、

# lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS]

……もう、サクッとプラグアンドプレイの一発認識である。

# ifconfig
eth0      Link encap:イーサネット  ハードウェアアドレス b8:27:eb:45:1d:d0
          inetアドレス:192.168.1.105 ブロードキャスト:192.168.1.255  マスク:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:498 エラー:0 損失:1 オーバラン:0 フレーム:0
          TXパケット:253 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:1000
          RXバイト:46665 (45.5 KiB)  TXバイト:34011 (33.2 KiB)

lo        Link encap:ローカルループバック
          inetアドレス:127.0.0.1 マスク:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  メトリック:1
          RXパケット:8 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:8 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:0
          RXバイト:1104 (1.0 KiB)  TXバイト:1104 (1.0 KiB)

wlan0     Link encap:イーサネット  ハードウェアアドレス 00:22:cf:97:fe:b9
          inetアドレス:192.168.1.107 ブロードキャスト:192.168.1.255  マスク:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:506 エラー:0 損失:169 オーバラン:0 フレーム:0
          TXパケット:25 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:1000
          RXバイト:128714 (125.6 KiB)  TXバイト:4541 (4.4 KiB)

 これも、もう、イッパツ。

 で、# shutdown -i0 -g0 -y、LANケーブル抜いて電源を入れなおす。

 サクッとつながる。ケーブルがだらだらつながっていたのが減って、これはとてもいいなあ。

USBのWiFiアダプタが快調に作動している様子
IMG_3308

アナログ入力をしてみる

 さて、今度はいろいろといじってみよう。

 Raspberry PiとArduinoにはいろいろと違いがある。その違い認識は世間ではもうとうの昔に確定済みであるようだが、私はその無視できない一つが「アナログ入力のあるなしではないだろうか?」と思い至っている。

 Arduinoはシンプルで扱いやすいにもかかわらず、10ビットのアナログ入力が6個もあり、これは意外と使い応えがある。抵抗やポテンショメータ、サーミスタ、CDSセル、音声など、実にいろいろなものをつなぐことができるのだ。

 だが、Raspberry Piにはアナログ入力は、ない。

 アナログ入力をしたければ、手段の一つに「Arduinoをつなぐ」というのがある。Arduinoを持っているなら、これは良い手段だが、なんだか無駄が大きい。

 もう一つが、「A/D変換器をつなぐ」ということだ。A/D変換IC、つまり「ADC」は、百何十円~数百円だから安い。合理的である。

 これについて解説しておられるサイトはたくさんある。それを参考にさせていただき、早速秋葉原へ行って2種類ばかりICを買い込む。

 これは、マイクロチップ・テクノロジー社製の「MCP3008-I/P」。8チャンネル10ビット、千石電商で320円。

MCP3008-I/P
IMG_3309

 コッチは、同じくマイクロチップ・テクノロジー社の「MCP3208-CI/P」。こちらも8チャンネルだが、幅は12ビット。秋月電子でソケット付き、データシート付きで320円。

MCP3208-CI/P
IMG_3310

 ついでにこの前壊したTLC5940NTも二つ買い込む。これも390円。

TLC5940NT
IMG_3311

 で、まずはMCP3208から試してみよう。

 Raspberry PiとICは、SPI通信でつなぐ。そのため、まず、Raspberry PiでSPI通信を行う要領を知る必要がある。

 Raspberry Piの場合は、SPIのモジュールをインストールしたり、ブラックリストから外すなどの着意が必要であったようだが、Raspberry Pi 2 の場合は、どうやらそのような操作は必要がなく、「# raspi-config」でAdvancedの中からSPIを選び、enableにすればよい。

 lsmodで確認し、次のように「spi_bcm2835」というモジュールが入っていればSPIが使える。

$ lsmod
Module                  Size  Used by
cfg80211              420690  0
rfkill                 16659  1 cfg80211
snd_bcm2835            19769  0
snd_pcm                74825  1 snd_bcm2835
snd_seq                53561  0
snd_seq_device          3650  1 snd_seq
snd_timer              18157  2 snd_pcm,snd_seq
snd                    52116  5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
8192cu                528485  0
spi_bcm2835             7100  0
i2c_bcm2708             5014  0
uio_pdrv_genirq         2966  0
uio                     8235  1 uio_pdrv_genirq

 さっそくブレッドボードにMCP3208を配置し宮城大学のサイトの記事にあるコードを使わせてもらったのだが、これがそのままでは動かず、ハマッた、ハマッた……。

ブレッドボードの状況
IMG_3312

 何か、Raspberry PiとRaspberry Pi 2 で、ioctrlに渡すデータ長に違いでもあるらしく、かなり試行錯誤した末、このようになった。

 宮城大学のサイトにあった元のコード(“raspSPI.cpp”内)

//  sendRecN: Nバイトデータの送信と受信(2048バイトまで)
void SPI::sendRecN (unsigned char *send, unsigned char *rec, int n)
{
    //  setup a block
    struct spi_ioc_transfer tr[1];
    tr[0].tx_buf = (unsigned int) send;
    tr[0].rx_buf = (unsigned int) rec;
    tr[0].len    = n;
    tr[0].speed_hz      = clock;
    tr[0].delay_usecs   = SPI_DELAY;
    tr[0].bits_per_word = SPI_BITS;
    tr[0].cs_change     = 0;
    //  send this byte
    int ret = ioctl(fd, SPI_IOC_MESSAGE(1), tr);
    if (ret < 0) {
        printf("error: cannot send spi message (SPI::sendRecN)\n");
        exit(-1);
    }
}

 Raspberry Pi model Bで動くように少し変更したコード(tr[]の個数と、tr[0]に渡す値のキャストを「int」から「unsigned long」に変更している)

//  sendRecN: Nバイトデータの送信と受信(2048バイトまで)
void SPI::sendRecN (unsigned char *send, unsigned char *rec, int n)
{
    //  setup a block
    struct spi_ioc_transfer tr[3];
    tr[0].tx_buf = (unsigned long) send;
    tr[0].rx_buf = (unsigned long) rec;
    tr[0].len    = n;
    tr[0].speed_hz      = clock;
    tr[0].delay_usecs   = SPI_DELAY;
    tr[0].bits_per_word = SPI_BITS;
    tr[0].cs_change     = 0;
    //  send this byte
    int ret = ioctl(fd, SPI_IOC_MESSAGE(1), tr);
    if (ret < 0) {
        printf("error: cannot send spi message (SPI::sendRecN)\n");
        exit(-1);
    }
}

(作動させた画面の様子)

  1132   867   827   829   833   838   877  2670
  1090   829   787   787   792   797   845  2668
  1028   768   725   721   724   732   796  2671
   929   678   631   623   625   636   737  2669
   791   534   471   444   429   435   572  2667
   408   172    94    54    29    53   281  2668
    84     0     0     0     0     0   111  2666
     0     0     0     0     0     0    20  2671
     0     0     0     0     0     0     0  2670
     0     0     0     0     0     0     0  2668
    19    29    34    39    41    36    27  2670
    87    93   101   110   114   107    81  2670
   173   173   183   195   201   186   146  2671
   274   276   300   327   347   339   276  2667
   614   609   650   692   727   698   552  2668
   948   901   907   902   911   916   741  2672
  1102   916   878   886   894   899   854  2670
  1160   888   865   868   873   878   913  2671
  1137   872   832   833   838   843   903  2665
  1093   830   788   787   792   796   869  2668
  1027   767   723   717   721   727   815  2669
   938   685   638   631   632   643   748  2669
   821   566   504   482   467   474   603  2665
   447   206   128    89    62    85   303  2669
   107     0     0     0     0     0   123  2670
     0     0     0     0     0     0    32  2669
     0     0     0     0     0     0     0  2667
     0     0     0     0     0     0     0  2670
    14    23    29    34    37    32    29  2669
    81    86    94   102   104    98    80  2665
   170   167   177   186   191   174   141  2671
   267   267   290   314   333   323   263  2668
   598   593   631   669   702   672   536  2670
   936   888   908   904   913   914   723  2669
  1098   917   876   888   894   899   840  2668
  1157   895   864   869   875   878   904  2668
  1138   873   834   835   841   844   902  2667

 7番ピンにポテンショメータをつなぎ、残りのピンは解放してあるので、乱雑な値が出ている。

投稿者: 佐藤俊夫

 50代後半の爺。技術者。元陸上自衛官。2等陸佐で定年退官。ITストラテジストテクニカルエンジニア(システム管理)基本情報技術者

「Raspberry Pi 2 Model B に WiFi、AD変換ICでアナログ入力」への15件のフィードバック

  1. 私もこの件で3日悩んでいます(^_^;
    SPI::sendRecN の if (ret < 0) のチェックで必ず引っかかり前に進みませんでしたので、当記事を参考にさせていただいたのですが、改善せずです。

    Rasperry Pi 2 からドライバ関係のセットアップが rasp-config に変更になったため、まだあまり参考記事がなく困っています。

    よろしければ、SPI::sendRecN の修正箇所を見つけた方法を教えていただけますでしょうか。

    よろしくお願い致します。

      1.  返信する時間がなく、今日になりました。私が返信する前にうまく動いたとのことで、何よりです。

         見つけた方法は、どなたかがyahoo知恵袋に次のように書いておられるのを見つけ……

        http://note.chiebukuro.yahoo.co.jp/detail/n352937

         そこで、念のため

        /usr/include/linux/spi/spidev.h

        ……を開いて「spi_ioc_transfer」の定義を見ていきますと、問題のtx_bufとrx_bufは

        struct spi_ioc_transfer {
        __u64 tx_buf;
        __u64 rx_buf;


        ……と定義されており、元のunsigned intは32ビットですから、大きさが違うな、ということを見て取った次第です。

         ただし、修正版のunsigned longも32ビットですので、これも違うと言えば違うんですよね……(苦笑)。

         ここからは実はよく確かめていないのですが、元のソースコードの配列の個数を1個から3個に増やしていることなどでなんとなく吸収しているのかな……などと思っています。

         もし試すとすると、配列の個数を元に戻し、「#include <linux/types.h>」を足して、キャストを「(unsigned long)」から「(__u64)」にしてみる、などもあるかもしれません(私は試してません)。

        1. お忙しいところ返信ありがとうございます。

          配列数を3のままにして、unsigned intに戻しても無事通っているので、3で吸収できているような気もします。

          また何かわかりましたらお知らせ致します。

          1. 当関数は通るようになったのですが、表示データがずっと”0″という現象に悩んでいます。

            オシロスコープでSPI関連端子をモニターしたところ、SPI信号は皆無でした。

            ポートがSPIモードになっていないのではないかと思っています。

            lamod でモジュールを教示させると、
            spi-bcm2835
            i2c_bcm2708
            この二つが表示されています。
            あちこちのサイトにあるspidevは表示されていません。

            佐藤様の環境ではspidevは表示されていますでしょうか?

            よろしくお願い致します。

  2. >Satoshi Higa 様

     今、現に動いている最中の私の環境では、次のようになっております。

    $ lsmod
    Module Size Used by
    cfg80211 420690 0
    rfkill 16659 1 cfg80211
    snd_bcm2835 19769 0
    snd_pcm 74825 1 snd_bcm2835
    snd_seq 53561 0
    snd_seq_device 3650 1 snd_seq
    snd_timer 18157 2 snd_pcm,snd_seq
    snd 52116 5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
    evdev 10232 0
    joydev 9047 0
    i2c_bcm2708 5014 0
    spi_bcm2835 7100 0
    uio_pdrv_genirq 2966 0
    uio 8235 1 uio_pdrv_genirq
    8192cu 528485 0

     この状態で、温度を測る試みができております。

     実は、私も、コンパイルが通るようになってから、ゼロばかり出てくる、ということに悩まされまして、その時はソフトウェアではなく、結線ミスでした。

     これもよく確かめていないのですが、結線ミスを2回やってしまいました。結局うまく動いたので、それで原因を確かめていないのです。2回同じ結線ミスをしたということは、参照しているどれかの資料が、一部間違っているのかな、と、今、急に思い至りました次第です。

    1. 佐藤様、お忙しいところ有益なコメントありがとうございます。

      加藤様のコメントをきっかけに、ハードウェアをとことんチェックしてみました。

      まずADコンバータを造りこんだ拡張基板を外して、ピンヘッダを直接オシロスコープでモニターしたところ、SPI信号は正しく出力されていることが確認されました。

      これでソフトウェアの問題はクリアとなりました。

      そこで拡張基板上の回路を徹底的にチェックしたところ、配線は間違っていなかったのですが、3.3V→5Vのレベル変換チップが正しく動いていないことがわかりました。

      明日新品の部品と取り換えて再度デバッグしてみます。

      成功したらまたお知らせいたします。

      1.  多少なりともお役に立てたようなことで、何よりです。

         こうして文字列を露出させておけば、正しい正しくないはさておき、似たようなことを試す多くの方が私たちの行動を参考にすると思いますので、有益なことと思います。

         私としては、アナログの入力には少し知見を得ましたので、今度はRaspberry Piから、どうにかしてアナログの出力を得たいものと考えております。

        1. 無事解決しました!

          レベルコンバータのイネーブルロジックを勘違いしていたのと、なんやかんやでADコンバータチップを壊してしまったようで、イネーブルロジックを反転してADコンバータを取り換えたところ、ちゃんと何らかのデータを出力するようになりました。

          これまでお忙しい中ご協力ありがとうございました。

          これでやっと次のステップへ進められます。

          重ねてお礼申し上げます。

          今回の回路の用途は特定用途のオシロスコープの試作機になります。佐藤様もアナログデータを扱われたいとのことですので、アナログ系で何らかの恩返しができればと思います。
          なので引き続きブログをフォローさせていただきます。

          ※この一連のメッセージで救われる人がいれば何よりですね。

          1.  無事にご解決とのこと、なによりです。ADCが壊れていたとのこと。私は先日、LEDドライバICを壊しましたが、それは3端子レギュレータで定格電圧を印加してからArduinoでロジックを入れたところ、どうも順序の違いによるものでしょうか、あっさりと壊れてしまいました。私ももう少し精進したいと思っております。

             特定用途のオシロスコープをご製作中とのこと、難しいものを手掛けておられて、驚き入るばかりです。

             私は、アナログ出力を試して、それから、少年時代は別として、あまり「モーターで動くもの」をやっておりませんので、なにかそういうことをやってみようかな、と思っているところです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください