2015年1月10日土曜日

SparkFun Geiger CounterのArduino化

先日設計上の不具合を何とか改修する事が出来たSparkFunのGeiger Counter SEN-09848だが、software(firmware)も製品購入時には非常に単純な物しか入っておらず、時間線量の算出・表示すら出来ない。

折角直したので、これを機会にいろいろprogramを書いて遊んでみたいので、ひとまずArduino化することにした。

ICSP pinheadersの取り付け

本品にはご覧のようにprocessorとしてATmega328P(flat package)、USB-TTL変換としてFT232RLが使われている。買った状態ではICSP端子にpin headersはついていないので、まず下図のように取り付けた。1番pinには細い線でmarkingされている。
ATmega328Pには外部発振子が付いていないので、内部RC発振を利用しているようだ。

さて、ICSP端子からbootloaderやfirmwareを書き込むには、ISP用のprogrammerが必要である。専用で安価なAVRISP mkII3,200円@秋月電子)をお勧めしたいが、持っていなければ別のArduinoにISP用のsketch(Arduino IDEに付属)を入れてprogrammerにする方法や、FT232Rから必要な端子が出ていればFT232R Bit Bangingという方法でprogrammingする事も出来る。詳しいやり方は他所で解説されているので、「Arduino ブートローダ 書き込み」等で検索してみてください。

本品はFT232RLを使用してはいるものの、Bit Bangingに必要なCTS、DSR、DCD、RIが結線されていないので、本品のFT232RLを使ってのBit Bangingは出来ないと考えた方が良いだろう。やるならCTS、DSR、DCD、RI端子が出ている別のFT232R搭載Arduino等を持ってきて、本品のICSP端子に接続して使う形になる。

なおICSP端子にはVCC/GND線も有りますが、AVRISP mkIIはここからtargetに電源を供給しません。逆にtargetが通電しているかどうかの検出に使っているようです。従って、targetには別途(本品の場合USB端子から)電源を供給して下さい。

Fuseの設定

早速programmerを繋いで、SEN-09848の購入時のfuseの状態を調べてみたところ、次のようだった。

 Extended   0xF8 (0x00) 
 High    0xDF 
 Low   0xE2 
なお拡張byteの3~7 bit目は使用されていないので、そこが1と見れば0xF8、0ならば0x00という事である。書き込みsoftwareにより、未使用bitsの表現が異なっている事がある。
AVR processorのfusesは「ONが0、OFFが1」と、通常とは逆になっているので、設定変更時十分注意しよう。間違ったfuse設定を書き込んでしまうと、AVR processorが2度と使用できなくなる恐れがある。

こちらの便利なsiteで上記bitsを解釈すると、fuseの状態は次の様になっていることが判る。
  • 内蔵 RC回路 8MHz 発振、起動遅延時間 65msec
  • Boot用flash領域 256words、Boot Reset Vector OFF
  • 電圧降下検出 VCC=4.3V (*)
(*) なおここの拡張byteにある電圧降下検出(BODLEVEL)のbitsは間違っていて、本来有り得ない組み合わせになっている。
さて、bootloaderを使用するため、fusesを書き換えてみよう。筆者はAtmel Studio 6.2(旧AVR Studio)とAVRISP mkIIの組み合わせで行った。
Optibootを使用する予定なので、BOOTSZ = 256W(512bytes)のままとし、clockの設定(SUT_CKSEL)も変更しない。変更するのは、下記2箇所のみとした。
  • BOOTRSTをON(0)に(bootloaderを使用するのだから当然)
  • BODLEVELを2.7Vに(変更しなくても良いが、正しい値にしておく。他の値でも良い)
他のbootloaderを使用する場合は、sizeに合わせてBOOTSZを調節して下さい。そのbootloaderを使用しているboards.txtの項目を参照し、fuseの設定やupload.maximum_sizeの値からbootloaderのsizeが推測できます。(32768や16384といった値からupload.maximum_sizeを引いてみます。)

先程も述べたように、絶対に間違ったfuse設定を書き込まない事。特に、外部発振の設定にしてしまうと、Ceralockや水晶発振子を(flat packageに!)外付しないと動作しなくなり、programmerによるaccessも出来なくなります。またRSTDISBL、SPIENも絶対に変更してはいけません

間違いが無い事をしっかり確認できたら、上記fusesの値を書き込み(Programし)ます。

Bootloaderの書き込み

