趣味

2011.07.05

自作ガイガーカウンタ2号機タイプ1(Rev.3=最終版)の製作

更に色々、試した結果、電源電圧の振れ幅が、だいぶん大きく、その影響を少なくするために、回路図を見直しました(2011年7月10日)。最新の回路図と実装図は下記となります。

11070205 11070403

こんな感じ。動作確認の結果は下グラフになった。

Gmgraph_20110710

出力パルスに最大値を示す緑色線の振れ幅は、10%程度のおさまっているようだ。


2011年7月5日時点の内容 → 自作ガイガーカウンタの電源に使用している家庭用AC100Vの電圧に、日中、変動が、だいぶんあるようなので、その安定化と、GM管も、J305βγで使うDC400V前後に特化して回路Rev.3へ置き換えることにした。下左画像が、回路図で、右下画像が、実装素となる。現在、長期動作確認中。2号機タイプ1としては、これで最終版とします。

11070203 11070402

今回採用の定電圧ダイオードは、デッドストックながら、1Z390を使用した、これは、200V定電圧ダイオード2本のカスケードや、100V定電圧ダイオードの4本のカスケードでも、同様の動作が得られる。100V定電圧ダイードは、チップ型であれば、現行生産品もあるよだ。 

さて、動作テストは、GM管の駆動電圧は、408Vの出力が出ていた。また、GM管のパルス出力は、約40mVと、Rev.2とだいたい同じ。

11070501 11070502

正常に、パスル出力も出ることを、確認。web公開測定システムへ接続して、テスト用線源(マントル)を接近させてみると、、、、

11070503_2

線源への反応もあるので、このまま、動作テストを継続。

| | コメント (2) | トラックバック (0)

2011.06.23

自作ガイガーカウンタ測定値のWEB公開システムプロト(3)

何とも、iPad/iPhone/iPod Touchでは、Javaアプレットが動作しないということなので、グラフを、JPEG画像ファイルへ出力するJavaアプリを作ってみた。これを、定期 的に実行して、Webサーバへ置いておけば、iPad/iPhone/iPod Touchでも、グラフとして、自作ガイガーカウンタの計測値が見れる。

Gmgraph_20110622
さて、このJavaアプリのシースコードは、下記になります。


import java.awt.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.applet.Applet; 
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.geom.*;
import java.io.IOException;

public class test_img 
{

