Pressure Sensor

大型の台風18号と19号が連続で発生して、それに合わせたわけでは無いと思うが秋月電子通商で大気圧センサをDIP基板化したモジュールが発売されたので、台風19号の上陸前に入手して試してみた。

インターフェースはI2CとSPIが選択可能で、Raspberry Piでは不要だがI2C使用時はジャンパーでプルアップ抵抗も有効にできる。LEDも載っていて通電すると光るのだが、これは不要な気がする。コマンドからの応答が無い時に、通電してないのか他の要因なのかが識別できる程度のメリットしか無い。まあこのモジュールをそのまま製品に使う事は無いだろうし、ブレッドボードで実験するだけなら消費電力が僅かに増えるのも気にはならないだろう。

使用方法はデータシートに記載されている通り、最初にパワーダウンモードから復帰させてあとは24ビットのデータを3つのレジスタから読み出せば良い。読み出した値を4096で割ったものが気圧(ヘクトパスカル)になる。

プログラムは以下の通り

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import quick2wire.i2c as i2c
import time
import sys

LPS25H = 0x5c

def i2c_read(addr, reg):
    with i2c.I2CMaster() as bus:
        data = bus.transaction(
                    i2c.writing_bytes(addr, reg),
                    i2c.reading(addr, 1))
        return data[0][0]

def i2c_write(addr, reg, data):
    with i2c.I2CMaster() as bus:
        bus.transaction(i2c.writing_bytes(addr, reg, data))

def get_press(addr):
    xl = i2c_read(addr, 0x28)
    l  = i2c_read(addr, 0x29)
    h  = i2c_read(addr, 0x2A)
    p = h >> 16 | l >> 8 | xl
    return round(p / 4096, 1)

def get_temp(addr):
    l = i2c_read(addr, 0x2B)
    h = i2c_read(addr, 0x2C)
    t = h >> 8 | l
    if t & 0x8000:
        t = -((t - 1) ^ 0xFFFF)
    return round(42.5 + (t / 480.0), 2)

if __name__ == '__main__':
    whoami = i2c_read(LPS25H, 0x0F)
    if whoami != 0xbd:
        print('device incorrect.')
        sys.exit()
    i2c_write(LPS25H, 0x20, 0x90)
    time.sleep(1)
    try:
        while True:
            pha = get_press(LPS25H)
            print(pha, "hPa")
            temp = get_temp(LPS25H)
            print(temp, "C")
            time.sleep(1)
    except KeyboardInterrupt:
        print('\nbreak')            

実際に台風19号が関東上空を通過している時にこのプログラムを動かして見ていると、グングン気圧が下がっていったのが面白かった。気象庁が一時間おきに発表している東京都の計測データと照らし合わせると1hPa程度低い値になっていたが、これは観測地点の差によるものだろう。

ちなみにこのモジュール内には温度センサも内蔵されていて、同時に読み出してみるとADT7410を使用した温度センサモジュールよりも0.5℃ほど低い値を示した。正確な温度計が無いのでどちらが正しいのかは分からないのだが、大気圧センサに内蔵されている温度センサは気圧の補正用途で、あまり精度は高くないらしい。温度センサの値はだいたいの目安程度に考えたほうが良いだろう。

広告

Linuxでリモート接続

普段仕事で使用しているのがWindows PCなので、Raspberry Piへリモート接続する場合はWinSCPやputtyといったWindows用のツールを使用して行っているのだが、Raspberry PiはLinuxベースなのでリモート接続もLinuxからのほうが簡単に行える。

Windows上に仮想PCツールVirtualBoxでLinux(Xubuntu)環境を構築したので、そこからRaspberry Piにリモートアクセスを行ってみた。まずはコンソール(ターミナルエミュレータ)からの接続で、これはSSHコマンドで簡単に行える。クライアントとなるLinux側から、以下のようにSSHコマンドを実行すれば良い。もちろんIPは接続するRaspberry Piのアドレスを指定する。

$ ssh -l pi 192.168.1.2

パスワードを入力すれば接続完了。あとは普通に使うことができる。