Fusesの次はいよいよbootloader本体の書き込みです。まず、Optibootの開発siteから最新版v5.0aをdownloadしてきます。Desktopに解凍し、その中の「optiboot_atmega328.hex」というのをFlashに書き込み(Programし)ます。
以上で書き込み作業は終了です。ProgrammerからSparkFun Geiger Counterを取り外します。

Arduino IDEの設定

Arduino IDEの個人用Sketchbook location(Preferencesを見ると判ります。通常はDocuments folderのArduino配下)に「hardware」というsub folderが無ければ作って、その下にこのzip fileを解凍して出来た「SparkFun Geiger Counter」というfolderをそのまま置きます。

中に入っているのはboards.txtだけで、その中身はこれです。
##############################################################
# Sparkfun Geiger Counter w/optiboot
#  ATmega328P, Int RC Osc 8MHz
##############################################################
sfgeigero.name=[Optiboot] Sparkfun Geiger Counter (8MHz Internal)
sfgeigero.upload.protocol=arduino
sfgeigero.upload.maximum_size=32256
sfgeigero.upload.speed=57600
sfgeigero.bootloader.low_fuses=0xE2
sfgeigero.bootloader.high_fuses=0xDE
sfgeigero.bootloader.extended_fuses=0x05
sfgeigero.bootloader.path=optiboot
sfgeigero.bootloader.file=optiboot_atmega328.hex
sfgeigero.bootloader.unlock_bits=0x3F
sfgeigero.bootloader.lock_bits=0x0F
sfgeigero.build.mcu=atmega328p
sfgeigero.build.f_cpu=8000000L
sfgeigero.build.core=arduino:arduino
sfgeigero.build.variant=arduino:standard
##############################################################
この後、Arduino IDEを起動すると、Tools -> Board menuに追加した項目が現れます。

13番pin LEDの追加

さて早速Blink sketchをuploadしてみたいところなのですが、SparkFun Geiger CounterはPB5、つまりArduino 13番pinにLEDが結線されていません。ですが幸い、このpin(PB5)はSPI clock用としてICSP端子に出ていますので、それを利用します。
つまり上図のようになっていますので、SCK pinとGND pinとの間にLED(と抵抗)を入れればOKです。
このようにすればBlink sketchの動作確認が出来る他、13番pin LEDはRESET buttonを押下した時にもbootloaderの動作で点滅するようになっているので、bootloaderが正しく書き込まれているかの確認にも使用出来ます。

Sketchのupload

さていよいよsketchのuploadです。しかしここにちょっと問題があって、筆者の所有しているSparkfun Geiger CounterのSEN-09848というversionにはauto-reset回路が無いのです。後継のSEN-10742SEN-11345(現行)にはauto-reset回路が付いています。

Auto-reset回路というのは、FT232RLのDTR端子から0.1uFを介してATmega328PのRESET端子に結線されているだけなのですが、これを追加するのは両ICsともflat packageのため面倒かつかなり見た目が悪くなります。

そこで筆者は手動resetで我慢することにしました。

ところがこのreset button押下のtimingがかなり微妙で、慣れが必要です。

Arduino bootloaderはresetされると、ごく短時間serial通信を待機します。このtimingに丁度うまくArduino IDEから通信の試行が行われるようにしなければなりません。

まず、通信のやりとりを見えるようにするため、Arduino IDEの「環境設定(Preferences)」で書き込み時の詳細表示を選択します。
コンパイル(compilation)の方は詳細表示にしなくても良いでしょう。

Sketchをuploadしようとすると、「Uploading...」の終盤になって次のような橙色文字の表示が現れます。ここがresetのtimingです。
うまくやるためには「Uploading...」の途中からreset buttonを押したままにして、上の橙色文字が見えたらすかさず指を離して下さい。上図のようにmessage領域を大きく広げておくと見易いです。

成功するとdataのやりとりが行われ、uploadが無事完了します。
これがuploadが成功した時の表示です。またuploadしたsketchに従ってLEDがblinkしていると思います。

Blink sketchのloop内のdelay()値をその都度変更すれば、新しいsketchが動作しているかどうかが判ると思います。またsketch内の「13」pin指定を「A5」に変更する事により、先ほどわざわざ外付したLEDではなく、本体上の「Counter」のLEDをblinkさせる事が出来ます。外付けLEDでの動作が確認できたら、blink sketchをそのように変更し、外付けLEDは外してしまいましょう。

Arduino IDEのserial通信とreset button押下のtimingが合わないとuploadに失敗し、以下の様な表示となります。
stk500_getsync(): not in sync: resp=0x00」というのが通信の同期に失敗した事を示しています。失敗していても、「Thank you.」「Done uploading.」等成功した時と同じような表示も出る事には注意して下さい。

