観測機器
Raspberry PI とは

 

 RaspberryPiとは      
 RaspberryPiを動かす      
 RaspberryPiによるGM-10  (USB   Python) 
 RaspberryPiによりホコリセンサーを動かす  (GPIO   C言語 )


いままで当研究所の計測系はいろいろな既製品のつみかさねで、結果として何でもかんでも1台のPCに処理をさせていました。すこし、分散処理をめざし負荷分散の方向で動くこととしました。米国のフォーラムではArduinoというマイコンを使用している例が多いですが、UNIXの勉強を兼ね、Raspberry Pi という手のひらサイズのコンピュータを使ってみました。とりあえず完成したのは、ガイガーカウンタGM-10用のインターフェーサ、とホコリセンサです。引き続き、トライしていきたいと思っています。(2014/07/0修正)

Raspberry Pi
 Raspberry Pi(ラズベリーパイ)は、ラズベリーパイ財団によって英国で開発されたARMプロセッサを搭載したシングルボードコンピュータで、小さいながらスマホに使われている最新のハードで、最近とみに人気のようです。写真の「GPIO HEADERS」にGPIO(General Purpose Input Output )汎用入出力の26ピンの端子があり、さまざまなスイッチ、センサをつなぐことができ、電子工作には大変便利です。上記のセンサをつなぎこみ、必要なプログラムを組み込むこととなります。一部の記事では名刺サイズと書かれていますが、コネクタやSDカードの出っ張りがあり、手のひらサイズというほうが適切です。

Raspberry PIを動かす

 小さいながら独立したコンピュータですから、落とし穴がたくさんあり、覚悟が必要です。Raspberry Piについてはさまざまな情報があふれていますが、一通りここに概略をメモしておきます。
用意するもの
Raspberry Pi本体 モデルB  RSオンライン 3940円
SDカード8GB 手持ち
5V 1A 電源 
LANケーブル USBケーブル 手持ち
VGA ディスプレイ 手持ち
HDMI to VGA adapter Amazon 980円
マウス 手持ち
キーボード 手持ち
Raspberry Pi用T型I/O延長基板 スイッチサイエンス (ブレッドボードでの実験バラック作成)

SDカードにLinuxのインストール
RaspberryPiにはハードディスクはありません。SDにインストールします。
Raspberry Piをはじめようのとおり、標準のRaspbian(Rspberry Pi用のDebian Linux)をインストールします。 
(1) SD AssociationのSDカードフォーマットツールによりSDカードのフォーマット
オプション設定をクリックし「論理サイズ調整」をONにして「OK」をクリック
(2) OSのインストーラNOOBSをダウンロードし展開
(3) フォルダの中に入っているimages、slidesといったフォルダとその他のファイルのみをSDカードにコピー
(4) Raspberry Pi本体にSDカードを挿入。USBマウスやキーボード、ディスプレイのケーブルをさして、電源ケーブルを差し込む

ここでディスプレイにログインメッセージが出るはずですが、私の場合ディスプレイとディスプレイアダプタの相性が悪いせいか、何も表示されず、これでは何も始められません。一時的に居間のデジタルテレビのHDMI端子に接続し、/boot/config.txtファイルを下記のとおり修正。
hdmi_force_hotplug=1
hdmi_group=3
hdmi_mode=9
hdmi_drive=2


(5) OSを選択しRaspbianをインストール
(6) RaspberryPi Software Configuration Tool による 初期設定

これで動くはず。しばらくいろいろUNIXのコマンドを試してみて、感じをつかみます。

(7) Widowsとファイル共用のためsambaをインストールします。
これにより、WindowsのエディタでRaspberry Piのファイルを編集したり、Windows側のGNPLOTなどアプリケーションで直接出力データを参照したり出来るようになります。
(8) この際、Raspberry PiのIPアドレスを
/etc/network/interfaces
を編集し、固定にしておいたほうがよい。また、ホスト名を
/etc/hostname および/etc/hosts
を編集し変更しておきます。あとでもできますが、Windows側の記述に影響してきますので、決定しておきます。
(9) これも後からでもよろしいですが、電源をいれたらすぐに自動ログインし、センサ用のプログラムが自動起動するように設定するとたいへん便利です。それには次のようにします。
/etc/inittab
を編集する。
$sudo nano /etc/inittab
73行目あたり
1:2345:respawn:/sbin/getty 38400 tty1