ファイルマネージャからRaspberry Piのファイルにアクセスする場合は、ファイルマネージャの機能を使う方法と、マウントして行う方法の二通りがある。Xubuntuは標準では「Thuna」というファイルマネージャが使われているので、まずはそれで接続する方法。異なるファイルマネージャが採用されているLinuxディストリビューションでは、当然ながら同じようには設定できないが、同等の機能は何かしらあるはずだ。

ファイルマネージャのメニューで「移動→指定場所を開く」を選択、または「Ctrl+L」を入力。
Xubuntu_Develop

上部の入力窓に

sftp://192.168.1.2/home/pi/

のように接続するRaspberry Piのアドレスとフォルダを入力
Xubuntu_Develop2

IDとパスワードを入力して接続完了。
Xubuntu_Develop3

最後にRaspberry Piのフォルダをマウントして使う方法。これはsshfsを使うので、以下のようにインストール

$ sudo apt-get install sshfs

使用するユーザをfuseグループに所属させてから、再起動

$ sudo adduser $USER fuse

マウントするフォルダを作成して、sshfsコマンドでマウント

$ mkdir mnt
$ sshfs pi@192.168.1.2:/home/pi/ mnt

この場合はRaspberry Piのpiユーザ権限でmntフォルダに/home/pi/フォルダをマウントする。実行するとパスワードを聞かれるので、指定したユーザのパスワードを入力して完了。アンマウントする時は以下のようにfusermountコマンドを使用する

$ fusermount -u mnt

実際に色々と試してみた感じではWindowsからリモートアクセスするよりも、やはり同じLinuxからアクセスしたほうがやりやすい。仮想PCツールでWindows上にも手軽にLinux環境は構築できるので、Raspberry Piにモニタやキーボードを繋がずに使いたい場合にはそれも一つの手だろうと思う。

Quick2Wire(3)

Quick2WireでI2C通信を行うのは簡単で、基本的にはI2CMasterオブジェクトのtransactionメソッドを使用するだけで済む。このメソッドの引数としてI2Cデバイスに対する読み書きを記述する。

説明するよりも実際のコードを見たほうがたぶん早い。お馴染みの温度センサーADT7410をRaspberry PiのI2Cポートに接続して、温度を読み出すプログラムは以下のようになる。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from quick2wire import i2c
from time import sleep

ADT_ADDR = 0x48

def get_temp(addr):
    with i2c.I2CMaster() as bus:
        data = bus.transaction(
                    i2c.writing_bytes(addr, 0x00),
                    i2c.reading(addr, 2))
        h = data[0][0]
        l = data[0][1]
        t = (h << 8 | l) >> 3
        if t & 0x1000:
            t = -((t - 1) ^ 0x1FFF)
        return round(t / 16.0, 2)

if __name__ == '__main__':
    try:
        while True:
            print("current temperature -> %7.2f" % get_temp(ADT_ADDR))
            sleep(1)
    except IOError as err:
        print('\nIOError: {0}'.format(err))            
    except KeyboardInterrupt:
        print('\nbreak')

with文でI2CMasterオブジェクトを作成して、transactionメソッドのパラメータとしてI2CデバイスへのRead/Writeを記述する。これは複数並べて書くことができるので、戻り値は必ず二次元配列(リスト)になる。アドレスが異なるデバイスへのアクセスを記述することもできる。たとえば

with i2c.I2CMaster() as bus:
    data = bus.transaction(
                i2c.writing_bytes(0x48, 0x00),
                i2c.reading(0x48, 2),
                i2c.writing_bytes(0x5c, 0x28),
                i2c.reading(0x5c, 1),
                i2c.writing_bytes(0x5c, 0x29),
                i2c.reading(0x5c, 1),
                i2c.writing_bytes(0x5c, 0x2A),
                i2c.reading(0x5c, 1))

このように書くと、以下のようなデータが帰ってくる

0x48のレジスタ0x00の値 0x48のレジスタ0x01の値
0x5cのレジスタ0x28の値 無効
0x5cのレジスタ0x29の値 無効
0x5cのレジスタ0x2Aの値 無効

複数のI2Cデバイスがぶら下がっているような場合や、一つのI2Cデバイスでも複数のレジスタに同時にアクセスしなければならないような場合に、まとめて記述する事ができるので便利ではないかと思う。ただし、その場合はエラー処理で注意が必要になるかも知れない。

Quick2Wire(2)