	public static void main(String args[]){

		int sx=2;
		int sy=3;
		int wx=320;
		int wy=240;
		int sz_x = 410;
		int sz_y = 240;
		int oft_y=0;
		int oft_x=100;

		Date dt = new Date();
		Calendar cal = Calendar.getInstance();

		int myYear = cal.get(Calendar.YEAR);
		int myMon = cal.get(Calendar.MONTH) + 1;
		int myDay = cal.get(Calendar.DATE);

		String myDate;

		BufferedImage myImage = new BufferedImage( sz_x, sz_y, 
			BufferedImage.TYPE_INT_BGR);

		try {
			// 背景画像(410x290)が必要(最初は白地でやって調整して)
			myImage = ImageIO.read(new File("11062008.jpg"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		Graphics2D off = myImage.createGraphics();
		off.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
			RenderingHints.VALUE_ANTIALIAS_ON);

		myDate = "" + myYear;
		if (myMon < 10) {
			myDate = myDate + "0" ;
		}
		myDate = myDate + myMon;
		if (myDay < 10) {
			myDate = myDate + "0" ;
		}
		myDate = myDate + myDay + ".";

		// これは、計測データを取ってくるサイトのホスト名
		// 同じPCで済む処理だけど、WEB経由で取り出してるよ
		String url;    String host = "example.org";
		int port = 80;
		Socket sock;
		BufferedReader sockin;
		BufferedWriter sockout;
		String str;
		int x=30,y=30,h=40,n=3;
		int i=0;
		int j=0;
		int px_cur=0, py_cur=0;
		int px_prv=0, py_prv=0;

		url = "http://" + host +  "/demo/gmdata_" + myDate + "csv";

		System.out.println( url );

		try {
			wx = sx * 24 * 6;
			off.setColor( Color.BLACK );
			off.drawLine(0+oft_x,wy-1+oft_y,
				wx+oft_x,wy-1+oft_y ); // X
			off.drawLine(0+oft_x,wy-10*sy+oft_y,
				wx+oft_x, wy-10*sy+oft_y ); // X

			for (i=0; i<8; i++ ) {
				off.drawLine(0+oft_x,10*i*sy+oft_y,
					wx+oft_x,10*i*sy+oft_y); // X
			}
			off.drawLine(0+oft_x,0+oft_y,
				0+oft_x,wy+oft_y); // Y
			for (i=12; i<(6*24); i+=12 ) {
				off.drawLine(sx*i+oft_x,sy*10+oft_y,
					sx*i+oft_x,wy+oft_y); // Y
			}
			off.drawLine(sx*i+oft_x,0+oft_y,
				sx*i+oft_x,wy+oft_y); // Y

			off.setColor( Color.BLUE );
			off.drawString( "DATE: " + myYear 
				+ "/" + myMon + "/" + myDay, 
				7+oft_x, 15+oft_y );

			sock = new Socket ( host, port );
			sockin = new BufferedReader(
			new InputStreamReader(sock.getInputStream()));
			sockout = new BufferedWriter(
			new OutputStreamWriter(sock.getOutputStream()));

			sockout.write("GET " + url +" HTTP/1.1\r\n");
			sockout.write("Host: " + host + "\r\n");
			sockout.write("Connection: close\r\n");
			sockout.write("\r\n");
			sockout.flush();

			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);
			str = sockin.readLine();
			System.out.println(str);

			int py_sum = 0;

			off.setPaint( Color.red );

			while ((str = sockin.readLine()) != null) {
				System.out.println(str);

				px_cur = j * 1;

				StringTokenizer st = new StringTokenizer(str, ",");
				st.nextToken();
				st.hasMoreTokens();
				py_cur = Integer.valueOf(
					st.nextToken().replaceAll(" ", "" ))*sy;
				py_sum += py_cur;

				off.draw( new Line2D.Double(
					px_prv*sx+oft_x, wy-py_prv+oft_y, 
					px_cur*sx+oft_x, wy-py_cur+oft_y 
				) );

				j++;
				px_prv = px_cur;
				py_prv = py_cur;
			}

			sockout.close();
			sockin.close();
			sock.close();

			int cpm_avg = (py_sum*10) / (j * sy);

			off.setColor( Color.BLUE );
			off.drawString( "J305Beta/Gamma AVG: " 
				+ cpm_avg + "/10 [CPM]", 
				7+oft_x, 28+oft_y );

			} catch (Exception ex) {
				ex.printStackTrace();
			}

			try {
				boolean result 
					= ImageIO.write( myImage, "jpg", 
					new File( "gmgraph_" + myDate + "jpg"));
			} catch( Exception e ) {
				e.printStackTrace();
			}

			System.exit(0);	
	  }
}

こんな感じ。これを、計測プログラムの直後に実行するように、タスクスケージュールしてみた。

11062401_2

この公開は、ここから閲覧できます。

なお、本サイトの提供する情報は、品質、信頼性、安全性などを保証するものではないことを、ご注意ください。

 

| | コメント (0) | トラックバック (0)

2011.06.19

自作ガイガーカウンタ2号機タイプ1(Rev.2)の製作

CK1026(駆動電圧DC900V)の不具合から、気を取り直して、中国製GM管J305βγ(駆動電圧DC380V)へ乗り換えて、製作を続行。これを、Rev.2とする。回路や部品は、CK1026のときのものを、配線変更などで、併用した。駆動電圧が、だいぶん異なるが、電源トランスの使用端子の変更などで、ちょうど対応が可能なようだ(下左回路図)。下右写真は、改造後の現物と動作確認の様子。

 

11051613 11061802

中身の様子は、J305βγの専用ホルダは新調(左下写真)。ラグ板上の部品の配置の変更はほとんどなく抵抗器の一端を、付け替えyたぐらいで済んだ(右下写真)。

11061903 11061902

マントルなどの線源を近づけてみて、CPMを測ってみた(下グラフ)。このGM管(但し、厚2mmのアルミケース越し)は、自宅の環境(市販のガイガーカウンタだと、だいたい、0.060μsV/h)だと、だいたい、10CPMを前後している。右下写真は、自作ガイガーカウンタの外観。

11061805 11061201

取り合えず、線量に応じてパルスのが出ているようだ。左下グラフに示すように、長時間連続動作テストを実施で、24h経過したが、特に不具合は起きていないようだ(このGM管は、中国製の現行部品なので、ちゃんと連続稼働して欲しいとことろだ)。また、24h経過後、右下グラフの0:00am-0:20amのところでマントルを近づけた結果、放射線への感度も維持されている事も確認した。

 

11062004
24h動作テスト
11062007
マントルへの感度確認テスト

まあ、このまま、連続稼働させて様子をみるが、以上の結果を以て、自作ガイガーカウンタ2号機タイプ1Rev.2の完成ということにしよう。お疲れ様でした。さて、次に行くか(^_^;A

【注意事項】

 安全上の注意として、金属ケースを使用する場合は、必ず、ケースにアースを取るようにしましょう。あと、本機の電源を入れた状態で中身をいじる作業は、絶対に身体にアースを取らず、絶縁手袋着用して、安全第一でお願い致します。

【備考1】

 今回、中国製GM管J305βγのために作ったオリジナルソケットホルダのアップ写真。

 

11062001 11062005

【備考2】

 今回の一連のガイガーカウンタ製作では、Webサーバ経由で測定値を開示することを前提に、電池(消耗品)不要で、家庭用AC100Vコンセントからの電源供給(ADアダプタは嫌いなので電源内蔵必須)で稼働する据え置き型ガイガーカウンタを前提にしてます。余談だが、携帯用のガイガーカウンタあれば、DC500V駆動の浜松ホトニクス製GM管を採用の1号機(チェルノブイリ原発事故のときに製作)をベースにすれば、小型かもそれほど難しくないかと(下写真)。但し、最近では、もっと市販のDC-DCコンバータでも適切なものがありそうなので、そっちも採用候補だと思う。

07031803

【謝辞】

今回の製作に必要となった部品や部材の調達など、アキバの部品屋さんや、三月兎さん、東急ハンズさん、有り難うございました。また、回路設計に関して、色々な方々と知人の助言に感謝です。


注)本記事の内容は、製作物の品質、信頼性/安全性などを保証するもではなく、ご注意下さい。


| | コメント (1) | トラックバック (0)

自作ガイガーカウンタ測定値のWEB公開システムプロト(2)

この記事は前回の記事のシステムが生成するCSVファイルを、Web経由で取得して、インターネットブラウザに折れ線グラフで表示させるJavaアプレットに製作に関するものです。下画像は、実行結果でだが、グラフとして表示されている内容はテストデータで意味はないものなので、ご注意下さい。

11061904_2
あくまでも、試作なので、装飾的な機能は、全くありません。Javaのソースコーソは、下記。


// ファイル名「test.class」として保存しないと、javacはエラーになる。
//
import java.awt.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.applet.Applet; 

public class test extends Applet 
{
	int sx=2;
	int sy=3;
	int wx=320;
	int wy=240;

	public void init() {
		this.setBackground(Color.white);
	}