をコメントアウト。代わりに
1:2345:respawn:/bin/login -f ユーザ名 tty1 </dev/tty1>/dev/tty1 2>&1
を書き込む。ユ−ザ名は pi など。

/home/pi/.profile
のさいごに自動起動したいプログラムをコマンド指定する。たとえば、下記の「GM-10読み取りプログラム 」の場合は
$nano /home/pi/.profile
sudo python ./GM-10reading.py
を書いておく。
(10) SDカードのバックアップをとっておきます。Win32DiskImager.exeをつかいます。使い方はこちら

Windows本体側の設定
 Raspberry PiはUSBコネクタにキーボードを接続して運用しますが、今回はセンサとともに、手の届かないところに設置しますから、Windowsホスト本体からLAN経由で遠隔操作できるようにします。そのためWindows上で動作するSSHクライアントとして、PuTTYと言うソフトを使用します。これによりWindows親機からリモートログインができます。日本語インストールはこちら
長時間つなぎっぱなしにしたいのですが、操作をしないと、切断されてしまいます。そのため[接続] カテゴリーの 「セッションをアクティブに保つための null パケットの送信」で、null パケットを自動送信する時間間隔 (単位: 秒) を設定180秒程度にします。デフォルトは 0 (null パケットは送信しない) です。


RaspberryPiによるGM-10
 先日(2014年5月末)突然PCとガイガーカウンタGM-10の接続がうまくいかなくなりました。PCを再起動しても、GM-10を認識しません。そこで、手元に手のひらサイズのLinuxコンピュータ(RaspberryPi)を用い、下図のようにPCとGM-10のあいだに、RaspberryPiをいれGM-10からのデータを読み取り、CSV形式のファイルをつくり、それをPCからアクセスすることとしました。これは何でもかんでもPCに処理をさせている現状から、少しでも負荷分散をしたいとの思いからです。

GM-10とRaspberryPiとの接続
GM-10とRaspberryPiとの接続はメーカのBlack Cat Systems のサイトにが載っています。RaspberryPiのUSBポートに接続してプログラムはPythonで書かれています。それを参考に構成しました。
いままでは9ピンシリアルのコネクタでPCに接続していましたので、USBとシリアルのコンバータが必要です。以前別の目的で購入したIOデータ社のUSB-RSAQ2というのが手元にありましたので、それを流用しました。生産終了品でWindows7では使えませんでしたが、今回復活しました。もちろん後継機種でもOKだと思います。
製品写真USB-RSAQ2

RaspberryPi側の準備については次の通りです。
(1) RaspberryPiを動くようにする。こちら
(2) 多くのUSBシリアルコンバータで使用されているICは、Linuxでは標準で導入されているため、USBポートに挿せば認識します。
コンソールで
$ lsusb
とコマンドを入力すると、
Bus 001 Device 004: ID 067b:04bb Prolific Technology, Inc. PL2303 Serial (IODATA USB-RSAQ2)
のようなメッセージが出て、認識されているのがわかります。

また、/devディレクトリのなかに、ttyUSB0 があるのを確認します。このデバイス名は、後ほどプログラムに必要です。

(3) つぎにPythonでシリアルインターフェースが使えるようにシリアルポート操作ライブラリをインストールします。
$ sudo apt-get install python-serial

Pythonプログラムの作成
Black Cat Systems のGM-10/GM-45のインターフェースのページには、のような記述があります。
「ガイガー管が粒子を検知するごとに、パルスはシリアルラインを通ってバイトとしてコンピューター送られます。したがって、1分間に受け取られたバイトの数を数えれば、CPM値を得ることが出来ます。送られるバイトの値はどうでもよく、単にバイト数を数えます。」
また、シリアルポートについて次のようにセットせよとの記述があります。
「38400b/s 8ビット 、ノーパリティ、 ハンドシェークなし」
さてお手本のBlack Cat Systems のPythonプログラムを見てみましょう。たしかに次のような記述があります。

 Black Cat Systemsの Pythonプログラムの要所を抜き書き
  