前回インストールしたQuick2WireはGPIOのピンに対する入出力と、I2Cによるデバイスとの通信機能を持つので、まずはGPIOの機能について試してみる。

Pythonでプログラムを組んで入出力を行う事はもちろんできるが、Raspberry Piのコンソールから仮想デバイスに対してリダイレクトするだけでも同じことが行える。GPIOピンヘッダの11番ピンがBCMチップのGPIO17で、Quick2WireではPin0(ゼロ)として扱われているので、ここに適当なLEDと抵抗が外付けされているものとする。
ちなみにQuick2WireのGPIO番号とピンヘッダとBCMチップのGPIO番号は以下のように対応している(Raspberry Piのリビジョンがv2の場合)

GPIO 0 1 2 3 4 5 6 7
Header 11 12 13 15 16 18 22 7
BCM 17 18 27 22 23 24 25 4

この状態でコンソールから以下のコマンドを実行する

$ gpio-admin export 17

これで /sys/devices/virtual/gpio/ にgpio17というデバイスが作成されるので、あとはこのデバイスに対してIn/Outの設定と値の入出力を行えば良い。

$ echo out > /sys/devices/virtual/gpio/gpio17/direction
$ echo 1 > /sys/devices/virtual/gpio/gpio17/value

これで接続されているLEDが光るはずだ。
出力されている値はcatコマンドで確認できる。

$ cat /sys/devices/virtual/gpio/gpio17/value
1

使い終わったら以下のようにunexportしておく

$ gpio-admin unexport 17

この一連の仮想デバイスに対する操作は、実はRaspberry Piの基本機能でも可能である。Quick2Wireを使用しなくても、以下のようにすれば同じことができる。

$ echo 17 > /sys/class/gpio/export
$ echo out > /sys/class/gpio/gpio17/direction
$ echo 1 > /sys/class/gpio/gpio17/value
$ echo 0 > /sys/class/gpio/gpio17/value
$ echo 17 > /sys/class/gpio/unexport

以前のRaspbianでは管理者権限が無いとこの操作は行えなかったのだが、現在のバージョンではgpioグループに所属していれば一般ユーザでもGPIOの操作が可能になっている。デフォルトのユーザであるpiは既にgpioグループに所属しているのでそのままで使用できるが、新たに作成したユーザの場合は以下のコマンドでgpioグループに所属させる必要がある。

$ sudo adduser $USER gpio

ユーザをグループに所属させるには usermod コマンドを使用する方法もあるが、元々所属していたグループ情報が失われてしまう危険性があるので、使用しないほうが無難。

PythonでQuick2Wireを使用してGPIOの操作を行う場合は、quick2wire.gpioモジュールをインポートしてその中のPinsオブジェクトを使用すると簡単に入出力が行える。GPIO0(11番ピン)に接続されたLEDを点滅させるプログラムは、以下のようになる。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from quick2wire.gpio import pins, Out
from time import sleep

if __name__ == '__main__':
    try:
        with pins.pin(0, direction=Out) as led:
            while True:
                led.value = 1 - led.value
                sleep(1)
    except KeyboardInterrupt:
        print('\nbreak')

pinオブジェクトの生成時にはIn/Out以外にもプルアップの設定や、信号の変化による割り込みの設定も行える。細かく説明すると長くなるので、入力変化によるイベントのサンプルだけ書いておく。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import select
from quick2wire.gpio import pins, In, Out, Rising, Falling, Both

if __name__ == '__main__':
    led = pins.pin(0, direction=Out)
    btn = pins.pin(7, direction=In, interrupt=Both)
    with led,btn:
        epoll = select.epoll()
        epoll.register(btn, select.EPOLLIN|select.EPOLLET)
        try:
            while True:
                events = epoll.poll()
                for fileno,event in events:
                    if fileno == btn.fileno():
                        led.value = btn.value
        except KeyboardInterrupt:
            print('\nbreak')

GPIO0(11番ピン)にLED、GPIO7(7番ピン)にスイッチが接続されているものとして、スイッチのH/L変化によるイベントでLEDの状態を変化させている。
このサンプルのような単純な処理ではあまりメリットは無いが、selectを使うと複数のI/O処理を登録しておいてイベントで一括処理する事が可能になるので、複雑なプログラムになってくると必要とされる場面もあるかと思う。