筆者はbaud rateを他に色々変えて試しましたが、何故か57600bps以外では成功していません。また他のOptibootの.hex filesも用いてみましたが、成功したのはこの「optiboot_atmega328.hex」だけでした。

実際のresetのtimingはかなり微妙(体感では200~300msec位の範囲)ですが、慣れればわりと確実にupload出来るようになります。練習して下さい。

現行のArduinoは殆どauto-resetになっているので、通信待機時間を長く取る必要が無くなり、現行のbootloaderではそれが極端に短くなっているようです。本機のような手動reset用には、きっとbootloaderを再compileして待機時間を長く取るようにすれば良いのかもしれませんが、筆者にはまだその方法が判らないところです。

また先も述べたように後継機種であるSEN-10742SEN-11345をお持ちの方は、auto-resetに対応していますので、reset buttonのtimingで苦労することは無い筈です。

他のbootloaderを用いる

Optiboot以外でも実はやってみました。本家TutorialのこちらからBreadboard.zipをdownload、展開し、前述の個人用Sketchbook locationのhardware folder配下に置きます。

Programmerを用いて、fusesとbootloaderをそれぞれ書き込みます。
  • Fuse設定は、Low 0xE2、High 0xDA、Extended 0x05(0xFD)
    • bootloaderのsizeは1024W(2048 bytes)
  • bootloaderはArduino IDEに付属の「ATmegaBOOT_168_atmega328_pro_8MHz.hex
IDEのTools -> Board menuには「ATmega328 on a breadboard (8 MHz internal clock)」という名称で現れます。

試してみたところ、こちらのbootloaderの方がOptibootよりもややtimingに余裕がある感じでした。Optibootでどうしてもtimingが掴めない方にはお勧めかもしれません。なお通信速度はやはり57600bps以外では動作しませんでした。

Arduino化完了!

何とかSparkFun Geiger CounterをArduino IDEで簡単に扱えるように出来ました。

製品版のfirmwareのsourcesはGitHubにあります。取り敢えず、製品に入っていた検知間隔に応じて0と1を出力するだけの非常に単純なfirmware(v12)を、Arduinoのsketchに書き直してみました。
/*
  SparkFun Geiger Counter
  Official v12 firmware on Arduino
  
 created 10 Jan 2015
 by Rin FUKUDA 
 jg1vgx@jarl.com
 */

// Constants
#define LEDPIN A5  // Counter LED (green)

// Variables
volatile long j=0;      // Interval since the last count
volatile long jlast;    // previous interval
byte cbit;     // '0' or '1' for char output on terminal