	public void paint(Graphics g) {
		Date dt = new Date();
		Calendar cal = Calendar.getInstance();

		int myYear = cal.get(Calendar.YEAR);
		int myMon = cal.get(Calendar.MONTH) + 1;
		int myDay = cal.get(Calendar.DATE);
		String myDate;

// 以下、URLの生成は、使用者がカスタマイズする
//
	myDate = "/demo/gmdata_"  + myYear;
	if (myMon < 10) {
		myDate = myDate + "0" ;
	}
	myDate = myDate + myMon;
	if (myDay < 10) {
		myDate = myDate + "0" ;
	}
	myDate = myDate + myDay + ".csv";

 	String url;    String host = "XXX.XX";  // ホスト名
	int port = 80;  // ポート名
	Socket sock;
	BufferedReader sockin;
	BufferedWriter sockout;
	String str;
	 int x=30,y=30,h=40,n=3;
	 int i=0;
	 int j=0;
	 int px_cur=0, py_cur=0;
 	 int px_prv=0, py_prv=0;

//	url = "http://" + host + ":" + port + myDate;
	url = "http://" + host + myDate;

	System.out.println( url );

 	try {

		wx = sx * 24 * 6;
      		g.drawLine(0,wy-1,wx,wy-1 ); // X
      		g.drawLine(0,wy-10*sy,wx,wy-10*sy ); // X

	 	 for (i=0; i<8; i++ ) {
			  g.drawLine(0,10*i*sy,wx,10*i*sy); // X
	 	 }
	 	 for (i=0; i<(6*24); i+=12 ) {
			  g.drawLine(sx*i,0,sx*i,wy); // Y
		 }
	 	 g.drawLine(sx*i,0,sx*i,wy); // Y

		sock = new Socket ( host, port );
		sockin = new BufferedReader(
		new InputStreamReader(sock.getInputStream()));
		sockout = new BufferedWriter(
		new OutputStreamWriter(sock.getOutputStream()));

		sockout.write("GET " + url +" HTTP/1.1\r\n");
		sockout.write("Host: " + host + "\r\n");
		sockout.write("Connection: close\r\n");
		sockout.write("\r\n");
		sockout.flush();

		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);
		str = sockin.readLine();
		System.out.println(str);

		g.setColor( Color.RED );
		while ((str = sockin.readLine()) != null) {
			System.out.println(str);

			px_cur = j * 1;

			StringTokenizer st = new StringTokenizer(str, ",");
			st.nextToken();
			st.hasMoreTokens();
			py_cur = Integer.valueOf(st.nextToken().replaceAll(" ", "" ))*sy;
			g.drawLine( px_prv*sx, wy-py_prv, px_cur*sx, wy-py_cur );

			 j++;
			px_prv = px_cur;
			py_prv = py_cur;
		}
		sockout.close();
		sockin.close();
		sock.close();
	 } catch (Exception ex) {
		ex.printStackTrace();
	}
}

こんな感じ。チョッチ疲れた。しかし、iPadでもJavaアプレットが動くものと誤解してたが、動かなかったのかと、更に疲れた(*´д`*)〜з あと、本記事は、製作物の品質や信頼性/安全性を保証するものではないことを、ご注意下さい。

| | コメント (0) | トラックバック (1)

2011.06.11

自作ガイガーカウンタ測定値のWEB公開システムプロト(1)

現在、まだ、自作ガイガーカウンタは、動作確認中だが、自作ガイガーカウンタの出力パルス計測とWEB公開システムを、暫定で組んでみた(右下図)。


11061101 11060801

 

 

作成したプログラムのソースコード(MS VC/C++)は以下。でも、ハード構成に依って、修正が必要である事を、注意しておく。

[ソースコード置場] https://github.com/digiponta/GeigerCounterFromMic


// gm_cnt_01.cpp : コンソール アプリケーション用のエントリ ポイントの定義
//

#include "stdafx.h"
#include <windows.h>
#include <mmsystem.h>

#include "gm_cnt_01.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// 唯一のアプリケーション オブジェクト

// WinApp theApp;
using namespace std;

WAVEFORMATEX wfe;
WAVEHDR whdr;
short *bWave;
HWAVEOUT hWaveOut;
HWAVEIN hWaveIn;

UINT numDevs;


int MyMain(int argc, TCHAR* argv[], TCHAR* envp[]);


void MyWaveInProc ( HWAVEIN hwi, UINT uMSG, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) {
int ret;
if ( uMSG != 958 ) fprintf( stderr , "CALLBACKE! (%d) @ %d\n", uMSG, __LINE__ );

if ( uMSG == WIM_OPEN ) {
// fprintf( stderr, "WIM_OPEN(%d)\n", __LINE__ );
}

if ( uMSG == WIM_DATA ) {
ret = waveInStop( hWaveIn );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return ;
}
ret = waveInClose( hWaveIn );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return ;
}
// (long)hWaveIn = -1;
fprintf( stderr, "WIM_DATA(%d)\n", __LINE__ );
}

}

#define MAX_NUM_DEVS 10
HMIXER hMixer[MAX_NUM_DEVS];
int isOpenedMixer[MAX_NUM_DEVS];
MIXERLINE mixerLine[MAX_NUM_DEVS];
UINT idMic;


int MyMain(int argc, TCHAR* argv[], TCHAR* envp[] )
{
int ret = 0;
int i;

{
int j;
numDevs = mixerGetNumDevs();
if ( numDevs == 0 ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}
fprintf( stderr, "numDevs = %d\n", numDevs );
if ( numDevs > MAX_NUM_DEVS ) numDevs = MAX_NUM_DEVS;

for (i=0, j=0; i<numDevs; i++ ){
ret = mixerOpen( &(hMixer[i]), (UINT)i, 0, 0, MIXER_OBJECTF_MIXER );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d) can't open mixar[%d]\n", __LINE__,
i);
isOpenedMixer[i] = 0;
} else {
j++;
isOpenedMixer[i] = 1;
}
}
if ( j < 1 ) {
fprintf( stderr, "ERROR(%d) cna't open all mixers\n", __LINE__ );
return -1;
} else {
fprintf( stderr, "%d opendMixars\n", j );
}


for (i=0, idMic = -1; i < numDevs; i++ ){
mixerLine[i].cbStruct = sizeof( mixerLine );
mixerLine[i].dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
ret = mixerGetLineInfo( (HMIXEROBJ)hMixer[i], &(mixerLine[i]),
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
if ( ret == MMSYSERR_NOERROR ) {
// fprintf( stderr, "found Mic[%d]\n", i );
// fprintf( stderr,
// "Name: %s, %s, %x\n",
// mixerLine[i].szName,
// mixerLine[i].szShortName
// );
if ( (mixerLine[i].szName)[0] != (char)'R' ){
idMic = i;
}
}
}
fprintf( stderr, "Mic ID = %d\n", idMic );

MIXERCONTROL mixerCtrl;
MIXERLINECONTROLS mixerLineCtrls;

mixerLineCtrls.cbStruct = sizeof ( mixerLineCtrls );
mixerLineCtrls.dwLineID = mixerLine[idMic].dwLineID;
mixerLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mixerLineCtrls.cControls = 1;
mixerLineCtrls.cbmxctrl = sizeof ( mixerCtrl );
mixerLineCtrls.pamxctrl = &mixerCtrl;
ret = mixerGetLineControls(
(HMIXEROBJ)hMixer[idMic], &mixerLineCtrls,
MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
}
{
MIXERCONTROLDETAILS_UNSIGNED micVolume;
MIXERCONTROLDETAILS mixerDts;

mixerDts.cbStruct = sizeof( mixerDts );
mixerDts.dwControlID = mixerCtrl.dwControlID;
mixerDts.cChannels = 1;
mixerDts.cMultipleItems = 0;
mixerDts.cbDetails = sizeof ( MIXERCONTROLDETAILS_UNSIGNED );
mixerDts.paDetails = &micVolume;

ret = mixerGetControlDetails( (HMIXEROBJ)hMixer[idMic],
&mixerDts,
MIXER_GETCONTROLDETAILSF_VALUE );
if (ret != MMSYSERR_NOERROR ){
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}
fprintf( stderr, "Vol: %d, Max: %d\n", micVolume.dwValue,
mixerCtrl.Bounds.dwMaximum );

// micVolume.dwValue = 24348; // needed value for GM counter
micVolume.dwValue = 22000; // needed value for GM counter

mixerDts.cbStruct = sizeof( mixerDts );
mixerDts.dwControlID = mixerCtrl.dwControlID;
mixerDts.cChannels = 1;
mixerDts.cMultipleItems = 0;
mixerDts.cbDetails = sizeof ( MIXERCONTROLDETAILS_UNSIGNED );
mixerDts.paDetails = &micVolume;

ret = mixerSetControlDetails( (HMIXEROBJ)hMixer[idMic],
&mixerDts,
MIXER_SETCONTROLDETAILSF_VALUE );
if (ret != MMSYSERR_NOERROR ){
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}
fprintf( stderr, "Changed to Vol: %d, Max: %d\n", micVolume.dwValue,
mixerCtrl.Bounds.dwMaximum );

}


for (i=0; i<numDevs; i++ ){
ret = mixerClose( hMixer[i] );
}

}
// return 0;

wfe.wFormatTag = WAVE_FORMAT_PCM;
wfe.nChannels = 1;
wfe.nSamplesPerSec = 32 * 1000 ;
wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * 2 ;
wfe.wBitsPerSample = 16 ;
wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 16;

whdr.dwBufferLength = wfe.nAvgBytesPerSec * 60 ; // 60 sec

bWave = (short *)malloc( whdr.dwBufferLength );
if ( bWave == NULL ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1 ;
}
whdr.lpData = (char *)bWave;

whdr.dwLoops = 0; // 1;
whdr.dwBytesRecorded = 0;
whdr.dwFlags = 0;
whdr.lpNext = NULL;
whdr.dwUser = 0;
whdr.reserved = 0;

ret = waveInOpen( &hWaveIn, WAVE_MAPPER, &wfe, (unsigned long)MyWaveInProc, 0, CALLBACK_NULL );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}

ret = waveInPrepareHeader( hWaveIn, &whdr, sizeof(WAVEHDR) );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}

ret = waveInAddBuffer( hWaveIn, &whdr, sizeof(WAVEHDR) );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}
ret = waveInStart( hWaveIn );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}


Sleep( 70 * 1000  ); // wait 60 sec

// if ( hWaveIn != -1 )
{
ret = waveInStop( hWaveIn );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}
ret = waveInClose( hWaveIn );
if ( ret != MMSYSERR_NOERROR ) {
fprintf( stderr, "ERROR(%d)\n", __LINE__ );
return -1;
}
}

short max, min, cur, prv, thr;
int cnt;

max = min = 0;
prv = cur = 0;
thr = 27000;
cnt = 0;

SYSTEMTIME mytm;


GetLocalTime( &mytm );

for (i=0; i<whdr.dwBufferLength/2; i++ ){
// fprintf( stdout, "%d,\n", (short)bWave[i] );
cur = bWave[i];
// if ( cur  == 0xffffcdcd ) break;
if ( max < cur ) max = cur;
if ( min > cur ) min = cur;

if ( prv < thr ) {
if ( cur >= thr ) cnt++;
}

prv = cur;
}


fprintf( stdout, "%04d/%02d/%02d %02d:%02d:%02d, %d, psV/h,  %d, %d, %d\n",
mytm.wYear, mytm.wMonth, mytm.wDay, mytm.wHour, mytm.wMinute, mytm.wSecond,
(cnt * 1000) / (3100) , cnt , max, min );



free( bWave );
return ret;

}
<numdevs; cur="bWave[i];" cnt="0;" thr="27000;" prv="cur" max="min" whdr.reserved="0;" whdr.dwuser="0;" whdr.lpnext="NULL;" whdr.dwflags="0;" whdr.dwbytesrecorded="0;" whdr.dwloops="0;" whdr.lpdata="(char" bwave="(short" whdr.dwbufferlength="wfe.nAvgBytesPerSec" wfe.nblockalign="wfe.nChannels" wfe.wbitspersample="16" wfe.navgbytespersec="wfe.nSamplesPerSec" wfe.nsamplespersec="32" wfe.nchannels="1;" wfe.wformattag="WAVE_FORMAT_PCM;" micvolume.dwvalue="24348;" mixerdts.padetails="&micVolume;" mixerdts.cbdetails="sizeof" mixerdts.cmultipleitems="0;" mixerdts.cchannels="1;" mixerdts.dwcontrolid="mixerCtrl.dwControlID;" mixerdts.cbstruct="sizeof(" mixerlinectrls.pamxctrl="&mixerCtrl;" mixerlinectrls.cbmxctrl="sizeof" mixerlinectrls.ccontrols="1;" mixerlinectrls.dwcontroltype="MIXERCONTROL_CONTROLTYPE_VOLUME;" mixerlinectrls.dwlineid="mixerLine[idMic].dwLineID;" mixerlinectrls.cbstruct="sizeof" id="%d\n"," mixerline[i].dwcomponenttype="MIXERLINE_COMPONENTTYPE_DST_WAVEIN;" mixerline[i].cbstruct="sizeof(" idmic="-1;" (i="0," isopenedmixer[i]="0;" !="MMSYSERR_NOERROR" ret="mixerOpen("></numdevs;>

このプログラムは、マイク入力の音量を既定値へ設定し、1分間、32kbpsでサンプリング。サンプリンフしたデータからパルスを計数するもの。

| | コメント (0) | トラックバック (0)

2011.06.05

自作ガイガーカウンタ2号機タイプ1(Rev.1)の製作

取り敢えず、試行錯誤の記事では、最終的に完成した情報が分かり難いので、完成したもの毎に、記事を纏める事にした。なお、タイプ0は、オリジナル回路のDC−DCコンバータで昇圧してGM管を駆動する形態。タイプ1は、AC100Vから電源トランスで昇圧してGM管を駆動する形態。タイプ2は、市販システム部品を組み合わせて作る形態と分類。この記事は、タイプ1となり、AC100V電源からトランスで昇圧して、GM管を起動する方式の製作品の紹介。

11060402 11060501

上左写真、GM管の出力パルスは、マイク信号レベルのオーディオ出力仕様(「11060501.mp3」をダウンロード )。上右写真、実際に、モニタスピーカーのマイク入力端子へ接続。下左画像は、回路図。下右画像は、実装図。

11051608_2

11052805_3

内部の様子は、GM管ホルダも、アクリルパイプで、自作しました(下左写真)。下右写真は、ラグ板の実装。ケーブルには、圧着端子経由で接続して、着脱を容易化。

11060404 11060405

MacBook Proへ接続してのパルスの計測は、usbサウンドアダプタを利用。32kbpsモノーラルで録音して、非圧縮のAIFFファイルに保存する事で、プログラムから容易にパルスの計数ができるようになる。下画像は、フリーのMacOSX用録音ソフト(Audacity)の画面。録音時間を1分間に設定して録音。

11060504
上記で録音したAIFFファイルを、下記のプログラムを使って、パルス計数。ガイガーミュラ管CK1026のCMPとμsV/hの換算計数は、このサイトのデータを使って、3100CMP=1μsV/h(推定値)を採用している。


#include "stdafx.h"
#include <windows.h>
#include <mmsystem.h>

struct HEADER_CNK {
	u_int32_t ckID;
	int32_t ckSize;
	u_int32_t formType;
};

struct HEADER_COM {
	u_int32_t ckID;
	int32_t ckSize;
	short numChs;
	u_int32_t numSam;
	short samSize;
	char samRate[10];
};

struct HEADER_SSND {
	u_int32_t ckID;
	int32_t ckSize;
	u_int32_t oft;
	u_int32_t blkSize;
};

main( int argc, char **argv )
{
	int fp;
	int ret;
	struct HEADER_CNK hCnk;
	struct HEADER_COM hCom;
	struct HEADER_SSND hSsnd;
	char sd;
	char sd_prev;
	char sd_prev_prev;
	char sd_max;
	char sd_min;

	double svh = 0.0;

	int cnt = 0;
	sd_max = sd_min = 0;

	fp = open( argv[1], O_RDONLY );
	if (fp == -1) {
		fprintf( stderr, "ERROR(%d), %s\n", __LINE__, argv[1] );
		return -1;
	}

	ret = read( fp, &hCnk, sizeof(hCnk) );
	ret = read( fp, &hCom, sizeof(hCom) );
	ret = read( fp, &hSsnd, sizeof(hSsnd) );
	sd = sd_prev = sd_prev_prev = 0;

	for ( cnt=0;; ) {
		ret = read( fp, &sd, sizeof(sd)  );
		if ( ret < 1 ) break;

		if ( sd > sd_max ) sd_max = sd;
		if ( sd < sd_min ) sd_min = sd;

		if ( sd < 0 ) sd =0;
		if ( (sd > 20 ) && (sd_prev > 0) && (sd_prev_prev == 0) ) 
		{ // 上記、20が閾値になっている
			cnt++;
		} else {
		}
		sd_prev_prev = sd_prev;
		sd_prev = sd;
		
	}
	close( fp );

	svh = (double)cnt / (double)3100.0 ; // CK1026 by http://einstlab.web.fc2.com/geiger/geiger3.html

fprintf( stderr, "%d, %d, %d, cnt = %d, usv/h = %e\n", hSsnd.ckSize, hSsnd.oft , hCom.samSize, cnt, svh ); fprintf( stderr, "Max: %d, Min: %d\n", sd_max, sd_min ); }

実行結果例は、下記。

luna:GM_LOG digi_ponta$ ./a.out 11060501.aiff 
2164, 0, 3392, cnt = 163, usv/h = 5.258065e-02
Max: 58, Min: -12
luna:GM_LOG digi_ponta$ 

0.053μsV/hと出てる。まあ、オーダ的に合ってるかな。なお、一応、実行してみて、もし、閾値が、Minの絶対値より低くなっていたら、Maxを超えない範囲で、閾値の修正が必要。

一応、以上で、紹介を終了。なお、この記事の内容は、製作物の品質保証するものではありませんので、利用には、再三再四、ご注意下さい。

さて、次に行くか(*´д`*)〜з

------

(追記2011/6/11) 外部からのサージノイズで、GM管へ過電圧が発生すると、不安定になることが判明。現在、下記の回路の見直しで、再度、動作テスト中。

 

11051611 11052806

-------

24hの動作テストの結果、残念なことだが、どうもGM管CK1026の挙動が安定しないことが判明(下グラフ)。
11061601
この変になったポイント(3:30am)以降は、GM管内で、定常的な内部放電が起き続きてる感じです。CK1026のデータシートだと、過電圧耐久性もアピールしてるんで、だいぶん劣化しているようだ。まあ、玩具のジャンク部品としては、数時間動作してれば良いとも。後は電源制御(ソリッドステートリレーなど利用)で騙し騙し使うか。現在、使っているこのCK1026は、もう復活しないか、現在、電源を止めて休ませている。CK1026のスペアは後、1本(ロシア製GM管CK1026が駄目なら、サイズが似通っている中国製GM管J305β(DC380V)へ乗り換える予定)。また、回路図は、下図へ見直ししている。
11051612
バリスタに直列に接続した抵抗を省いている。この安全回路は、AC100V側のヒューズで対応。


注)現在、中国製GM管J305βγへ乗り換えて、動作確認中です。この変更後の回路は、上記のものを、少々、改造して、併用しています。(追記:2011年6月19日)

