電子工作ではおなじみのSparkFunが出しているガイガーカウンター、SEN-11345。すごく気になる…。
コンパクトなガイガーミュラー菅には、LND712を使用している上、ArduinoでおなじみのATMega328を搭載しているんですよね。以下のArduino Pro Miniと動作周波数も同じです。
というか、このArduino Pro Mini、以前庭先の自動水やり機を作った時の余りが手元にあるんですよね。
でもって、Geiger Counter用コードがGithubにpushされていると。
ハード構成は色々違うはずですが、このGeiger Counter用コードがArduino Pro Miniで動くのか試してみたくなりました。
OSXでMakeする
Arduinoのソフトウェアは基本的にArduino IDEで開発するので、Geiger Counterのように素でMakeする環境はちょっとハードル上がります。
個人的には、マウスでボタン押してソフトウェア書き込みするより、全ての作業がコマンドラインで完結している方がやりやすい。
でもOSXのターミナルでMakeするには、色々と下準備が必要です。
- Arduino IDEをインストールする
- avrコマンドへのパスを通す
- Arduino Pro Mini上で動作させるためのMakefile修正
- cpm単位で値を返すようにGeiger Counterのソースコードを修正する
これで、OSX上でMakeできる上、make program
コマンドでボードへのソフトウェア書き込みもできてしまいます。
以下、詳細です。
Arduino IDEをインストールする
リンク先からインストーラをダウンロードして、インストールしてください。
avrコマンドへのパスを通す
Makeでavr-gccやavrdudeコマンドが必要になるので、PATHが通ってないといけません。
以下のようにします。
$ export PATH=/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin:${PATH}
永続的にパス通しておきたいなら.bash_profile辺りに追記しておきます。
$ echo 'export PATH=/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin:${PATH}' >> ~/.bash_profile
パスがちゃんと通れば、以下のようにavrdudeコマンドが実行できるはず。
$ avrdude -C /Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf -c ?
Valid programmers are:
2232HIO = FT2232H based generic programmer
4232h = FT4232H based generic programmer
arduino = Arduino
arduino-ft232r = Arduino: FT232R connected to ISP
arduinoisp =
avr109 = Atmel AppNote AVR109 Boot Loader
avr910 = Atmel Low Cost Serial Programmer
avr911 = Atmel AppNote AVR911 AVROSP
avrftdi = FT2232D based generic programmer
avrisp = Atmel AVR ISP
avrisp2 = Atmel AVR ISP mkII
...
Arduino Pro Mini上で動作させるためのMakefile修正
以下のようにします。
--- a/firmware/geiger_counter_board/Makefile
+++ b/firmware/geiger_counter_board/Makefile
@@ -197,16 +197,20 @@ LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#
# Type: avrdude -c ?
# to get a full listing.
-AVRDUDE_PROGRAMMER = stk500v2
+AVRDUDE_PROGRAMMER = arduino
+#AVRDUDE_PROGRAMMER = avrisp
#AVRDUDE_PROGRAMMER = ponyser
# com1 = serial port. Use lpt1 to connect to parallel port.
#AVRDUDE_PORT = lpt1
-AVRDUDE_PORT = COM3
+AVRDUDE_PORT = /dev/tty.usbserial-A9KZJ9DL
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+AVRDUDE_CONF = -C /Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf
+AVRDUDE_BAUD = -b 57600
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
@@ -382,7 +386,7 @@ gccversion :
# Program the device.
program: $(TARGET).hex $(TARGET).eep
- $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+ $(AVRDUDE) $(AVRDUDE_BAUD) $(AVRDUDE_CONF) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
AVRDUDE_PORTは使用するPro Miniによって変わるので、適宜変更してください。
AVRDUDE_PROGRAMMERはavrispでも正常に書き込みできました。
ちなみに、このavrdude(AVR Downloader/UploaDEr)コマンド、詳細なオプション情報はリンク先のdownload pageからマニュアルがダウンロードできるので、もっと詳細が知りたくなったらこちらを参照してください。
cpm単位で値を返すようにGeiger Counterのソースコードを修正する
Githubに公開されているGeiger Counter用コードは以下のように、INT0割り込み回数を1秒毎にprintfするようになっています。
ISR(INT0_vect) {
i++;
cbi(PORTC, STATUS_LED);
}
ISR(TIMER1_OVF_vect) {
TCNT1 = 34000; //(256/8MHz)*(65536bits-34000)~=1.009s
printf("counts per second: %ld ?r", i);
i=0;
}
int main(void) {
ioinit(); //Setup IO pins and defaults
delay_ms(1200); //wait to settle
while(1) {
sbi(PORTC, STATUS_LED);
delay_ms(30);
}
cli();
}
void ioinit (void) {
...
//load timer with a value to optimize for 1 second, (256/8MHz)*(65536bits-34000)~=1.009s
TCNT1 = 34000;
sei(); //turn on global interrupts
}
ガイガーミュラー菅に放射線が通ると割り込み発生、ってことなんでしょうね。
さらにTimer1のTCNT1設定方法をCOUNTERS ON THE ATmega168/328で見てみると、コードのコメントにある通り、1クロック毎にデクリメントしてちょうど1秒になるように設定してやると、1秒タイマーの出来上がり。
Timer/Counter Register (stores the counter value) Can be accessed as TCNT1.
The Control Logic unit in counter1 has the ability to increment, decrement or clear(reset) the TCNT1 register.
これをcpm単位で返せるように修正すると、以下のようになります。…間違ってないよね?
ISR(INT0_vect) {
++cps;
cbi(PORTC, STATUS_LED);
}
ISR(TIMER1_OVF_vect) {
TCNT1 = TCNT1_1SEC;
//printf("%lu ?r", sec);
if (sec < 60) {
cpm += cps;
++sec;
}
cps = 0;
}
int main(void) {
ioinit(); //Setup IO pins and defaults
delay_ms(1200); //wait to settle
while(1) {
sbi(PORTC, STATUS_LED);
delay_ms(30);
if (sec >= 60) {
//printf("cpm:%lu ?r", cpm);
printf("cpm:%lu ?n", cpm);
cpm = 0;
sec = 0;
}
}
cli(); // Disables all interrupts by clearing the global interrupt mask.
}
可能なかぎりISR(割り込み処理)内の処理は軽く、単純な四則演算だけで処理して、少なくとも返すcpmの値を計測する時間に差が発生しないようにしたつもり。
これでmakeしたコードをArduino Pro Miniに書き込んで、
$ make
$ make program
screenコマンドでArduino Pro Miniが返す値を表示してやると、
$ screen /dev/tty.usbserial-A9KZJ9DL 19200
こうなります。
cpm:3000
cpm:3051
cpm:2989
まぁ、ガイガーミュラー菅がないので、適当な変な値が表示されるだけですが。
結局何がしたいのか?
SEN-11345を使って定点観測所を作りたいんですよね。
行政が作る定点観測所は、どうも信用ならない。あるがままの値を計測するのではなく、計測所周りを綺麗に掃除して綺麗な値を公表したいだけに思えるので。
こんな感じでその日その瞬間の空間線量値をつぶやいたり、
バッテリ電圧がかなり低下しています。
現在22.34[V]ですので、PCサーバ等の電源を落とします。
2016年8月28日11時26分に取得したデータを元にしています。— solar_monitor (@mybot_athome) 2016年8月28日
地点毎の線量をグラフ化して公開したりしたいですね。
Safecast APIでの線量値のPost方法もわかったので、iOSアプリでのマップ情報も参照できるようになる。…予定です。