SparkFunのSEN-11345をcpm単位で空間線量を返すように修正してみる。ついでに、OSXでmakeする環境整備も。

電子工作ではおなじみの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するには、色々と下準備が必要です。

  1. Arduino IDEをインストールする
  2. avrコマンドへのパスを通す
  3. Arduino Pro Mini上で動作させるためのMakefile修正
  4. 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を使って定点観測所を作りたいんですよね。

行政が作る定点観測所は、どうも信用ならない。あるがままの値を計測するのではなく、計測所周りを綺麗に掃除して綺麗な値を公表したいだけに思えるので。

こんな感じでその日その瞬間の空間線量値をつぶやいたり、

地点毎の線量をグラフ化して公開したりしたいですね。

Safecast APIでの線量値のPost方法もわかったので、iOSアプリでのマップ情報も参照できるようになる。…予定です。

スポンサーリンク
  • このエントリーをはてなブックマークに追加