| | コメント (0) | トラックバック (1)

2011.05.08

GWのガイガーカウンタ自作チャレンジ(2台目) アーカイブ

以下、2011年のGW中に行ったガイガーカウンタの自作の記録。1台目は、チェルノブイリ原発事故のときに作りましたが、回路設計が甘く、余り精度が良くないので、GM管も手に入ったので、2台目を作る事にしました。

また、与えられた回路図通りに作るキットを使う電子工作とは別に、手に入った部品で、臨機応変かつアドホックに回路を構築して行くRPG的な右往左往のあるサバイバルな電子工作っていうのも、楽しいこと。以下、日割りで、製作記事を掲載してます。

注) 申し訳ないのですが、以下の回路図で、3倍圧回路のダイオードの3本の極性は逆に記載されてます。ご注意下さい。この記事の最後に、正しい回路図を掲載致します。


【2011年4月29日】

 今日は、千石電商に出現したガイガーミュラー(GM)管(RAYTHEON社製CK1026)をゲットー。これは、もう、生産してないデットストックとのこと。

11042903 11042904

 あと、千石電商で、DSO nano v2(下写真)もゲット。これで、GM管の信号をキャプチャだね。DC900Vの電源供給をどうするかだ。

11042905


【2011年4月30日】

 昨日買ったガイガーミュラー管(CK1026)を駆動する電源回路(予定仕様:入力DC6V/出力DC900V)の部品の一部をゲット。