void setup() { 
  // pin I/O settings
  pinMode(LEDPIN, OUTPUT);
  
  // Interrupts on INT0 (OUT)
  attachInterrupt(0, onCount, RISING);

  //Initialize serial and wait for port to open:
  Serial.begin(9600); 

  // Wait to settle
  delay(1200);
  interrupts();


void loop() { 
  // turn off the LED (HIGH is the voltage level)
  digitalWrite(LEDPIN, HIGH);
  // wait for a short while for counting
  delay(30);
  j++;


void onCount() {
  // blink LED
  digitalWrite(LEDPIN, LOW);
  delay(10);

  // check intervals  
  if(jlast < j) cbit = 0;
  if(jlast > j) cbit = 1;
  
  // send byte char to console
  Serial.print(cbit);
  
  // reset intervals
  jlast = j;
  j = 0;
}
たったこれだけです。こちらにも置きました。Sketchをuploadしたところ、ちゃんとArduino化以前と全く同じ動作で検出~countする事を確認しました。Arduino IDEにはSerial Monitor機能が付いているので、別のsoftwareを起動せずに動作確認が出来、大変便利です。
さらに、dotによる簡易bar graphで時間線量(CPM, counts per minute)をserial出力するsketchを書いてみたのでここに置きます。

2015年1月3日土曜日

SparkFun Geiger Counterの改修

震災の年にback-orderで注文し数ヶ月待って入手してあったSparkFunのSEN-09848というGeiger Counterだが、いざ届いて使おうとする前に、同製品のComments欄で「回路設計に重大な問題があり、そのままで使うと貴重なGeiger管に定格(450~650V)を超える過大な電圧(1,000~1,500V)がかかっている」という事が指摘され、物議を醸していた。

そこではいろいろ回路修正方法が議論されていたが、ともかく修正しない事には使えない代物だという事が判り、少しガッカリするとともに、いつか修正しようとして箱にしまったまま、忙しさに紛れて早3年以上過ぎてしまった。

しかし気になって仕方がなかったので、この正月休みに遂にその修復を試みてみる事にした。

SparkFun Geiger Counterの世代

  
SparkFunのGeiger Counterは原発事故後に当然ながら注目を浴びたが、これから述べる不具合をusersから指摘されたためその後改版を繰り返している。当方が入手したのは震災当時販売されていたSEN-09848という一番左の物である。

SEN-10742では、見て判る通り真ん中左の高圧印加用のswitchがより耐圧のある適正な物に変更されたが、過大電圧の問題や、後に述べる検出回路の誤りはここでも修正されていない。

現行品のSEN-11345になり、高圧回路には本来あるべき定電圧回路が挿入され(右端に新しく増えた黒い部品がZener diodes)、また検出回路がanode検出からcathode検出に変更され正しいpulsesを拾うようになった。SEN-11345の回路には問題は無いので、これから買われる方は安心して注文されて良いと思う。

一方、SEN-10742迄の製品をお持ちの方は、これから述べる回路修正が必要である。さもないとGeiger管を過大電圧により壊してしまう事になるかもしれない。なおSEN-09848の前にさらに古いversion(SEN-09298)もあるが、当然ながら不具合品である。

問題点

これは主に2つある。
  • (1)Geiger管に定格(450~650V)を超える高圧(1,000~1,500V)がかかっている。
    • 高圧系の定電圧回路が省略されていることと、恐らく作者が設計時にtesterの誤用により適正な電圧であると誤解した事が原因と推測されている。
  • (2)検出回路の極性に誤りがあり、適正にpulseを検出できない。
    • anode検出を採用しているにもかかわらず、NPN transistorでinterfaceを組んでいる。
他にもswitchの耐圧の問題とかあるのだが、省略する。

SparkFunの製品siteのComments欄では主に(1)の問題しか議論されていないが、日本の「がた老AVR研究所」のblogで、(2)の問題とその対策が詳細に解説されていた。

当方は、この「がた老」さんの方法を参考に修正しようと考えていたが、基板のresistを削ったり、遠方から配線を引き回したりという手順がやや複雑に見え、そのまま放置してしまっていた訳である。


修正作業


修正前の状態

それでは修正作業について解説していきたいが、その前に修正前の状況をoscilloscope(DSO Nano v2)で確認しておく。SEN-09848の修正前の検出回路周りは次の様になっている。
OUTがATmega MPUに入る、transistorで整形された(はずの)trigger出力である。

まず、Geiger管のanode出力であるSIGTP1で見てみる。
これが正規のpulseなのだろうが、高圧過ぎるためか雪崩効果(avalanche effect)が起き、次のような連続pulsesも頻繁に観測される。
実際にはSEN-09848のoriginalの状態では、上の正規pulseの方をcountしているのではなく、下の雪崩効果の連続pulsesをQ4の出力(collector)側の大容量capacitor C9で平滑してOUTに出力しているらしい。TP2OUT)での観察結果を見てみよう。
このように雪崩効果の持続時間にもよるのだろうが、50~100msecの矩形pulseとなってQ4から出力され、これがATmega MPUに入力されていた。

しかしこれでは、本来のGeiger管のpulsesを計測しているのではなく、「雪崩効果」の数を計測している事になってしまう。そもそも0.1秒なんて長さのpulseは線量計測としてはどう考えてもおかしい。

途中経過

「がた老AVR研究所」の方法が正しいことは最初から判っていたが、blogに記載されているresistを削ったりする方法が面倒に思えてしまい、他の2、3の部品の交換だけで何とかならないか、最初試行錯誤していた。

問題(1)の高圧を適正化する方法は、C2 10uFを 0.5~1uFにすることで良いのだという。まずそれを行い、また検出回路のQ4のcollector側の平滑用のC9を0.33uFに下げてみた。しかしそれではpulseを殆ど全くcountしなくなってしまった。Oscilloscopeで見てみると、まずQ4のbase(TP1)ではこのような物が見られた。
Geiger管のpulseは真ん中の大きなnegative pulseであるが、それ以外に小さな周期性pulse(1.6msec周期くらい)を見るようになった。(なぜこういうのが出るようになったのかは今でもよく分からない。)Geiger管のpulseもovershootがあり、何だか不思議な形だ。

Q4の出力側(TP2)で見ると、それなりにpulseらしい波形であったが、何故かこのpulseではMPUが殆ど全くcountしてくれないのだった。Firmwareのsourceを見てみると、ちゃんとfalling edgeで入力pinをtriggerするようにprogramされているのだが。

最終修正

高圧の修正と平滑capacitorの値の修正だけでは結局駄目だと分かったので、意を決して検出回路の修正もすることにした。

やった事は、「がた老AVR研究所」のblogを参考に、こちらのsiteの「アノード検出方式のインターフェース回路」ほぼそのままに改めたのである。より具体的には、上に引用したSparkFunの回路図上で説明すると、下記のように修正を行った。
  • Q4 MPSA18(NPN)→ 2SA1015(PNP)に変更
  • R9 1k → 56k に変更
  • Q4 Emitter を VCC に配線
  • SIG と VCC 間に、R 2MとC 100pFを並列に挿入
  • R10 1k8 は削除
  • C9 47uF は R 100k に置換
お手本にした回路と少し抵抗値が違うのは、手持ち部品の都合である。

Resistを削るのはやや面倒だから、横着をしてtransistorの脚を1本空中配線して誤魔化した。
この修正により、見事にGeiger Counterとして正規のpulseをcountするようになった。もし「がた老AVR研究所」の記事がなかったら、筆者の知識だけでは到底修正し得なかった事である。「がた老」さんにはこの場を借りて心より御礼申し上げる次第である。

その正常動作を再びoscilloscopeで見てみよう。まずTP1だが、transistorをPNPに変えたためVCC基準で測定した。 
先ほどの途中経過での不思議なpulseと違い、美しい正規pulseが入るようになった。周期性の小さなpulse(原因不明)は見られているが、これらはMPUでのcountに全く影響を与えないので気にしないことにする。C2 capacitorを都合で1uFにしてしまったためまだ電圧がやや高いのか2枚めの写真のような連続pulseを時に見ることがあるが、それほど計測に影響はないようである。C2は0.47~0.68uFが良いと思う。

検出transistorを通過したTP2での出力は次のように綺麗な100usec前後の矩形波pulseとなり、ATmega MPUできちんとcountされるようになった。
但しfirmwareではまだfalling edgeで検出するようにprogramされているようなので、rising edgeに修正するのが良いかも知れない。どちらでも同じようにはcountするけれど。

なおSparkFunがSEN-11345で行った検出回路の修正は、Q4はNPN transistorのまま、検出方式をanode検出からcathode検出に変更している。このためOUTでの出力はactive low(negative pulse)であり、falling edgeでのtrigger検出のままでprogram上も問題ない。同じ方式で修正するにはGeiger管周りの回路変更が必要で大がかりになりすぎるため、筆者は「がた老」さんと同じくPNP transistorによる検出方式とした。

あとがき

因みにこのGeiger Counterを設計したAaronという人は、もう転職してしまってSparkFunに居ないそうである。彼(a1ronzo)は最初問題に気付いていなかったようで、製品のComments欄で「電圧も高くないし、製品はずっと正常に動作している」としきりに不具合を否定していた。

このGeiger Counterは元々放射線量計測を目的としたというよりは、乱数発生器として企画された面がある。だから元から入っているfirmwareには時間線量を出力する機能は無く、ただpulseのcountに応じて0か1かを出力するだけの単純なprogram(countの間隔が前の間隔より長い時0、短い時1)となっている。

彼がこのGeiger Counterを設計・販売後に日本の原発事故が起こり、本製品が世界中から注目を集めることになり、結果的に設計ミスが白日の下に晒されることになったのは、彼にとっては不遇だったと言えよう。

日本のmakerだったら、非を認めて製品を無償交換するくらいの設計ミスだと思うが、海外には日本のような「謝罪文化」は無いので、問題点が指摘されても交換は行われないし、買った人もそれを強く要求するわけでもない。

日本人の感覚だとAaronの立場に立たされれば、責任を取って退職したのではないかと思う。

Aaronは途中から設計ミスを認める発言をするようになっていたし、結果的にSparkFunは設計ミスとみられる部分を完全に修正して現行品をreleaseしている。最後の改修品がAaronの手によるものかどうかは筆者には判らない。

筆者は、Aaronは日本人ではないから引責退職したわけではなかろうけど、自身の設計ミスがこれだけ大きく取り沙汰されてしまった事の責任を痛感してはいたと思う。だから彼は転職という形でそれを清算した(早く言えば「逃げた」?)のではないか、というのは上記の改修作業をしながらの筆者の空想である。