import serial
# 途中省略

# 始めにシリアルポートを開く。デバイス名は環境に合わせて変更のこと
port = serial.Serial("/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A4008VgR-if00-port0", baudrate=38400,timeout=0.0,dsrdtr=True)
print port #うまくopenできればデバイス名が表示される def get_counts():
#途中省略
#read some bytes from the serial port #シリアルポートからバイトを読み込む recbytes=port.read(100)
#number of bytes is the number of detection events #バイト長が検出されたイベントの数をあらわす newCounts=len(recbytes) #以下省略


試験プログラム
上を参考に、試しに次のような試験プログラムを作ります。 なおPythonの serial ライブラリの使い方はこちらにあります。

 試験プログラム serialtest.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
     
import serial


con=serial.Serial('/dev/ttyUSB0', baudrate=38400, timeout=0.1,dsrdtr=True)
print con.portstr
while 1:
	str=con.read(100)
	newCounts=len(str)
	print newCounts
注 左のインデント余白はTabコード

RaspberryPiのUSBポートにUSBアダプタ、GM-10をつなぎ込み、この試験プログラム(ファイル名はserialtest.py)を実行してみます。
$ sudo python ./serialtest.py

すると、デバイス名 /dev/ttyUSB0 が表示された後、たくさんの’0’と、時々’1’が出力されるでしょう。(無限ループですから停止するにはCtrl+C。)この’1’はガイガーミューラ管に放電(event)があったことを示しており、この数を1分間数えると、CPM値となります。

PythonによるGM-10読み取りプログラム
基本的なことは上記の通りですが、1分ごとに繰り返しファイル書き込みをする必要があります。そのためにPythonのthreading処理により、マルチプロセス処理を行うこととしました。threadingとは複数のプロセス(thread)を同時に実行して並列に処理を進めることで、美しいプログラムが書けそうなので、挑戦してみました。すなわち、シリアルポートを監視し変化をよみとるThreadを常時まわしておき、一方メインプログラムでは1分に1度、ファイルに出力するよう構成することとします。

以下、GM-10読み取りプログラム GM-10reading.pyを説明します。
(1)  threading モジュールをimport
(2) GPIOはLEDのために使います。GPIO17にLEDを配線しているものとします。
(3) 上の実験のとおりGM-10をつなぎ込みます。取りこぼしのないよう timeout=0.0 としています。
(4) onCounts この変数でThreadの間で値をもちまわる
(5) readGM10()というなまえのThreadを定義、常にシリアルポートを見に行き、読み取ったバイト数を数えています。
(6) メインプログラムではreadGM10を生成し、デーモンスレッドとして起動します。
(7)  1分ごとに、readGMがカウントアップした値 onCounts を読み取り、そして 0 に戻しています。
(8) geigerディレクトリのなかのファイル名cpm.txt として、その値を時刻と共にファイル出力します。CSV形式で たとえば
2014/06/01 00:48:21 , 14
のようなレコードが1分ごとに出力されます。これはオリジナルのRaSoftが出力するファイルと同じ形式です。ほかのコンピュータ(メインのPC)が、随時読み出しますので、毎回openし、追記し、closeしています。

起動は
$ sudo python ./GM-10reading.py

 GM-10読み取りプログラム GM-10reading.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c)H.Ishikawa 2014/06/20

import serial
import threading #(1)
import time
import datetime
import csv
import RPi.GPIO as GPIO #(2)


#GPIO LED用(2)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) 
GPIO17 = 17
GPIO.setup(GPIO17,GPIO.OUT)