11043005
 パワーFET(30V/0.0040-0.0050Ω)、整流用ダイオード(1500V/1A/400nsec)と、DSO nano v2用のmicro SDメモリ(互換性未確認)。パワーFETは2SK3142と2SK2894の2種類買ってみた。ダイオードは、できれば、100nsecが良い。後、必 要な部品は、CMOSロジックIC、イグニッショントランス(ストロボ用でいいかな)、耐圧1500Vのコンデンサ類など。


【2011年5月1日】

 今日は、引き続き、アキバで、部品を探索。

11050102 11050101

 予定の回路図は、右上画像だが、まだ、検証してないので、試作して確認する予定。あと、組み立てには、イグニッション・トランスが必要だが、店頭在庫が無 いようなので、代替部品を探さねば。まあ、趣味の電子工作なので、アキバで買える部品でのみ作るろう。上の回路図は、パクってきたけど、チェルノブイリ原 発事故のときに作った1号機は、パワーFETの代わりにパワートランジスタを使っているところを除いては、ほぼ同じ回路。


【2011年5月2日】

 今日は、イグニッション・トランス以外の部品をゲットして、一次側の発信器とトランスのドライバまでの動作確認をしてみた。

11050202 11050201

 知人から周波数をもっと上げても良いのではという助言を受け、前の回路図のパラメータは少々、変更して、発信器の抵抗値は、1MΩとして、キャパシティ値を、470pFにしている。この変更で、周波数が、約7KHz になってます(右写真のオシロの波形)。まだ、イグニッション・トランスは、まだ無いので、ダミーで抵抗を、パワーFETの負荷に入れて計ってます。これ により、予定の回路図は、修正がかかって、、、

