「写ルンです」に使用されているトランスは、参考資料から約1:350 の巻き線比のため、1次側に電圧調整回路を入れて、2次側で700V程度 になるようにしました。
通常動作
・更新時間 10秒
・放射線検出時 → LED Red点灯 / ブザー x 1回
・放射線検出が定常状態 → LED Green 5secおきに点灯
・放射線検出がやや多い → LED Green 3secおきに点灯
・放射線検出が多い → LED Green 1secおきに点灯
【ソースコード】
【main.c】
//───────────────────────────────────
// Includeの定義
//───────────────────────────────────
#include <pic.h>
#include "port.h"
#include "timer.h"
#include "trigger.h"
#include "led.h"
//───────────────────────────────────
// Define User Memory
//───────────────────────────────────
static unsigned char Timer100ms;
static unsigned char Timer10ms;
static unsigned char Flag10ms;
static unsigned char Flag1ms;
static unsigned char FlagDet = 0;
static unsigned char TimerDet = 0;
static unsigned int CountDet = 0;
static unsigned char TimerBuzz = 0;
//───────────────────────────────────
// Here be interrupt function
// - the name is unimportant.
//───────────────────────────────────
static void interrupt isr(void)
{
if( RA1 == 0 )
{
FlagDet = 1; // 放射能検出
}
INTF = 0; // clear the interrupt
if(T0IF) // timer interrupt
{
Flag1ms = 1;
if( Timer10ms != 0 )
{
Timer10ms --;
}
else
{
Flag10ms = 1;
Timer10ms = 9;
}
T0IF = 0; // clear the interrupt flag
}
}
//───────────────────────────────────
// Main
//───────────────────────────────────
void main(void)
{
init_port();
init_trigger();
init_led();
init_timer0();
GIE = 1; // Enable interrupts
TimerBuzz = 50;
for(;;){
// 1msec 処理
if( Flag1ms )
{
Flag1ms = 0;
trigger_main();
led_timer_1ms();
led_main();
}
// 10msec 処理
if( Flag10ms )
{
Flag10ms = 0;
Timer100ms ++;
if( TimerBuzz == 0 )
{
PortBuzzOff;
PortRedOff;
}
else
{
PortBuzzOn;
PortRedOn;
TimerBuzz --;
}
if( FlagDet == 1) // 放射能検出
{
FlagDet = 0;
if( TimerBuzz == 0 )
{
TimerBuzz = 5;
}
if( CountDet < 50000 )
{
CountDet ++;
}
else
{
led_set_mode(LED_MODE_HIGH);
}
}
}
// 100msec 処理
if( Timer100ms >= 10 )
{
Timer100ms = 0;
// 10secおきに更新
TimerDet ++;
if( TimerDet > 10 )
{
if( CountDet > 10 )
{
led_set_mode(LED_MODE_HIGH);
}
else
{
if( CountDet > 1 )
{
led_set_mode(LED_MODE_MIDDLE);
}
else
{
led_set_mode(LED_MODE_NORMAL);
}
}
CountDet = 0;
TimerDet = 0;
}
}
}
}
【port.c】
#include <pic.h>
#include "port.h"
void init_port(void)
{
WPUA = 0b00001000; // Pullup
TRISA = 0b00001010; // 1:入力、0:出力設定
ANSELA = 0b00000000; // A/D 禁止
PORTA = 0b00110001;
OPTION_REG &= 0b01111111;// Pullup許可
CLKOUT = 1; // CLKOUT function is disabled
INTE = 1;
IOCAN1 = 1; // INTERRUPT-ON-CHANGE PORTA NEGATIVE EDGE REGISTER
}
【trigger.c】
#include <pic.h>
#include "port.h"
#include "trigger.h"
static char TrgInterval = 0;
//───────────────────────────────────
// initialize trigger
//───────────────────────────────────
void init_trigger(void)
{
PortTrigOff;
}
//───────────────────────────────────
// Trigger main (2msec)
//───────────────────────────────────
void trigger_main(void)
{
TrgInterval ++;
if( TrgInterval >= 40 ) // 40msec (25Hz)
{
PortTrigOn;
TrgInterval = 0;
PortTrigOff;
}
}
【led.c】
#include <pic.h>
#include "led.h"
#include "port.h"
static LED_MODE mode = LED_MODE_NORMAL;
static long TimerGreen = 3000;
static char FlagGreen = 0;
//───────────────────────────────────
// initialize LED
//───────────────────────────────────
void init_led(void)
{
PortGrnOff;
PortRedOff;
}
//───────────────────────────────────
// Set mode
//───────────────────────────────────
void led_set_mode(LED_MODE value)
{
mode = value;
FlagGreen = 1;
TimerGreen = 20;
PortGrnOn;
}
//───────────────────────────────────
// LED 1msec Timer
//───────────────────────────────────
void led_timer_1ms(void)
{
if( TimerGreen > 0 )
{
TimerGreen --;
}
}
//───────────────────────────────────
// LED main
//───────────────────────────────────
void led_main(void)
{
if( TimerGreen == 0 )
{
if( FlagGreen == 0 )
{
FlagGreen = 1;
TimerGreen = 20;
PortGrnOn;
}
else
{
FlagGreen = 0;
PortGrnOff;
switch( mode )
{
case LED_MODE_NORMAL:
TimerGreen = 5000;
break;
case LED_MODE_MIDDLE:
TimerGreen = 3000;
break;
case LED_MODE_HIGH:
TimerGreen = 1000;
}
}
}
}
【timer.c】
#include <pic.h>
#include "timer.h"
//───────────────────────────────────
// initialize timer 0 (1msec)
//───────────────────────────────────
void init_timer0(void)
{
OSCCON = 0b01100010; // PLL Disable / 2MHz Internal clock
PS2 = 0; // Clk 1/2
PS1 = 0;
PS0 = 0;
PSA = 0;
TMR0CS = 0; // select internal clock
TMR0IE = 1; // enable timer interrupt
}
【port.h】
#ifndef _PORT_H_
#define _PORT_H_
/**********************************************
マクロ定義
**********************************************/
#define PortBuzzOn RA0 = 0
#define PortBuzzOff RA0 = 1
#define PortTrigOn RA2 = 1
#define PortTrigOff RA2 = 0
#define PortRedOn RA5 = 0
#define PortRedOff RA5 = 1
#define PortGrnOn RA4 = 0
#define PortGrnOff RA4 = 1
/**********************************************
外部参照関数
**********************************************/
void init_port(void);
#endif
【led.h】
#ifndef _LED_H_
#define _LED_H_
/**********************************************
定数/型定義
**********************************************/
typedef enum
{
LED_MODE_NORMAL, // 定常状態
LED_MODE_MIDDLE, // 中くらい
LED_MODE_HIGH // 高い
} LED_MODE;
/**********************************************
外部参照関数
**********************************************/
void init_led(void);
void led_timer_1ms(void);
void led_main(void);
void led_set_mode(LED_MODE value);
#endif
【timer.h】
#ifndef _TIMER_H_
#define _TIMER_H_
/**********************************************
外部参照関数
**********************************************/
void init_timer0(void);
#endif
【trigger.h】
#ifndef _TRIGGER_H_
#define _TRIGGER_H_
/**********************************************
外部参照関数
**********************************************/
void init_trigger(void);
void trigger_main(void);
#endif
【ビルド時の注意点】
MPLABでビルドする際には、「Configuration bits」 ダイアログ(下記)で
CLKIN を I/O に設定しないと RA4 端子が I/O として使用できません。
また、MCLR端子を I/O として使用する場合は MLRE の設定と共に
下記のように LVP を禁止に設定しておく必要があります。
この説明は、ユーザーズマニュアル(50ページ)にも記載されています。
MCLRE: RA3/MCLR/VPP Pin Function Select bit
If LVP bit = 1:
This bit is ignored.
If LVP bit = 0:
1 = MCLR/VPP pin function is MCLR; Weak pull-up enabled.
0 = MCLR/VPP pin function is digital input
【HEXコード】
下記URLよりダウンロード可能です。
http://hmmk.co.jp/sample/GM_Counter.hex
【動作検証】
1分間に1回程度検出しているようですが、正常に動作しているか不明です。
回路およびプログラム変更で、1分間に5回程度検出しています。
下記動画は放射能レンズを近づけた実験です。
【その他】
たまたま見かけた「Software Design (ソフトウェア デザイン) 2011年 07月号」にArduinoで作るガイガーカウンタの記事が載っていました。
5ページにわたってわかりやすく書かれていましたし、回路図も載っていました。