教育用GM管開発を振り返って(11)
www.radi-edu.jp
apgmman.hatenablog.com
放射線教育支援サイト「らでぃ」の実験集に掲載した「Pythonで計数経時変化の実験」のPythonプログラムについて解説する。Pythonやライブラリーのインストール方法や注意点、Pythonの文法の特徴などは「教育用GM管開発を振り返って(9)」に記載した。
「Pythonで計数経時変化の実験」のプログラム例
1秒間の計数を繰り返し、経過秒数と1秒率を画面に表示するとともに、csvファイルに出力するプログラムで、ラドン220の半減期の測定や、統計的変動の実験に使用できる。
まず、必要なライブラリーをインポートする。このうち、numpyはPythonのインストールで同時にインストールされるので、ライブラリーとして別途インストールする必要はない。#以下はコメント文である。
import pyaudio #マイク入出力処理 import numpy as np import matplotlib.pyplot as plt #グラフ処理 import cv2 #カメラ画像処理
次に、グローバル変数を宣言し、初期値を決める。閾値の変数thresholdは、パルス波高を予めモニターして数値を決め、キーボードから入力する。
global m, threshold #グローバル変数 m = 1 #経過時間 threshold = input('Threshold?') #閾値を設定
出力ファイルcps_data.csvを開き、ヘッダーを書き込んでおく。出力ファイルはExcelなどの処理ソフトを利用することを念頭にcsvファイルとした。
with open('cps_data.csv', mode='w') as fc: #計数値を書き込むファイルを新規モードで開く fc.write('Time(sec)' + ',' + 'CPS' + '\n') #タイトル cps_data = [] #計数値の空リストを用意
次に一連の音声入力をストリーミングとしてデータ化し、計数からグラフ描画に至るまでを関数化する。CHUNKは入力単位でここでは、1024個ごとにサンプリングする。サンプリング周波数は変えられるが、デフォルトのままにした。録音時間は1秒である。
def streamandcount(): #入力からグラフ描画まで処理 CHUNK = 1024 #入出力の長さ FORMAT = pyaudio.paInt16 #2Byte整数 CHANNELS = 2 #ステレオ RATE = 44100 #サンプリング周波数(Hz) RECORD_SECONDS = 1 #録音時間(秒)
ストリーミングをオープンし、CHUNKごとのデータdata-rawをframesというlistに追記していく。
p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, #入力のみ frames_per_buffer = CHUNK) frames = [] #空のlistを用意
1秒分のデータを加算して、framesに追記していく。
for i in range(int(RATE * RECORD_SECONDS // CHUNK)): #CHUNK単位で切り捨て data_raw = stream.read(CHUNK) frames.append(data_raw) #43回分を加算 frames_int16 = np.array(frames)
ここでストリームを閉じる。
stream.stop_stream() #ストリームを閉じる
stream.close()
p.terminate()
以下は、計数と計数率の画面とファイルへの出力のための演算で、まず、2進数を10進数に変換し、データは片チャンネルだけでよいので、ステレオのLチャンネルのデータだけを抽出する。
pulse = 0 #計数を初期化 data_l = data[::2] #ステレオのLチャンネルを取り出す onflag = False #閾値超過フラッグを初期化 ||< データが閾値を超えるとフラッグを立て、閾値を下回るとカウント1を加算し、フラッグを降ろす。閾値を超えたところから下回ったところまでを1カウントとするので、複数パルスでも重複カウントすることはない。 >|python| for k in range(len(data_l)): #data_l全体が範囲 dat = data_l[int(k)] #data_lのk番目の値 if int(dat) > int(threshold) and not onflag: #閾値を初超過 pulse = pulse + 1 #1カウントを加算 onflag = True #閾値超過フラッグを立てる if int(dat) <= int(threshold): #閾値以下になったら onflag = False #閾値超過フラッグを降ろす
計数率をCPSで画面に表示する。
cps = pulse #CPSに換算 print('CPS = ' + str(int(cps))) #計数値を画面に出力
同時に計数率をファイルに出力する。フォーマットは、経過秒数、1秒率となっている。 cps_data.append(cps) #計数値のlistに追加
with open('cps_data.csv', mode='a') as fc: #ファイルを開く fc.write(str(m) + ',' + str(cps) + '\n') #経過と計数値を追記
さらに、入力信号の一部の44msec分をパルス波形のモニターとして上段のグラフに表示し、下段には経過時間と1秒率をグラフに表示して計数のトレンドが分かるようにした。
fig = plt.figure(num = 1, figsize = (6, 7)) #グラフを定義 plt.subplot(211) #グラフの上半分を指定 plt.plot(data_l[200:1200]) #入力信号の一部44msec分を表示 plt.ylim(-250, 1000) #y軸の範囲 plt.xlabel('t (msec/44)') #x軸のラベル plt.ylabel('PulseHeight') #y軸のラベル plt.subplot(212) #グラフの下半分を指定 plt.plot(cps_data) #計数値を表示 plt.xlim(0, 600) #x軸の範囲 plt.ylim(0, 1000) #y軸の範囲 plt.xlabel('t (sec)') #x軸のラベル plt.ylabel('CPS') #y軸のラベル plt.pause(0.3) #0.3秒間だけ描画 plt.clf() #グラフを閉じる
キーボードからqを入力するまで、計数を反復する。プログラムの停止には、キーボードからqを入力する。
while True: #キー入力を待つ streamandcount() #処理を反復 m = m + 1 #経過時間1秒を加算 if cv2.waitKey(0) & 0xFF == ord('q'): #qを入力 break #処理を終了
画面に出力したグラフの例を図に示す。
上のグラフの上段はモニター用のパルス波形で、下段は計数率の経時変化、すなわち経過秒数に対する1秒率の関係を描画している。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)
教育用GM管開発を振り返って(10)
放射線教育支援サイト「らでぃ」の実験集に掲載した「Pythonで反復計数の実験」のPythonプログラムについて解説する。Pythonやライブラリーのインストール方法や注意点、Pythonの文法の特徴などは「教育用GM管開発を振り返って(9)」に記載した。
「Pythonで反復計数の実験」のプログラム例
10秒間の計数を、キーqの入力で停止するまで繰り返し、計数率を画面表示するとともに、csvファイルに出力する計数の基本プログラムについて解説する。
まず、必要なライブラリーをインポートする。このうち、numpyはPythonのインストールで同時にインストールされるので、ライブラリーとして別途インストールする必要はない。#以下はコメント文である。
import pyaudio #マイク入出力処理 import numpy as np import matplotlib.pyplot as plt #グラフ処理 import cv2 #カメラ画像処理
次に、グローバル変数を宣言し、初期値を決める。閾値の変数thresholdは、パルス波高を予めモニターして数値を決め、キーボードから入力する。
global m, threshold #回数と閾値の変数をグローバルと宣言 m = 1 #測定回数 threshold = input('Threshold?') #閾値を入力
出力ファイルcpm_data.csvを開き、ヘッダーを書き込んでおく。出力ファイルはExcelなどの処理ソフトを利用することを念頭にcsvファイルとした。
with open('cpm_data.csv', mode='w') as fc: #出力ファイルを新規モードで開く fc.write('Time(sec)' + ',' + 'CPM' + '\n') #ヘッダーを書き込む
次に一連の音声入力をストリーミングとしてデータ化し、計数に至るまでを関数化する。CHUNKは入力単位でここでは、1024個ごとにサンプリングする。サンプリング周波数は変えられるが、デフォルトのままにした。録音時間は10秒である。
def streamandcount(): #マイク入力から計数までの処理 #stream CHUNK = 1024 #入出力の長さ FORMAT = pyaudio.paInt16 #2Byte整数 CHANNELS = 2 #ステレオ RATE = 44100 #サンプリング周波数(Hz) RECORD_SECONDS = 10 #録音時間(秒)
ストリーミングをオープンし、CHUNKごとのデータdata-rawをframesというlistに追記していく。
p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, #入力のみ frames_per_buffer=CHUNK) #ストリームを開く frames = [] #空のlistを用意
10秒分のデーターを加算して、framesに追記していく。
for i in range(int(RATE * RECORD_SECONDS // CHUNK)): #CHUNK単位で切り捨て data_raw = stream.read(CHUNK) #CHUNK単位で音声信号をサンプリング frames.append(data_raw) #430回分を加算 frames_int16 = np.array(frames) #listをnumpyアレイに変換
ここでストリームを閉じる。
stream.stop_stream() #ストリームを閉じる
stream.close()
p.terminate()
以下は、計数と計数率の画面とファイルへの出力のための演算で、まず、2進数を10進数に変換し、データは片チャンネルだけでよいので、ステレオのLチャンネルのデータだけを抽出する。
#count pulse = 0 #計数を初期化 data = np.frombuffer(frames_int16, dtype='int16') #バイトデータを整数に変換 data_l = data[::2] #ステレオのLチェンネルを取り出す onflag = False #閾値超過フラッグの初期値
データが閾値を超えるとフラッグを立て、閾値を下回るとカウント1を加算し、フラッグを降ろす。閾値を超えたところから下回ったところまでを1カウントとするので、複数パルスでも重複カウントすることはない。
for k in range(len(data_l)): #data_l全体が範囲 dat = data_l[int(k)] #data_lのk番目の値 if int(dat) > int(threshold) and not onflag: #閾値を超えたら pulse = pulse + 1 #1カウントを加算 onflag = True #閾値超過フラッグを立てる if int(dat) <= int(threshold): #閾値以下になったら onflag = False #閾値超過フラッグを降ろす
計数率はCPMで表示することとしたので、10秒のカウント数を6倍して画面に出力する。
cpm = pulse / RECORD_SECONDS * 60 #CPMに換算 print('CPM = ' + str(int(cpm))) #CPMを画面に出力
同時に計数率をファイルに出力する。フォーマットは、回数、計数率となっている。
with open('cpm_data.csv', mode='a') as fc: #出力ファイルを追記モードで開く fc.write(str(10 * m) + ',' + str(cpm) + '\n')
キーボードからqを入力するまで、計数を反復する。プログラムの停止には、キーボードからqを入力する。
while True: #キー入力まで反復する if cv2.waitKey(1) & 0xFF == ord('q'): #qを入力すると break #プログラムが終了 streamandcount() #処理を繰り返す m = m + 1 #回数のカウントを1増やす
Pythonの実行は、Windows Power ShellまたはCMDを開いて、ファイル名を入力することで行う。そうすれば、終了時にも計数率は画面上に残っているので、結果を確認することができる。Pythonファイルをダブルクリックして実行した場合は、画面上に残らないので結果は出力ファイルで確認することになる。学校の授業で、距離の実験や遮へいの実験を行う場合は、条件を変えて10秒率で6回の測定を繰り返すので、6回測定後に一旦停止して、再度再開できるプログラムの方が適している。しかし、キーボード入力でコントロールする方法に確実性がないために、できていない。うまい方法があれば教えてほしい。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)
教育用GM管開発を振り返って(9)
放射線教育支援サイト「らでぃ」の実験集に掲載した「Pythonでパルス波形を見る実験」のPythonプログラムについて解説する。Pythonについては全くと言っていい専門外なので、間違って理解しているところがあるかもしれないが、一例として挙げたプログラムの実行は確認している。以下の解説は、むしろPythonをこれから始める人に見ていただきたい。
Pythonの実装など
プログラム開発は、Windows10で行った。64bitの Windows10でPythonを実装し、ライブラリーとして、音声などのアナログ信号を扱うPyAudioと、グラフを表示するMatPlotLibなどをインストールした。インストールの際の注意事項、Pythonの使用方法、パソコンなどへの接続方法、Visial Basic 6ユーザーを念頭にした文法の違いを以下に挙げる。
(1) Pythonをインストールするには、https://www.python.jp/install/windows/install.html にアクセスし、記述に従ってインストールする。
具体的には、https://pythonlinks.python.jp/ にアクセスし、PythonのバージョンとパソコンのOSを選んでインストール・パッケージをダウンロード、実行する。その際、
"Add Python 3.x to PATH"にチェックを入れてからインストールをクリックする。
(2) 必要なライブラリーをインストールする。ライブラリーはpipコマンドでインストールできる。
例えば、OpenCVは、Windows画面の左下にある「ここに入力して検索」をクリックし、cmdと入力してコマンドプロンプトを開き、pip install opencv-python と入力する。(https://qiita.com/fiftystorm36/items/1a285b5fbf99f8ac82eb 参照)
PyAudioの場合は、インストールする前にMicrosoft Visual C++ Build Tool をインストールしておく。具体的には、https://visualstudio.microsoft.com/ja/downloads/ を開き、下の方にある「Visual Studio 2019のツール」から、「Build Tools for Visual Studio 2019」をダウンロードする。さらに、パッケージを開いて、「C++ Build Tools」にチェックを入れ、右側のオプションのチェックは全て外して、「インストール」をクリックする。なお、Cドライブに1.67GByte以上の空き容量が必要なので確保しておくこと。
次に、https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio を開き、Pythonのバージョン3.8とWindows 32ビットを選んでwhlファイルをダウンロードする。ファイルはユーザーのホーム・ディレクトリーに移動し、pip install 「ダウンロードしたファイル名(PyAudio-0.2.11-cp38-cp38-win32.whlなど)」を入力する。
また、Matplotlibもインストールしておく。
(3) Pythonファイルは、ユーザーのホーム・ディレクトリーに置き、「Pythonファイル名.py」をダブルクリックして起動し、終了にはグラフの「閉じる」を利用すればキーボード操作を省ける。
(4) GM計数装置のイヤホン端子とパソコンのマイク入力端子またはタブレットの4極入力端子をシールド・ケーブルで接続する。その際、0.022μF~0.1μF程度のコンデンサを並列接続して使用する。次に、「コントロールパネル」から「オーディオデバイスの管理」を開いて、「録音」→当該「マイク」の「プロパティ」で録音の「レベル」が中位になるようスライダーを調節または確認する。このタブレットはタッチパネルの動作が不安定なので、必要に応じてマウスを利用する。
(5) Pythonの学習について
Pythonは、昔のBasicやFortranなどに慣れた人ならなじみやすいコマンドライン入力方式となっている。GUIやタッチパネルに慣れた人には難しいかもしれない。
パソコンのプログラミング未経験者ならば、Python入門編から勉強する必要があるが、コマンドライン入力に慣れた人の場合は、逆に、似ているが違う使い方に注意する必要がある。Pythonコードの書き方の基本は、PEP8 Style Guide for Python Code というドキュメントにある。(https://pep8-ja.readthedocs.io/ja/latest/)
(6) Visual Basic 6との文法の違い
- コードが基本的に変数と制御文でできていることは、ほかの言語と変わらない。ただし、Basicなどではサブルーチン、Visual Basicではプロシージャーといったコードの「くくり」はない。敢えて言えば関数(def)がそれに似ている。
- ライブラリーの機能を使うにはライブラリーをimportすれば、外部関数として使用できる。ただし、ライブラリーの名称または略称(cv2、plt、npなど)を関数の前に付ける必要がある。
- 反復処理をするためのfor文、if文やwhile文などの制御文の末尾には、コロンが必要で、次の行から制御文の範囲の終わりまでは4字の字下げをするだけで、終わりを示すコマンドはない。字下げの字数は同じでないといけない。
- 数字はそのままでは文字として扱われるので、変数aの値を数として使用するにはint(a)のようにして整数化する。逆に数字を文字として出力するにはstr()を使う。
- 関数の内外で同じ変数を使用する場合は、global宣言をするが、変数をdefの前に初期化しておき、global宣言はdef内で行う。予めglobal宣言をするVisual Basicなどとは違うので注意したい。
- 行列にはlist[]とarrey()があって別の機能なので、混在する場合は、お互いに変換する必要がある。
- Visual Basicでのdo文はないので、for文を使う。
- Listの内は、[始めの要素:終わりの要素:インクリメント]となっているが、それぞれ省略が可能で、「始めの要素」を省略すると最初から、「終わりの要素」を省略すると最後まで、「インクリメント」を省略すると、インクリメントは1と解釈される。
- if文やfor文で、「何もしない」コマンドは、passとcontinueがあって、passは「何もしない」、continueは「次のループに進む」の意味になる。ループの外に出るのは、breakを使う。
「Pythonでパルス波形を見る実験」のプログラム例
最初に、計数に必要な検出パルスの最大値やノイズレベルを知り、そもそも検出できているかどうかをモニターするための、パルス波形を見るPythonプログラムを取り上げる。
まず、必要なライブラリーをインポートする。このうち、numpyはPythonのインストールで同時にインストールされるので、ライブラリーとして別途インストールする必要はない。#以下はコメント文である。
import pyaudio #マイク入出力処理 import numpy as np import matplotlib.pyplot as plt #グラフ処理 import cv2 #カメラ画像処理
次に一連の音声入力をストリーミングとして関数化する。CHUNKは入力単位でここでは、1024個ごとにサンプリングする。サンプリング周波数は変えられるが、デフォルトのままにした。録音時間はパルスの描画を考慮して120msecにした。
def streamandshow(): #入力からグラフ描画まで処理 CHUNK = 1024 #入出力の長さ FORMAT = pyaudio.paInt16 #2Byte整数 CHANNELS = 2 #ステレオ RATE = 44100 #サンプリング周波数(Hz) RECORD_SECONDS = 0.12 #録音時間(秒)
ストリーミングをオープンし、CHUNKごとのデータdata-rawをframesというlistに追記していく。
p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, #入力のみ frames_per_buffer = CHUNK) frames = [] #空のlistを用意 for i in range(int(RATE* RECORD_SECONDS // CHUNK)): #CHUNK単位で切り捨て data_raw = stream.read(CHUNK) frames.append(data_raw) #追記
framesのデータを2進数に数値化する。
frames_int16 = np.array(frames)
ここでストリームを閉じる。
stream.stop_stream() #ストリームを閉じる
stream.close()
p.terminate()
以下は、パルス波形を描画するための演算で、まず、2進数を10進数に変換し、データは片チャンネルだけでよいので、ステレオのLチャンネルのデータだけを抽出する。さらに、データの最大値を求め、画面に出力する。
data = np.frombuffer(frames_int16, dtype='int16') data_l = data[::2] #ステレオのLチャンネル data_max = max(data_l) #最大値を求める print(data_max) #最大値を画面に出力
グラフの大きさを決め、パルス波形を描画する。描画は0.3秒間だけ保持して、全体の処理を繰り返す。
fig = plt.figure(num = 1, figsize = (6, 4)) #グラフの大きさを決める plt.plot(data_l[100:]) #最初の100点をスキップ plt.pause(0.3) #0.3秒間だけ描画 plt.clf() #グラフを閉じる
プログラムの停止の停止には、キーボードからQを入力する。
while True: #キー入力を待つ if cv2.waitKey(1) & 0xFF == ord('q')#qを入力すると、 break #処理を終了 streamandshow() #処理を反復
PythonはWindows Power ShellやCMDのコマンドラインで実行されるため、Pythonプログラムの一時中断や再開といった手段がない。waitKeyを使うのはカメラの機能だが、利用させてもらった。ウエブカメラを使用していないのに、OpenCVをインポートしたのはそのためである。Pythonが実装されていれば、PythonファイルをダブルクリックすればPythonプログラムが起動する。バグがあったり、プログラムが終了したりすると、CMDなどの窓が閉じてしまうので、バグフィックスにはCMDでPythonファイルを実行させる方が良い。バグがあれば、エラー原因などが表示されている。また、出力が表示されているので、出力を確認するにはこの方が良い。
パルス波高分布のグラフ描画の例を以下に示す。
上のパルス波形を見て、計数の閾値を例えば1000と決めることができる。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)
教育用GM管開発を振り返って(8)その2
(その2)は続編なので、前編がまだの方は前編を先に。
7SEGGM管のPICプログラム(続き)
以下が計数を実行する本体で、まず検出を確認する。信号がONなら、フラッグを立て、再度、信号がONになれば、検出とみなしてフラッグを降ろす。CINI以下は、反復して実施される。
CINI BTFSS PORTA,4 ;RA4がクリアならばMAINへ GOTO CPAS BSF ON,0 ;(ON,0)をセット GOTO MAIN CPAS BTFSS ON,0 ;(ON,0)がクリアならばMAINへ GOTO MAIN
次では、パルスの検出後1msec以内の後続パルスを継続的に排除して、複数パルスによる重複カウントを避ける処理を実行している。
PDOWN ;パルスの立下りを検出 MOVF TMR1H,0 ADDLW 0xF9 BTFSS STATUS,C ;TMR1H=256-7=249=0xF9 GOTO T1CLR MOVF TMR1L,0 ADDLW 0x30 BTFSC STATUS,C ;TMR1L=256-208=48=0x30 GOTO CSTART ;TMR=7*256+208=2000=1msec/(0.125usec*4) T1CLR ;TMR1リスタート CLRF TMR1H CLRF TMR1L MOVLW B'00000001' MOVWF T1CON
ここからが、計数の本体で、まず、計数を8進数で加算し、10進数の各桁に桁上がりを含めて換算する。
CSTART INCF N1,1 ;N1=N1+1 MOVF N1,0 SUBLW 0x0A BTFSS STATUS,Z GOTO NCL CLRF N1 INCF N2,1 ;桁上がり(N2=N2+1) MOVF N2,0 SUBLW 0x0A BTFSS STATUS,Z GOTO NCL CLRF N2 INCF N3,1 ;桁上がり(N3=N3+1) MOVF N3,0 SUBLW 0x0A BTFSS STATUS,Z GOTO NCL CLRF N3 INCF N4,1 ;桁上がり(N4=N4+1) MOVF N4,0 SUBLW 0x0A BTFSS STATUS,Z GOTO NCL CLRF N4 NCL BCF ON,0 ;(ON,0)をクリア GOTO MAIN
以下はサブルーチンで、HFEXでは、ボタンスイッチが押されたときに立てるフラッグのONとOFFを切り替える。LEDOFFでは7セグメントLEDを消灯する。
HFEX BTFSC HF,0 GOTO EX0 BSF HF,0 ;If Hold flag is clear RETURN EX0 BCF HF,0 ;If Hold flag is set RETURN ; LEDOFF CLRF PORTB ;Rev.2 BCF PORTA,0 BCF PORTA,1 BCF PORTA,2 BCF PORTA,3 RETURN
DSPでは7セグメントLEDに数値を表示する。計数のレジスターが改変されないように、レジスターを置き換えて処理をしている。
DSP ;7seg-LED display LX0 MOVF LX,1 BTFSS STATUS,Z GOTO LX1 BTFSC PORTA,0 GOTO LXE MOVF N5,0 MOVWF N CALL SEG MOVWF PORTB BSF PORTA,0 ;RA0点灯(7-SEGがカソードコモンのため、NPNTr使用) GOTO LXE LX1 MOVF LX,0 SUBLW 0x01 BTFSS STATUS,Z GOTO LX2 BTFSC PORTA,1 GOTO LXE MOVF N6,0 MOVWF N CALL SEG MOVWF PORTB BSF PORTA,1 ;RA1点灯(7-SEGがカソードコモンのため、NPNTr使用) GOTO LXE LX2 MOVF LX,0 SUBLW 0x02 BTFSS STATUS,Z GOTO LX3 BTFSC PORTA,2 GOTO LXE MOVF N7,0 MOVWF N CALL SEG MOVWF PORTB BSF PORTA,2 ;RA2点灯(7-SEGがカソードコモンのため、NPNTr使用) GOTO LXE LX3 MOVF LX,0 SUBLW 0x03 BTFSS STATUS,Z GOTO LXE BTFSC PORTA,3 GOTO LXE MOVF N8,0 MOVWF N CALL SEG MOVWF PORTB BSF PORTA,3 ;RA3点灯(7-SEGがカソードコモンのため、NPNTr使用) LXE RETURN
SEGでは、10進数の数値の表示を7セグメントLEDの各セグメントに割り当てている。
SEG ;7SEG変換 MOVF N,1 BTFSC STATUS,Z RETLW B'01111110' ;0 MOVF N,0 SUBLW 0x01 BTFSC STATUS,Z RETLW B'00110000' ;1 MOVF N,0 SUBLW 0x02 BTFSC STATUS,Z RETLW B'01101101' ;2 MOVF N,0 SUBLW 0x03 BTFSC STATUS,Z RETLW B'01111001' ;3 MOVF N,0 SUBLW 0x04 BTFSC STATUS,Z RETLW B'00110011' ;4 MOVF N,0 SUBLW 0x05 BTFSC STATUS,Z RETLW B'01011011' ;5 MOVF N,0 SUBLW 0x06 BTFSC STATUS,Z RETLW B'01011111' ;6 MOVF N,0 SUBLW 0x07 BTFSC STATUS,Z RETLW B'01110000' ;7 MOVF N,0 SUBLW 0x08 BTFSC STATUS,Z RETLW B'01111111' ;8 MOVF N,0 SUBLW 0x09 BTFSC STATUS,Z RETLW B'01111011' ;9 RETLW B'01001111' ;E ; END
見た目は複雑そうだが、実際は順に実行されるので、演算の流れのイメージは掴みやすい。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)
教育用GM管開発を振り返って(8)その1
自作には工作技術のほかにマイコンやパソコンのプログラミング技術が必要になる。ここでは、7セグメントLED表示の7SEGGM管を例にとってPICマイコンのプログラミングについて解説したい。
必要なもの
マイコンにもいろいろあるが、PICマイコンを使い出した切っ掛けは、たまたま手に取った入門書がPICだったのと、「電子工作の実験室」というサイトの存在が大きい。偉そうに言っても、プログラミングは誰かのパクリから始まる。PICのマニュアルだけでアセンブラーが書けるわけもない。まずは、入門書の例を実際に確認していくことから始まった。その前に、PICを使用するにはプログラムを書き込むライターが必要だ。Microchip社の純正ライターは高いので、秋月電子製の同等品のキットを購入し、はんだ付けして作った。今でも使っていて問題はない。言語については、当時はアセンブラーだけが無料で利用できた。現在はC言語が無料で使用できるが、C言語は使ったことがない、というか、勉強したが、ポインターという考え方が理解できずに挫折した。Microchip社のマニュアルもアセンブラーで使用例が記述されている。
最初は情報館で
PICを使い始めたのは情報館の工作教室だった。何か、中学生に適した工作はないかと考えて思い付いたのはロボットだったが、予算的に実現が難しい。何とか千円程度の部品代で済む工作はないかと考えて、特別にワークショップという枠を設け、PICを使った工作物を展開した。バーサライターといって情報館にも展示物があって振ると文字が見えるという工作を手始めに、ベンハムのコマ、赤外線リモコン、走行モジュール、電子サイコロなどを実施した。これで、かなりプログラミングの腕を上げたと思う。バーサライターこそパクリだったが、ベンハムのコマはモーターの回転制御、赤外線リモコンはパルス制御、電子サイコロは乱数の実現などの課題があった。
7SEGGM管のPICプログラム
「らでぃ」の実験集に掲載しているが、以下に一部を抜粋して解説する。
最初はコンフィギュレーションで始まる。品番と基本的なスイッチの選択を指定する。この部分だけは他の部分と書式が違っている。一般的には、ラベル、命令など、引数など並んでいる。PICは、使い慣れた16F84Aの後発品で機能をアップした16F819を使用した。
INCLUDE "P16F819.INC" LIST P=16F819 __CONFIG _INTRC_IO & _WDT_OFF & _PWRTE_ON & _BODEN_OFF & _MCLR_OFF & _LVP_OFF & _CP_OFF
ここで、MCLRをOFFにしたのは、PICの4番ピンを10秒率への切り替え判定に使用したことによる。
次はファイルレジスタの定義。Nの列は変数で0x20などはメモリー位置を表す。;以下はコメント。
N EQU 0x20 ;Converter to 7seg-LED ON EQU 0x21 ;Pulse detection flag TU EQU 0x22 ;Counter for 1sec-timer WB EQU 0x23 ;Backup of STATUS SB EQU 0x24 ;Reset of W TM EQU 0x25 ;Counter for 10sec-timer LX EQU 0x26 ;Dynamic light-on N1 EQU 0x27 ;10^0 N2 EQU 0x28 ;10^1 N3 EQU 0x29 ;10^2 N4 EQU 0x2A ;10^3 N5 EQU 0x2B ;Holder of N1 N6 EQU 0x2C ;Holder of N2 N7 EQU 0x2D ;Holder of N3 N8 EQU 0x2E ;Holder of N4 HF EQU 0x2F ;Hold Flag
次がプログラムの最初で、実行もここから順に行われる。タイマーTMR0による1秒間を作り出す割込みのための割込み処理を記述している。この1秒ごとのクロックは常時動作している。第2カラムは命令で、確か35ある命令のうち必要なものだけを覚えればよい。数値は、主に2進数か8進数で表示されている。つまり、1から255までの8ビットに相当する数値を表している。
ORG 0 ;リセットベクタ GOTO START ORG 4 ;割込みベクタ BCF INTCON,TMR0IF ;割り込みフラグをクリア MOVWF WB ;Wレジスタ退避 SWAPF STATUS,0 ;STATUS取り出し MOVWF SB ;STATUS退避 BANKSEL TMR0 MOVLW 0xD9 ;カウント値=217(=256-39)を再ロード MOVWF TMR0 INCF TU,1 ;TUレジスタをカウントアップ BCF PORTA,0 ;全消灯 BCF PORTA,1 BCF PORTA,2 BCF PORTA,3 INCF LX,1 ;LXレジスタをカウントアップ MOVF LX,0 ADDLW 0xFC BTFSC STATUS,C ;LX=4ならばリセット(LX=0) CLRF LX SWAPF SB,0 ;STATUS戻し MOVWF STATUS SWAPF WB,1 ;Wレジスタ戻し SWAPF WB,0 RETFIE
次では主にCPUの速度、入出力ポート、タイマーTMR0の時間間隔、計数レジスターなどの初期値を指定しており、最初に1回だけ実行される。
START BANKSEL OSCCON MOVLW B'01110100' ;内部クロック8MHz MOVWF OSCCON BANKSEL ADCON1 MOVLW B'00000110' ;All pins as digital I/O MOVWF ADCON1 BANKSEL TRISA MOVLW B'11110000' ;RA4-RA7を入力ポート、RA0-RA3を出力ポート MOVWF TRISA BANKSEL TRISB MOVLW B'00000000' ;RB0-RB7を出力ポート MOVWF TRISB BANKSEL OPTION_REG MOVLW 0x87 ;256カウントモード指定 MOVWF OPTION_REG ;プリスケーラへ出力 BANKSEL TMR0 MOVLW 0xD9 ;カウント値=217(=256-39) MOVWF TMR0 ;タイマーへ出力 BCF ADCON0,ADON BSF INTCON,TMR0IE ;タイマ割り込み許可 BSF INTCON,GIE ;全体割り込み許可 CLRF N1 ;N1,N2,N3,N4は1位から4位 CLRF N2 CLRF N3 CLRF N4 CLRF N5 ;N5,N6,N7,N8は保持用 CLRF N6 CLRF N7 CLRF N8 CLRF TU CLRF LX CLRF ON CLRF TMR1H CLRF TMR1L BSF HF,0 ;Hold ON
次からが実行の本体で反復して実行される。ここで、まず、1秒率の測定か、10秒率の測定かを判断する。
MAIN BCF INTCON,TMR0IE ;タイマ割り込み禁止 CALL DSP ;7seg-LED display BSF INTCON,TMR0IE ;タイマ割り込み許可 BSF INTCON,GIE ;全体割り込み許可 BTFSS HF,0 ;If Hold Flag is set CALL LEDOFF ;If Hold Flag is clear BTFSS PORTA,5 ;Sellect SW GOTO SEL10 ;Sellect SW is clear
7セグメントLEDは起動とともに1秒率の表示で始まって、計数ブロックのCINIで計数し、1秒ごとに表示、1秒間保持をする。
SEL1 ;Sellect SW is set(count/1sec) BSF HF,0 MOVF TU,0 ;TUレジスタが200でリセット(5msec*200=1sec) ADDLW 0x38 ;256-200=56=0x38 BTFSS STATUS,C GOTO CINI ;Counting CLRF TU MOVF N1,0 ;計数保持 MOVWF N5 MOVF N2,0 MOVWF N6 MOVF N3,0 MOVWF N7 MOVF N4,0 MOVWF N8 CLRF N1 CLRF N2 CLRF N3 CLRF N4 GOTO MAIN
ボタンスイッチを押すと10秒率の表示に切り替わる。CINIで計数すると同時に、サブルーチンHFEXが呼ばれて10秒率のフラッグがONであることを確認し、7セグメントLEDにカウントダウンが表示される。10秒経つと10秒間のカウント数が表示され、次にボタンスイッチが押されるまで表示が保持される。
SEL10 MOVF TU,0 ;TUレジスタが200でリセット(5msec*200=1sec) ADDLW 0x38 ;256-200=56=0x38 BTFSS STATUS,C GOTO CINI CALL HFEX CLRF TU INCF TM,1 ;TM=TM+1(sec) MOVF TM,0 ADDLW 0xF6 ;256-10=246=0xF6 BTFSS STATUS,C GOTO CINI CLRF TU CLRF TM
以下が10秒率の表示になる。
SELX ;10sec毎に表示 MOVF N1,0 ;計数保持 MOVWF N5 MOVF N2,0 MOVWF N6 MOVF N3,0 MOVWF N7 MOVF N4,0 MOVWF N8 CLRF N1 CLRF N2 CLRF N3 CLRF N4 GOTO MAIN
以下は、教育用GM管開発を振り返って(8)(その2)に続く。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)
教育用GM管開発を振り返って(7)
自作できることを基本的なコンセプトとして、開発を進めてきた。ここでは、標準型GM管を例にとって、自作の心構えやスキルについて話してみたい。
必要なもの
元より高価な測定器などは使用していない。最小限必要な計測器でも、たかだか1万円台である。しかし、買い溜めた工具類は、1点数千円でも総額は計り知れない。以下は、クリアケースGM管と高電圧電源の製作に必要な工具類で、「らでぃ」の実験集にも掲載されているが、これだけの工具を一度に揃える必要がある。ただし、*印が付いた工具は、手間を省くための工具なのでなくても構わない。
- 可変速電動ドリル*
- ピン・バイス
- ドリル刃(φ1.5、φ2.5、φ3.0、φ3.2)
- リーマー
- スパイラル・ドリル刃*
- 面取りドリル刃*
- ドライバー
- 組みスパナ
- はんだごて
- はんだ吸い取り器
- はんだごてスタンド
- 電圧調整器
- ラジオペンチ
- ニッパー
- ピンセット
- ブラシ
- やすり
- クリップ
- 木片
- マーカー
- ワイヤーストリッパー
- はさみ
- カッター
- カッティング・マット
- 定規
- ケース用ゲージ*
- GM管用ゲージ*
- 穴あけポンチ(φ2)
- 金づち
- マット
このほかに、完成後の動作不良などの対応には、主に導通や電圧を測定するために、テスターまたはデジタルマルチメーターが必要になる。*印が付いた工具は、5台とか10台など製作数が多い場合に労力を減らすための工具なので、体力や筋力に自信があったり、1日に何台も製作しなかったりする場合はなくてもよいが、あると楽に作業ができる。
製作にあたっては、当然、部品が必要になる。同じ例では、以下のような部品を購入する必要がある。秋葉原の各店の通販で購入したが、必ずしも1店では揃わない。
- (1)小型ボリューム 5KΩB
- (2)テストピンジャック(黒)
- (3)テストピンジャック(赤)
- (4)5mm赤色LED ESL-R5A33ARCN114
- (5)トランジスタ 2SC2120-Y 35V800mA
- (6)006Pアルカリ電池 9V
鈴商
- (1)タカチ電機工業 PB型プラケース PB-2
- (2)スライドSW(3P・中) 19-3P
- (3)サトーパーツ ラグ板2列×5P L-3522-5P
- (4)マル信無線電機 RCAプラグ(黄)MR-568M 黄
- (5)RCAジャック(カラーリング付き、黄)
- (6)ビス 真鍮 ナベ 2×5mm 100個入
- (7)電池スナップ(スケルトンタイプ)120mm I-120
- (8)goot 精密プリント基板用ハンダ SD-62
- (9)セラミックイヤホン(プラグなし)
- (10)耐熱電子ワイヤー UL3265-24 L-10 赤
- (11)耐熱電子ワイヤー UL3265-24 L-10 黒
そのほかにも、小物があって、
モノタロウ
別途購入
- 高圧電源基板 @200×100
- 被覆電線 0.75mm2 20mm×100
- 熱収縮チューブ φ3.0 10mm×100
- 熱収縮チューブ φ1.0 10mm×100
- ピン針 ×100
- 黒画用紙 50mm×170mm×100
- シール 赤・丸 φ5×200
- シール 黒・丸 φ5×200
- 両面テープ マット 15mm×7mm×200
- 両面テープ プラスチック用 15mm×30mm×100
- アルミテープ 75mm/10×60mm×100
- 金属シール 10mm×20mm×200
これらの小物は、秋葉原の店舗で見て購入したり、近くのホームセンターや文具店で購入したりしたものである。
これだけの、購入品のリストを作り、どの店にあるかを調べて発注するだけでもかなりの労力と時間を要する。当然、それ以前に、開発の構想があり、回路図や設計図の作成があり、といってもポンチ絵しか描いたことはないが、試作があり、必要に応じて改良があり、等々のプロセスがあるが、実はそれ自体が、いわば自作の醍醐味である。自作は出来上がってしまえば、それを使用するか、飾っておくか、誰かに譲るか、しか選択肢がない。これを見て、萎えるようなら自作などやらない方が良い。挑戦心が湧いてくるようなら、見込みはある。
工具には取り扱いによってはケガをするものもあり、緊張感をもって作業する必要がある。当然、手作業なので出来栄えにも考慮しなければならない。できるだけ美しく作るのも自作の楽しみの一つと思う。電子回路には、はんだ付けが必須の作業である。まず、きれいにはんだ付けができないといけない。でないと、トラブルに悩まされるうえに、修復にも手間がかかる。自作では、ユニバーサル基板という2.54mmピッチの基板のホールにはんだ付けするが、かなり細かい作業になる。慣れればともかく、最初はかなり窮屈に見える。実際、注意しないと、隣のホールにはんだがつながってしまう。はんだごての選定も重要で、こて先の細い方が細かい作業に向いているような気がするが、熱量が小さいのではんだが溶けにくい。はんだも工業製品では無鉛はんだ使用が常識だが、無鉛はんだは融点が高いので、はんだ付けに失敗したときの修復が難しい。自作では有鉛はんだの方が無難と思う。言うまでもないが、はんだごてによる火傷には注意したい。はんだ付けの作業には、こて台についているスポンジを頻繁に使った方がよい。予めスポンジには水を浸して軽く絞っておくが、こて先をきれいにするとともにこて先の過熱を防ぐ効果がある。ユニバーサル基板では、プリント基板と違って配線は自分で自由にできるが、配線の多重交差はできるだけ避けたい。後で、不具合があったときに、はんだ付けが原因でも、怪しい個所にアクセスしにくくなるうえ、修復の際に配線を一旦外して再度はんだ付けする個所が増えてしまう。
図で見る通り、高圧電源の電子回路は冷陰極放電管用の高圧ユニットをジャンク品で使用しているだけで、ユニバーサル基板はない。倍電圧整流回路は10Pラグ板上に組んでいるので、この場合はむしろワット数の大きいはんだごてを使用した方が良い。話しが後先になるが、この冷陰極放電管用の高圧ユニットはジャンク品なので、現在は手に入らないと思う。鈴商で購入したものだが、鈴商は営業を続けているので、問い合わせて在庫があれば手に入るかもしれない。ほかに、冷陰極放電管用の高圧ユニットの代品を探す手もある。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)
教育用GM管開発を振り返って(6)
自作GM管の代表格である「大気圧空気GM管」は「空気GM管」とも称される。なぜ、ここで「空気」を取って「大気圧GM管」としたかなど、本質的な話題について語ります。
大気圧GM管のポイント
開発の初期に、管のサイズや、アノード、カソード、ガス組成などをパラメーターとした実験を行い、候補を絞り込んだ。その結果が、クリアケースGM管になり、塩ビ管を容器とする密閉型のGM管に至っている。現在は、さらに簡素化して、密閉型GM管のガス注入ノズルを排して、半密閉にするという改良を進めている。半密閉というのは、注入孔に蓋を接着するが、必要に応じて蓋を剥がしてブタンを再注入できるというもの。自作なのでGM管の性能が所定の基準に満たない場合がある。その場合に、必要に応じて内部パーツやガスを交換できるようにしておけば、再生が可能になる。ガス交換を例に挙げたが、アノードを交換する場合は、端窓を一旦剥がし、交換後に修復する。実は、塩ビの容器と天板の加工にもっとも手間がかかるので、これらが再利用できれば残りの手間は少ない、というのがその理由である。この改良した密閉型GM管は最近のテストでは、1ヵ月以上もほぼ性能を維持しているが、今後、テストを継続して性能の維持期間を見極める。
改めて強調するが、「大気圧GM管」の基本的構成要素は、二つ折りで先端フープのアノード、線材はステンレス鋼、黒画用紙のカソード、充填ガスは10%程度のブタン+空気、の3点である。これらは、クリアケースGM管で確立し、密閉型GM管でも継承されている。外部構造としての、高電圧電源との接続を露出部のないプラグイン方式も一貫して採用している。エビデンスは「らでぃ」の実験集に載せたので、以下ではポイントについて解説する。
アノードについては、基本的に米村式の二つ折りアノードを採用している。電界解析でも、通常の円筒形GM管のような全長の単線アノードよりも、中間長のアノードの方が先端部での電界強度が大きいことが分かっているが、実験結果でもその傾向は支持されている。一般的には線材は細い方が、より電界強度が高くなる。つまり、動作電圧が低くなって有利に働く。しかし、先端部にフープがある場合は違う結果となる。要するに、先端フープがあることで線径の効果が打ち消される一方、先端部での電界強度が効果的に効いてくる。先端フープの径をパラメーターとすると、径が小さいほど電界強度は大きくなるが、極端に小さい、例えばフープなしにすると、放電が不安定になり、プラトー領域も極端に狭くなる。したがって、最適なフープ径は2mm程度と考えている。実はステンレス鋼をアノードに加工する場合、先端フープを径2mmに仕上げるのは工具なしでは難しい。ではどうするか。二つ折りにした他端をラジオペンチで挟んで、指でよじり、ある程度の径になったら、楊枝の先を使って2mmに仕上げることができる。アノードの先端には工具で傷を付けたくない。ステンレス鋼を使用する理由は前にも書いたが、銅線に比べて汚れが付きにくく、酸化しにくいことにある。白金線ならば加工はしやすいと思うが、極めて高価で自作には向かない。ステンレス鋼の線径は、0.23mmを継続的に採用しているが、知る限り、ホームセンターなどで入手できる最小の線径である。アノード・ユニットはピンに刺すだけという形状の特徴があって、交換が容易なように配慮している。
初期の「大気圧空気GM管」のカソードは、ただ紙製としか書いていないが、白画用紙と考えられる。黒画用紙にしたのは、仲間内の情報からで、紙に墨汁を塗って乾かすとカソードに使えるというものだった。あるいは、コピーの印刷面でもよいという情報もあった。黒画用紙にしたのは、カーボンが含まれているからで、導電性があると考えていた。実際、長方形のカソードの形状で、その両端をそれぞれクリップで挟み、その間の抵抗値を測ると、100kΩから400kΩであった。実際に実験すると、この範囲ではそれほどプラトー特性に違いはない。しかし、あるとき、別の黒画用紙を買ってきて同様にして抵抗値を測ると、無限大になっていた。どうも炭素を含まない黒画用紙もあるようで、よく見るとやや緑がかっていた。それ以来、黒画用紙を買った後は、必ず抵抗値を測定するようにしている。実は、白画用紙でもプラトー領域が高電圧側にシフトし、やや計数値が低下するが、測定できなくはない。カソードの導電率が影響しているとすると、金属カソードの方が有利に思える。ではなぜ、黒画用紙なのか。金属カソードは、アルミと銅とステンレス鋼を比較したが、どれも大きな違いはない。銅は酸化や汚れに弱いので使いにくい。ステンレス鋼は硬すぎる。使うとするとアルミなので、黒画用紙と比べてみると、少なくともプラトー領域や計数率の面で黒画用紙が劣っている訳ではないことが分かった。また、黒画用紙の利点は、γ線に対して感度が低い点にもある。GM管をβ線検出器として利用したい場合、γ線が少ないほどよい。距離の実験ではγ線はβ線と込みで考えればよいが、遮へいの実験ではバックグラウンドとして効いてくるので、少ない方が好ましい。金属カソードの難点の一つは、傷が付きやすく異常放電の原因となることである。その点、黒画用紙なら何も気にすることはない。ついでに言えば、黒画用紙は金属カソードよりも圧倒的に安く、自作には適している。
「空気GM管」でないのは何故か
最初の矢野先生の「空気GM管」は、まさに空気だけだった。その後、米村先生がライターガスを消滅ガスとして添加した。ライターガスは、一般的にはブタンが主成分で、プロパンが入っているものもある。ガス自体は液化石油ガスというカテゴリーにあって、ブタン濃度が高いほど高級とされる。初期の「大気圧空気GM管」はほとんどライターから直接GM管内にガスを注入している。ガスの濃度の記述はない。道具なしで定量のガスを注入するのは極めて難しい。そこでシリンジを使うことにした。これならば定量のガスを注入できるので、厳密ではないがある程度ガス濃度のコントロールができる。その後に分かったことだが、多少濃度が変わっても、それほど性能には影響がない。これまでの失敗例を聞くと、ライターの選定だったり、ガスの注入量が適当だったりしたことが原因と思われる。
現在、使用しているのは高純度ブタンという表示のあるライター充填用のガスボンベで、プロパンの混入は極めて少ない。断っておくが、カセット式のガスコンロにつかうブタンガスもGM管には使える。ただし、ガス漏れを防ぐための悪臭がある。プロパンは試していないので、使えるかどうかは分からない。パラメーター実験では、10%から50%の範囲でブタン濃度の上昇とともにGM管の動作電圧が線形で上昇した。10%を選択したのはこの結果を受けたもので、さらにブタン濃度を減らせばより動作電圧としては有利になると思ったが、濃度のコントロールが難しくなるので止めた。
オシロスコープ観察からは、ブタン濃度が増えると複数パルスの発生が減少するので、消滅ガスとしての作用は認められる。しかし、容量%でブタン濃度50%となると、重量%ではブタンの方が多くなる。10%ブタンならともかく、50%ブタンにもなると、さすがに「空気GM管」なのか迷うところだ。その後、0%ブタンつまり100%空気から、100%ブタンまでブタン濃度をパラメーターとするオシロスコープ観察でパルスの数を数えて計数に換算した。その結果、0%ブタンでも100%ブタンでも計数は可能で、動作電圧の最小値は2%から5%ブタンであった。ブタン濃度度が増えると、ほぼ直線的に動作電圧が上昇し、0%ブタンでは極めて高い動作電圧となることなどが分かった。100%ブタンとなると、もはや「空気GM管」ではあり得ない。その中間も空気が主な電離気体なのか疑わしい。というのは、空気もブタンも同程度の電離電圧なので、どちらも電離気体の候補になる。消滅ガスの役割は炭化水素であるブタンのものだが、電離気体がどちらなのか、あるいは両方なのかは分からない。5%前後で動作電圧が最低になるのも、何か理由があるはずだが調べても分からない。
このように考えて、「空気GM管」とは呼ばずに、「大気圧GM管」と呼ぶことにした次第。
(※id:TJOがid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)