RaspberryPi
RaspberryPiによるGM-10インターフェース
 先日(2014年5月末)突然PCとガイガーカウンタGM-10の接続がうまくいかなくなりました。PCを再起動しても、GM-10を認識しません。そこで、RaspberryPiを用い、下図のようにPCとGM-10のあいだに、RaspberryPiをいれGM-10からのデータを読み取り、CSV形式のデータログファイルをつくり、それをPCからアクセスすることとしました。これはPCにたとえ不具合がおこっても、独立にデータログだけはRaspberryPiでとり続けることができるようにとの思いからです。

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のファイルを読み取り、描画し、アップロードしています。この結果はこちらです。