Quick2WireのI2C機能については次回に。

Quick2Wire

Raspberry PiはLinuxベースのPCでありながら、I/Oポートに接続されたセンサから値を取得したり、モータやサーボを動かしたりというマイコンボード的な事が手軽にできるのが特徴で、Python言語からGPIOやI2Cを操作する手段も何種類か用意されている。

初期の頃から存在しているI2Cデバイス制御用モジュールsmbusは手軽にpythonから使えるのだが、実行時に管理者権限が必要となる。ユーザと管理者が通常は同一なRaspberry Piではあまり問題にはならないと思うが、リモートデスクトップ等の環境でどうしても一般ユーザ権限で動かさなければならないという場合に困る。

調べてみるとQuick2WireモジュールならI2Cの操作に管理者権限が不要という事なので、インストールして試してみる事にした。
apt-getではインストール出来ないので、少しばかり手順が煩雑になる。

Quick2Wireのドキュメントではvirtualenvを使用した仮想環境での使用が推奨されているので、virtualenvがインストールされていない場合は最初にその環境をセットアップ。ここでは仮想環境の名前を「python32env」とした。

$ sudo apt-get install python-pip
$ sudo apt-get install python-virtualenv
$ virtualenv -p python3 python32env

python32envディレクトリに移動してから

$ source bin/activate

で仮想環境を起動。

次にQuick2Wire-Gpio-Adminをインストール

$ git clone https://github.com/quick2wire/quick2wire-gpio-admin.git
$ cd quick2wire-gpio-admin/
$ make
$ sudo make install
$ cd ..

Quick2Wire-Python-APIをインストール

$ git clone https://github.com/quick2wire/quick2wire-python-api.git
$ cd quick2wire-python-api
$ export QUICK2WIRE_API_HOME=`pwd`
$ export PYTHONPATH=$PYTHONPATH:$QUICK2WIRE_API_HOME
$ git checkout
$ python3 setup.py install
$ cd ..

Quick2Wireを使うためにはユーザがgpioとi2cグループに所属している必要があるので、所属していない場合は以下のコマンドを実行してから再起動する。

$ sudo adduser $USER gpio
$ sudo adduser $USER i2c

pythonを起動して、Quick2WireモジュールがインポートできればOK