11050105
 こんな感じ。ACアダプタの出力電圧は、計ってみると、約6.2Vだったので、47Ωの抵抗器の値の調整が必要になると思う。次は、トランスを、どうにかせんと、、、、


【2011年5月3日】

      
 今日は、トランス探し。取り敢えず、イグニッション・トランスが見つからないので、耐圧に問題がある可能性があるが、電源トランスを昇圧に使うことに決めて、1:100の巻数比のあるものをゲットして、お試し。

11050301 11050302

 この電源トランスの採用で回路図は、発信器の周波数を下げ、波形整形回路も外し、、、、

11050106 

 こんな感じ。明日、2W(余裕もって4Wにしとうこうか)の抵抗器を買ってこなければ、1Wだと、かなり熱くなる。保護回路は、面倒いので、100V未満のバリスタを入れてみる。なお、GM管からの信号は、データシートに依ると、12V以下となっている。

 あと、DSP nano v2の使用感。ボタンが今ひとつ、押し難い感。少し出っぱりが欲しい。まあ、何か貼っておくか。


【2011年5月4日】

 どうも、必要な電圧まで、上がらない感。出力パワーも足りてない感。三倍圧回路には、やはり、正負対象の波形が必要。回路図を更に見直し。明日、足りない 部品を買って、更にチャレンジ。よく考えると、いっぺんにDC900Vを作らず、DC450Vの回路を2つ作って、2つを直結する方が、楽かな。でも、取 り敢えず、今までの路線で行くところまで行こう(^_^;A。
11050401
明日、試す回路図は、、、、
11050107
 こんな感じ。昨日、ゲットした電源トランスには、7V-8V-9Vと1V間隔が2つあるので、8Vをセンタにして、7Vと9Vへ半相ずらした信号を送るようにしてみる。これで、出力波形は、正負で対象になって、倍圧回路が予定通りに動作するはず。


【2011年5月5日】

 今日は、回路図を見直して、再実験。

11050501 11050108

 なんとか、GM管からの信号がオシロから見えるようになってきた。あとは、なんとか、電気を食わないようにする工夫をせなば。


【2011年5月6日】

 今日は、GM管の出力信号の記録方法を変更。DSO nano v2を予定していたが、AS-ISの機能だと、ロガーとして使えない事判明。そこで、何か、身近なもので、ロガーをということで、パソコンの録音機能を利用することに、これであれば、何時間でも記録できる。

11050601 11050109

 そもそも、ガイガーカウンタのイメージは、測定器からカリガリなる様なイメージで、線量も、数を数えられれば、事が済む。課題は、パソコンの録音機能へ渡す信号は、Max1Vにすることと、サンプリング周波数の周期より長いパルス幅になるようにすること。DSC nano v2で、パルス幅を、計ってみると、400μsec前後(上左写真)あるみたいなので、そのまま、行けそうだ。あとは、電圧の調整。回路図を見直した(上右画像)。


【2011年5月7日】

 やっと、GM管から、パソコンまで、回路的につながりました。GM管の出力信号も、なんとか記録されることも確認できました。これで、秋葉原のパーツショップの商品(電子部品類)のみで、ガイガーカウンタが作れることも確認できた。

11050702 11050701

 なお、出力パルスの録音アプリは、フリーウェアAudacity(MacOSX版)を使って、32KHzサンプリングで、非圧縮signed 8bit AIFFファイルに書き出してます。このデータから、パルスの数を自作プログラム(下記)で、計数したところ、通常ケースは、7CPM(換算 0.058μsV/h)、マントルを付けたケースは、52CPM(換算0.433μsV/h)となりました。オーダ的には、SDM2000Uと同じだった ので、出来はまあまあかな。 GM管の出力パルスに、細いのと太いのがあるのが分かったが、細いのは、ノイズ(音として多めにバリバリ鳴ってる)かしら? しかし、GWのほとんどを費やしてしましった(T^T)ウック! あとは、定時定点観測用のブラシュアプだが、これは、後日、やろう。回路図は、昨日と同じ、、、、

11050110

 こんな感じだが、幾つかの電子部品(電源トランスなど)は、定格以上で使用しているので、要注意です。47Ω/5Wが意外に熱くなっている。現状の回路 ベースでの改善の方向性としては、測定するときだけ、発信器を稼働させて、当該抵抗器の発熱時間(連続最長数分間ぐらい)を短くするとかな。


【AIFFファイルからパルスカウントプログラム】 (MacOSX 10.6.7/XCODE)

//
// 入力ファイルが1分間分で、32KHzサンプリングで、
// 非圧縮signed 8bit AIFF形式という前提のプログラムです。
// また、電圧が低過ぎるパルスは、回路の仕様上無いはずなので、
// ノイズとして、カウントしません。
//
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>

struct HEADER_CNK {
    u_int32_t ckID;
    int32_t ckSize;
    u_int32_t formType;
};

struct HEADER_COM {
    u_int32_t ckID;
    int32_t ckSize;
    short numChs;
    u_int32_t numSam;
    short samSize;
    char samRate[10];
};

struct HEADER_SSND {
    u_int32_t ckID;
    int32_t ckSize;
    u_int32_t oft;
    u_int32_t blkSize;
};

main( int argc, char **argv )
{
    int fp;
    int ret;
    struct HEADER_CNK hCnk;
    struct HEADER_COM hCom;
    struct HEADER_SSND hSsnd;
    char sd;
    char sd_prev;
    char sd_prev_prev;
    double svh = 0.0;
    int cnt = 0;

    fp = open( argv[1], O_RDONLY );
    if (fp == -1) {
        fprintf( stderr, "ERROR(%d), %s\n", __LINE__, argv[1] );
        return -1;
    }

    ret = read( fp, &hCnk, sizeof(hCnk) );
    ret = read( fp, &hCom, sizeof(hCom) );
    ret = read( fp, &hSsnd, sizeof(hSsnd) );

    for ( cnt=0, sd = sd_prev = sd_prev_prev = 0; ; ) {
        ret = read( fp, &sd, sizeof(sd)  );
        if ( ret < 1 ) break;
        if ( sd < 0 ) sd =0;
        if ( (sd > 0) && (sd_prev > 0) && (sd_prev_prev == 0) ) cnt++;
        sd_prev_prev = sd_prev;
        sd_prev = sd;
       
    }
    close( fp );

// CPMからμsV/hへの変換は、0.00833をかけ算すれば良いみたいだ
// 但し、この係数は、この特定の条件での実験でのみ、有効な値。

    svh = 0.00833 * (double)cnt ;

    fprintf( stderr, "%d, %d, %d, count = %d, sv/h = %e\n",
        hSsnd.ckSize, hSsnd.oft , hCom.samSize, cnt, svh );
}

【2011年5月8日】

 取り敢えず、自作ガイガーカウンタに、電源制御を付ける場合の回路図を書いてみた(但し未検証)。
11050801

トランスのドライブ側には、パルス幅を制限する回路を付けているので、発信を止めるだけで、良いはずだ。


【まとめ】

  • アキバでも、必ずしも、予定している電子部品が手に入るとは限らない。代用品も、知恵を絞ろう。
  • 携帯型スロレージオシロDSO nano v2は、便利。
  • 上記の電子回路は、目的の動作を実現しているけれど、良い設計とは言えません。もっと、適切な電子部品と出会えたり、手に入れば、もっと良い電子回路になる可能性が、十分あります。この回路では、昇圧トランスがもっとも重要な部品で、この選定でほぼ、周りが決まます。今、知人から、別のトランスの使用の助言をいただきましたので、その採用で、設計変更を予定してます。
  • 今回、2台目の自作で、新たに得た知見としては、検出結果の記録に専用のレコーダは不要ということ。一般的なボイスレコーダを使う事で、長時間の記録が可能となること。これを実際に、パソコンのUSBサウンド変換アダプタを使用して、実際に、やってみたこと。

以上、GW終了!


【正誤訂正】

上記の回路図には、ダイオードの極性に誤りがありました。下の回路図が、現在の実態を表す回路図となっています。

11050901


【補足】

一応、以上の記事の内容を理解して上で、24h使用など、もっと真っ当に使用すること、を意識したエンハンスの方向性は、下記があるだろう。なお、言うまでもない事ですが、実験でなく、真面目な使用の方は、完成した製品をご購入して、お使い下さい。

  • 使用している電圧以上の定格のトランスの採用して、回路設計を見直す。この手のトランスとしては、真空管用の電源トランスであれば、使える物がある。但し、50Hz前後での利用が前提になる。例えば、ノグチトランスの電源トランスPM-50010M(0-100-110V to 0-300-400-500V(10mA))。
    多分、DC-DCコンバータとして使用するの難しく、AC100V(実効値)から、AC300Vへ昇圧すれば、交流の最大値は、1.4倍なので、2倍圧回路を入れれば、約2.82倍のDC846Vが得られる計算(下回路図)。AC100V側には、0.5Aのヒューズもお忘れなく。もしくは、AC400Vを2倍圧で使って、分圧してDC900Vにして、使うなど。但し、計測用のオペアンプは、-12V(0.2A)電源で駆動する必要があるが、その電源は、どうするかは、未検討。11051601
    もう少し考えて、GM管は、+846V側で使うことに変更して、
    11051604
    オペアンプあり版
    11051608
    オペアンプなし版

    なお、上右回路図を、2011年6月4日に製作完成している(下画像)。

    11060402 11052805_2

    上記はAC100V電源専用の据え置きタイプになる。定点観測用途では、むしろ、バッテリー使う機種よりも使い易いかと思う。

    一応、DC9Vから、DC900Vへ昇圧する下回路(フライバックを利用)も試して、DC900Vの出力を確認している。しかしながら、これも、結局、ノグチトランスの耐圧500Vを超えた900Vを出力する使い方になるので、余り、お薦めできない。

    11051501

    あと、二次側のコンデンサの直列接続の保護回路は、現在、下回路図で考えている。
    11051507
    上記の保護回路付けると、下記の条件で、出力電圧が、DC900Vになった(追記2011年5月21日)。
    • 二次側の負荷抵抗: 60MΩ+6KΩ
    • 発信周期: 600μsec~800μsec
    • Hレベル時間(解放時間): 上記の内数で、30μsec
    • 一次側の電源の47Ωの端子電圧が、1.77V(37.7mA)となった。前回は、3.2V(68.1mA)。どうもノグチトランスはコイル巻数が多過ぎるようだ。

  • DC2000VまでのDC-DCコンバータモジュールも存在するので、出来合いのものを使うのもの良い。例えば、Bellnix MHV12-1.0K2000Pなど。これは、入力が12V前後で、出力電圧は、DC1000V(Max2mA)まで可変で設定できる。但し、この価格は、高めで、税別27K円弱。アキバだと、株式会社晴恒で扱っているが、取り寄せになる。11052002 なお、秋葉原では、株式会社晴恒が取扱店(上写真)。これを使ったときの回路図案(下画像)。 11052101_2
  • ガイガーミュラー管も内包するガスの種類で、扱い方次第で寿命がだいぶん異なるようだ。故障時の交換部品の入手も考えると、デッドストックでない製品の利用が、無難だろう。なお、この記事で取り上げたガイガーミュラ管は、定格以上の電圧をかけて使うと寿命がだいぶん短くなるとか。
  • あと、トランスのドライブに関しては、電流を流し込むエッジよりも、電流を切るエッジの方が、巻き数比に近い昇圧が得られるので、上記の初期の回路図(インターネットの検索結果)で、保護ダイオードが入っているのは、昇圧の効率を悪くしている。トランスのドライブに使用するFETの耐圧を大きめにして、ダイオードを取る方が良い。

以上

| | コメント (2) | トラックバック (1)