先日設計上の不具合を何とか改修する事が出来た
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 mkII(
3,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-10742、
SEN-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-10742、
SEN-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を書いてみたので
ここに置きます。