~/python32env $ python
Python 3.2.3 (default, Mar  1 2013, 11:53:50)
[GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information.
>>> import quick2wire
>>>

Quick2Wireの使用法については次回に。

GPIOエクステンション改造

Raspberry PiのGPIOポートをブレッドボードに引き出すためのアダプタが以前は国内販売されていなかったので、ピンヘッダとユニバーサル基板を使って自作した物を使っていたが、今は取り扱っている所が増えて楽に入手できるようになった。
ざっと捜してみただけでも色々と見つかる。

Raspberry Pi用T型I/O延長基板
RaspberryPi対応GPIO変換基R板キット (ケーブル無し)
ブレッドボード接続用Raspberry Pi GPIOエクステンションキット (Model B専用)
Raspberry Pi GPIOエクステンション [RPi-GEB]

この中ではaitendoで扱っているアダプタが350円と最も安かったので、試しに一個購入してみた。
VCCとGNDがブレッドボードの電源ラインと直接接続できるタイプなので便利なのだが、電源ラインの位置は規格化されているわけではないので、当然ながら使えないブレッドボードも存在する。
と言うか手持ちのブレッドボードでは全てうまく使えなかった。ギリギリで使えたものでも、微妙にずれていてかなり無理をしないと挿せない。挿すと基板が歪んでしまう。

さすがにその状態で使用するのは不安なので、簡単に改造してみた。電源ラインのピンをハンダゴテで外し、代わりにVCCとGNDにブレッドボード用のジャンパー線をハンダ付けする。
ピンを抜く時は先に樹脂部分をニッパー等で切り外し、表側からコテ先を当てて裏からラジオペンチで一本ずつ引き抜くと簡単。基板は万力等で固定しておく。

あとは抜き取った穴にジャンパー線を差し込んでハンダ付けすれば良い。電源は+3.3Vと+5Vの両方が出ているので、必要な分だけハンダ付けする。
リード部分を切断して被覆を剥いてからハンダ付けしたほうが見た目は綺麗になると思うが、面倒なのでそのままハンダ付けした。

R0012687

出来上がったものを実際に使うとこんな感じ。これで利用できるブレッドボードの種類が増える。

R0012686

virtualenv

Raspberry Piはワンボードマイコンであると同時にLinuxマシンでもあるので、色々な開発言語を使用する事ができるが、PiはPythonから来ている事からも分かるように開発元はPython言語を推奨している。

現在のPython言語の最新バージョンは3.xだが、バージョン2.xが広く使われていたのと、3.xと2.xの互換性の問題から現状では両方のバージョンが併用されていて、Raspberry Pi(Raspbian)にも両方のバージョンがインストールされている。

Raspberry Piのコンソールで単にPythonを起動すると

Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.

このようにPython2.7が起動する。Python3.xを使うためには「python3」で起動すれば良い。

Python 3.2.3 (default, Mar  1 2013, 11:53:50)
[GCC 4.6.3] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.

ここから分かる通り現状ではまだPython2.xがメインで、Raspberry PiにおけるPython3.xはテスト的な扱いになっている。Python3.xがいずれ主流になるのだとは思うが、当分の間は両方のバージョンが混在する状態になってしまうのは避けられず、どちらかのバージョンでしか動作しないモジュールもあるので色々と問題が出る可能性がある。

そのために特定バージョンのPython実行環境を仮想的に提供するツール「virtualenv」が存在する。これを使用すると大元の環境とは分離した仮想環境でPythonを実行する事ができるので、その環境でプログラムを動作させたり、モジュールをインストールして試すことができる。

virtualenvによって構築された仮想環境は言ってみれば「箱庭」的なもので、他には影響を与えないので自由に色々と試すことができるというメリットがある。

インストールは以下のように行う。

$ sudo apt-get install python-pip
$ sudo apt-get install python-virtualenv

ネット上でvirtualenvの解説を読むと、virtualenvwrapperも一緒にインストールして使用する例が多いのだが、virtualenv単体で使用するのはそれほど難しくないし、なによりもイメージが掴みやすいので最初は単体で使用してみる事をお勧めする。

インストールが完了したら、以下のコマンドで仮想環境を作成する

$ virtualenv -p python3 env32

これは「env32」というフォルダを作成して、そこにpython3の環境を作成するという意味になる。virtualenvの古いバージョンでは実行時に「–no-site-packages」オプションを指定しないと、インストール済みモジュールもコピーされてクリーンな環境にはならなかったのだが、現在のバージョンでは何も指定しない場合はインストール済みモジュールをコピーしないようになった。

逆にインストール済みモジュールを引き継ぎたい場合には「–system-site-packages」を指定する必要がある。ネット上の解説ではこのあたりが古いままになっている所もあるので、注意が必要。

仮想環境の構築にはちょっと時間がかかるので、途中で止まってしまっても焦らずに待つこと。

構築が終わったら指定したフォルダができているはずなので、そこに移動して以下のコマンドを実行する。

$ source bin/activate

これでpythonの実行環境はそのフォルダの中にコピーされたものが使用されるようになる。試しにpythonとだけ入力して実行してみると

Python 3.2.3 (default, Mar  1 2013, 11:53:50)
[GCC 4.6.3] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.

先ほどまでとは違ってPython3.xが起動するのが分かると思う。この状態でモジュールのインストール等を行うと、それはこの仮想環境フォルダの中だけに反映される。つまり、必要が無くなったらフォルダごと削除してしまえば、他に全く影響を与えずに消すことができる。

仮想環境を終了する場合は

$ deactivate

を実行すれば良い。仮想環境下ではプロンプトの頭に仮想環境の名前(フォルダ名)が表示されているが、deactivateすると元に戻るのが分かるはずだ。この環境はストレージ容量が許す限りは何個でも作成できるので、バージョンの違うモジュールで動作を試すような場合には役立つだろう。

Raspberry Piでroot権限なしでGPIOやi2cが使用できる「Quick2Wire」ライブラリは、Python3のみに対応で公式なドキュメントでもvirtualenvの使用が推奨されている。そちらのインストールや使用方法についてはまた次回に。