# (3)USB-Serialを使用する場合、ttyUSB0
con=serial.Serial('/dev/ttyUSB0', baudrate=38400, timeout=0.0,dsrdtr=True)
print ('measurement start ' + datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S.%f") + ' ' +con.portstr)


onCounts = 0 #(4)この変数でThreadの間で値をもちまわる

def readGM10(): #(5)
	global onCounts
	onCounts = 0
	LEDCounts = 0
	GPIO.output(GPIO17,GPIO.LOW)
	while True:
		str=con.read(100)
		newCounts=len(str) # 
		onCounts = onCounts + newCounts
		LEDCounts = LEDCounts + 1
		if newCounts != 0: #(2) eventがあれば、LEDつける
			GPIO.output(GPIO17,GPIO.HIGH)
			LEDCounts = 0
		if LEDCounts >= 100: #(2) 適当な時間でLED消す
			GPIO.output(GPIO17,GPIO.LOW)
			LEDCounts = 0
	


if __name__ == '__main__': #(6)
	t=threading.Thread(target=readGM10)
	t.setDaemon(True)
	t.start()
	while True:
		time.sleep(59.94)# (7) 1分 値はカットアンドトライ
		cpm = onCounts
		onCounts = 0
		print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S.%f") , cpm

		outputfile = open('geiger/cpm.txt' , "a" ) #(8) ファイル出力
		writer = csv.writer(outputfile)
		now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
		buffer = [now, cpm]
		writer.writerow(buffer)
		outputfile.close()


ガイガーカウンタGM-10用のインターフェーサ完成版
正規のRS232Cは古い規格で信号は±5〜15 V振幅とされており、またGM-10の規格をみると、9〜12Vで使うようにとされています。USBシリアル変換器では、このような電圧は出ていません。RaspberryPiに5Vの通常のACアダプタからの電源を加え、実測してみると4Vも出ていません。すくなくも5Vはほしいところで、実験してみるとガーガーミューラ管に充分な電圧が加わっていないようで、CPM値が低くなってしまいました。そのため、専用の独立DC電源を用意し、USB出力端で5Vとなるようにしました。基板タイプのスイッチング電源の5V・2A・イータ電機BNS05SA-U1で、出力10%可変です。
左側が電源 ケースはタカチ電機TW13-5-13
古い基板を流用しているためよけいなICソケットがついている。
左からインターフェーサ、USB-RSAQ2USBシリアル変換器、GM-10ガイガーカウンタ


ホストのWindowsPCでの処理は、5分に一度、GNUPLOTがRaspberryPiのファイルを読み取り、描画し、アップロードしています。この結果はこちらです。


PM2.5 花粉観測のためのセンサ 作成
PM2.5や花粉観測のためのほこりセンサは特殊なインターフェースですので、このままではPCにつながりません。RaspberryPiで一時処理を行い標準的なファイルにしてPCに渡すこととします。 使われているセンサーは、下記の通りです。

型番 :SEN12291P
販売サイト:Seeed Technology Inc. 日本サイト:FabxFab
メーカ: 神栄テクノロジー株式会社
メーカ型番: PPD 42NJ
規格表:こちら

 このセンサーを分解し内部を解析した方がおられます(いわゆるリバースエンジニアリング)。その資料が公開されていましたので、一部使わせていただきます。
下の白い抵抗はヒータ ここで空気が暖められ、上昇する
左側は発光ダイオード、この光が空気中のホコリで反射し、右の受信ダイオードで検出される
発光ダイオードの光は、実際は見えないが、赤色ダイオードに取り替えて実験したところ。レンズで集光され、ここを通過する空気を観測する

検出された微粒子の大きさに応じた、パルスが出力されます。PWM(パルス幅変調)という方式で、これを30秒間以上LOレベルのしめる時間比(デューティサイクル)を求めます。それを下のグラフに従って、単位体積あたりの微粒子の個数に変換します。 (規格表による)



ここで、このグラフを数式に表した方がおられ、それによると、次の通りです。


 この式で x はデューティサイクルを%であらわしたもの、 y は0.01立方フィートあたりの粒子の個数ですので、分かりやすい単位に換算が必要です。

 このセンサーの入出力コネクタは5端子でその配置は次の通りです。すなわち出力はP1(端子4)とP2(端子2)の2系統あり、小さな微粒子と大きな微粒子の2種類を計測できます。その際P1は1ミクロン以上で固定ですが、P2はT1(端子5)に抵抗をつなぐことにより、計測の粒子サイズを変更することが出来ます。デフォルトは「2.5ミクロン以上」です。
1 : COMMON(GND)
2 : OUTPUT(P2)
3 : INPUT(5VDC 90mA)
4 : OUTPUT(P1)
5 : INPUT(T1)・・・FOR THRESHOLD FOR [P2]

端子の物理規格:JST EHシリーズ EHR-5
ハードの作成
必要な部品(RaspberryPi本体をのぞく)
ホコリセンサー 上述
SDカード8GB 手持ち
12V40mm角 DCファン 秋月電子 150円 これを5Vでゆっくり回す
5V 2A 電源 旧パソコンから取り外したもの
ケース 旧モデムのケース再利用
LANケーブル USBケーブル 手持ち
抵抗 2.4K 3.9K X2
ユニバーサル基板 サンハヤト
26Pピンソケット 秋月電子 50円
接続用JSTコネクタ マルツパーツ館


 GPIOにホコリセンサーをつなぎ込みます。GPIO 番号の呼び方はいろいろな経緯で複数あるようです。ここではBCM Rev2の規格で記述していきます。

 http://wiringpi.com/wp-content/uploads/2013/03/gpio1.png

 ホコリセンサの必要な電源は5Vプラスマイナス10%で、この範囲の電源を用意しなければ精度は保証されません。Raspberry PiのGPIO HEADERには5Vの電源が取り出せるピンがありますが、実測するとこの範囲に収まりません。またRaspberry Piはあたらしいデバイスを使っているため、基本入出力電圧が3.3Vで、上記ホコリセンサーのPWMパルスを直接接続はできず、電圧を3/5に変換する必要があります。そのため抵抗で分圧します。下のような簡単な接続基板を作成しました。これをRaspberryPiのGPIO HEADERに直接マウントし、ほかの基板、FANなどとコネクタ接続します。、

部品面から見ているので、上の回路図とは反転 PaspberryPiのGPIO HEADERにマウントしたところ


適当なケースに格納 右下は電源
空気の流れを考慮し小さいファンを使用
ファンの下の小さな四角い窓はホコリセンサーの
空気取り入れ口
軒下に設置 ルータを経由してWindowsマシンに接続
隣は1Wire温度センサ




Raspberry Piのほこりセンサソフトの作成

 Raspberry Piで動くセンサ用のソフトを作ります。Raspberry Piはもともと教育用のため、Pythonという、あたらしい汎用のスクリプト言語が基本となっています。ホコリセンサーは、幅が10msから90msのパルスの幅を精度良く読み取らなければなりません。そのためにGPIOをHIかLOかをくりかえし読みに行く必要があります。このような仕事はリアルタイムのマイコンが得意で、本来UNIXのような多重プログラミングの機械は不得意です。それをあえてやろうというわけですから、コンパイルした実行形式のプログラムですこしでも、高速に読み取りたいのです。そのためC言語で記述します。Linuxマシンですから、当然C言語がつかえます。GPIOを読みに行くプログラムをPythonとCで記述し速度を比較すると、70倍の差がありました。
 裏側で動くソフトは極力減らし、余計なことはWindowsの親機にまかせ、簡潔なソフトにします。読み取り頻度は0.1m秒としました。

GPIOのwiringPiライブラリをインストール
GPIOをC言語から使えるようにするライブラリWieringPiインストールする

バージョン管理システムGitのインストール
$ sudo apt-get install git-core

WiringPiのソースファイルをダウンロード
$ git clone git://git.drogon.net/wiringPi

プログラムのコンパイル
$ cd wiringPi
$ ./build


インストールされたバージョンを確認します。
$ gpio -v

Raspberry Piで動かす、ホコリセンサーのよみとりプログラム
(1)  GPIOのwiringPiライブラリをinclude
(2)  よくつかうGPIO番号をdefineしておく
(3) wiringPiをBCM規格でイニシャライズ(重要) GPIOヘッダのPin11とPin15がBCM規格の番号で読めるようになる
(4) GPIO17とGPIO22を読み取りモードにセット
(5) 無限ループ
(6) GPIO17とGPIO22を読む
(7) パルスがLOレベルの場合カウンタを1あげる
(8) これを0.1msごとに繰り返し約1分続ける
(9) 1分ごとに、ファイルにデューティー比を出力する。dustsensorディレクトリの中にdustsensor.txtというCSV形式のファイルができる。
時刻,小さい粒子,大きい粒子
たとえば
2014/05/18 11:18:03,0.005348,0.000245

 ホコリセンサー  dustsensor.c
/* ホコリセンサー
* 2014/05/08 (C) H.Ishikawa
*/
#include <wiringPi.h> //(1)
#include <time.h>
#include <stdio.h>

#define GPIO17 17 //1micro small_particle //(2)
#define GPIO22 22 //2.5micro large_particle //(2)

int main (void)
{
    time_t timer;
    struct tm *date;
    char date_time[256];
	FILE *fp;
	char *fname = "dustsensor/dustsensor.txt";
	   	
	if (wiringPiSetupGpio() == -1) return 1 ;//BCM GPIO pin numbers  //(3)
	pinMode(GPIO17, INPUT) ; //(4)
	pinMode(GPIO22, INPUT) ; //(4)
	
	long count_small_particle,count_large_particle,total;
	int small_particle,large_particle;
	float lowpulse_small_particle = 0.0;
	float lowpulse_large_particle = 0.0;
	timer = time(NULL);          
	strftime(date_time, 255, "%Y/%m/%d %H:%M:%S", localtime(&timer));   
	
	printf("measurement start %s\n",date_time);
	while (1){//(5)
		count_small_particle = 0;
		count_large_particle = 0;
		total = 0;
		fp = fopen( fname, "a" ); //追記形
		while (total < 331000) {  //(8)
			total = total + 1;
			small_particle = digitalRead (GPIO17); //(6)
			if (small_particle == 0){   //(7)
				count_small_particle = count_small_particle + 1;
			}
			large_particle = digitalRead (GPIO22); //(6)
			if (large_particle == 0){   //(7)
				count_large_particle = count_large_particle + 1;
			}
			delayMicroseconds(100);//(8) 0.1ms
		}
		

		timer = time(NULL);          
		strftime(date_time, 255, "%Y/%m/%d %H:%M:%S", localtime(&timer)); 
		lowpulse_small_particle = (float)count_small_particle / (float)total;
		lowpulse_large_particle = (float)count_large_particle / (float)total;
		fprintf( fp, "%s,%f,%f \n", date_time,lowpulse_small_particle,lowpulse_large_particle); //(9)
		printf("%s,%f,%f \n",date_time,lowpulse_small_particle,lowpulse_large_particle);
		fclose( fp );
	}
	return 0;
}

このプログラムを、Raspberry Pi上にdustsensor.cというなまえで保存し、コンパイルします。たとえば
$ gcc dustsensor.c -o dustsensor.exe -lwiringPi

実行は
$ sudo ./dustsensor.exe

dustsensorディレクトリの中にdustsensor.txtというCSV形式のファイルができる。
[時刻,小さい粒子,大きい粒子]の形式
たとえば
2014/05/18 11:18:03,0.005348,0.000245
1分ごとに書き込まれる。

Windows本体側のほこりセンサ用プログラム

Windows本体側では、次のような処理をおこなっています。
(1) 1時間に一度、Raspberry PiのCSV形式ファイルを読み、上に述べた変換式により、単位体積あたりの粒子数に変換する
(2) 10分間の移動平均を求める
(3) GNUPLOTでグラフを描画する
(4) FTPでホームページにアップロードする
ここらは一般的な方法ですので、詳細は省略します。