明日夜は、雷来るかもしれない予報。
というわけで、秋月で買っておいた雷センサー。
http://akizukidenshi.com/catalog/g/gK-08685/
こないだ作ったケーブルレリーズシールドにもなる
アレに、雷センサーを取り付け。
秋月の製品ページで公開されているサンプルスケッチ
を元に、特定の液晶じゃなく、シリアルポートにデータ
を出力できるようにちょこっと改造。
(そのスケッチは後述)
ただし、ピン配置については、DFrobot社のLCDシールド
と合わせて使いたかったので、D5の代わりに、ピン入力
割り込みが使えるD2に変えてみた。
で、動かしてみる…。
とりあえず、I2Cの通信はできてるみたいなんだけど、
500kHzのキャリブレーションがはたらかない。なんで
だろうと思って色々スケッチを見返してみるも、
反応無し。
これは、モジュールがだめってことか?と思ったら、
そうではなかった。
雷センサーモジュールのI2C以外の端子=雷検出の
ピン割り込み用、およびキャリブレーション時の
周波数信号出力用は、D5(固定)に繋がないと
うまくいかないらしい。
理由は、「FreqCounter.h」ライブラリが、16ビット
タイマのキャプチャ機能を使っているかららしく、
コードの中身をちょっと読んでみて解った。
あぁ、困った。ピン配置変えるだけじゃぁすまない
んだよな。LCDシールドがこれだから。
というわけで、対応策を考えてみる…
ソフト的にピンの変化の回数を拾って、回数を
延べ時間で割れば、平均周波数が出てくるだろう、
と思ったんだけど、やってみると、遅い周波数なら
かなり正確な値が出るのに、500kHzに近づくと誤差
がでかくなる。
理由を考えてみる…
多分、時間計測その他でArduinoコアで発生している
タイマ割り込みが悪さしているのかと。なにしろ、
16MHzでも500kHzを計るには、32クロック間隔。
elfファイルから逆アセンブリリスト眺めてみても、
ソフトでピン変化を見るのはぎりぎりのクロック数。
ってことは、割り込みが挟まれば、間違えなく誤差
として計上されちゃう。これだ、多分。
というわけで、ソフト的に図るという手段はだめ
っぽい。別の方法を考える。
キャリブレーション時にD5から入力できて、雷待ち
のときはD2から入力してもかまわないわけだから、
その間隙を突くことにする。
さっきの写真のように、D5とD2の間に1kΩの抵抗
を取り付けて、キャリブレーション時にはD5を入力
に設定しておいて、それが終わったらD5は出力に。
→つまりLCD出力用に切り替え。
D2は、ピン変化割り込みがネイティブで利くので、
元々ピン選択としてはこっちのほうがいいだろうと。
とりあえず、キャリブレーションが終わったら、
レジスタのダンプがだらだらと出るだけ。
キャリブレーションの様子。とりあえず、ぶっ壊れず
動くみたい。まぁあたりまえ。
こうなって、キャリブレーションが終わったら、
あとはレジスタの中身がだらだらと出てくる。
部屋の中の電磁ノイズを拾うみたいで、時々こんな
メッセージが出てくる。
というわけで、D2とD5が1kΩで繋いじゃえば、
インターバルタイマや、雷にシンクロして
シャッター切るみたいな用途なら、これで
いいんじゃないかなと。
というわけで、秋月からダウンロードした
Arduino用スケッチの改造版。
(ちょっと、無駄に長い、かつ、まだピンチェンジ
割り込みとか組み込んでない)
//AS3935 SCL = A5
//AS3935 SDA = A4
//AS3935 IRQ = D5 -> D2
//AQM1602 SCL = A5
//AQM1602 SDA = A4
//USE 5V PWR
#include <Wire.h>
#include <FreqCounter.h>
#define AS3935_ADRS 0x00
#define AFE_GB 0x1F // ANALOG FRONT END GAIN BOOST = 12(Indoor) 0x00 to 0x1F
#define NF_LEV 0x02 // NOIS FLOOR LEVEL 0x00 to 0x07
#define WDTH 0x02 // WATCH DOG THRESHOLD 0x00 to 0x0F
String OUT_STRING;
byte reg0,reg1,reg2,reg3,reg4,reg5,reg6,reg7,reg8,reg3A,reg3B,reg3C,reg3D,regDUMMY;
unsigned long enargy;
unsigned int distance;
long int freq;
long int OLD_BUFFER = 10000;
long int NOW_BUFFER = 0;
int C;
long int F;
byte CAP_RESULT;
void ByteWrite(byte reg, byte data)
{
Wire.beginTransmission(AS3935_ADRS);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission();
delay(50);
}
byte ByteRead(byte reg)
{
byte data = 0;
Wire.beginTransmission(AS3935_ADRS);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(AS3935_ADRS,1);
data = Wire.read(); // 1バイトを受信
return data;
}
void resistorRead(void)
{
Wire.beginTransmission(AS3935_ADRS);
Wire.write(0);
Wire.endTransmission(false);
Wire.requestFrom(AS3935_ADRS,9);
reg0 = Wire.read();
reg1 = Wire.read();
reg2 = Wire.read();
reg3 = Wire.read();
reg4 = Wire.read();
reg5 = Wire.read();
reg6 = Wire.read();
reg7 = Wire.read();
reg8 = Wire.read();
Wire.beginTransmission(AS3935_ADRS);
Wire.write(0x3A);
Wire.endTransmission(false);
Wire.requestFrom(AS3935_ADRS,4);
reg3A = Wire.read();
reg3B = Wire.read();
reg3C = Wire.read();
reg3D = Wire.read();
}
void setup()
{
pinMode(2,INPUT);
pinMode(5,INPUT);
Wire.begin();
Serial.begin(9600); // start serial communication at 9600bps
Serial.println("READY"); // print the reading
Serial.print("IRQ from D2 = ");
Serial.print(2);
Serial.print(" (now : ");
Serial.print(digitalRead(2));
Serial.println(")");
DISP_OPENNING();
INIT_AS3935();
}
void loop()
{
Serial.println();
while(1)
{
if (digitalRead(2)== HIGH) INT_DETECTS();
resistorRead();
serialDisplay2();
}
}
void INT_DETECTS(void)
{
byte reg3buffer;
delay(4);
resistorRead();
reg3buffer = reg3 & 0x0F; //interrupt reason
if (reg3buffer == 0x01) INT_NH(); // noise too high
if (reg3buffer == 0x04) INT_D(); // disturber
if (reg3buffer == 0x08) INT_L(); // lightning
}
void INT_NH(void) //noise level too high
{
Serial.println();
OUT_STRING = "Nois Level High ";
delay(700);
serialDisplay();
OUT_STRING = "Watching........ ";
Serial.println(OUT_STRING);
}
void INT_D(void) //disturber detected
{
Serial.println();
OUT_STRING = "Disturber DETect";
delay(700);
serialDisplay();
OUT_STRING = "Watching........";
Serial.println(OUT_STRING);
}
void INT_L(void) //lightning interrupt
{
OUT_STRING = "LIGHTNING DETECT";
Serial.println(OUT_STRING);
enargy = (((reg6 & 0x0F) * 65536)+ (reg5 * 256)+ (reg4)) & 0x0FFFFF;
distance = (reg7 );
OUT_STRING = " E=" + String(enargy) + " D=" + String(distance) + "km";
if(reg7 == 0x01) OUT_STRING = " E=" + String(enargy) + " OvrHed";
if(reg7 == 0x3F) OUT_STRING = " E=" + String(enargy) + " OutRng";
Serial.println(OUT_STRING);
delay(1300);
OUT_STRING = "Watching........";
Serial.println(OUT_STRING);
}
void INIT_AS3935(void)
{
ByteWrite(0x3C,0x96); // preset default
ByteWrite(0x3D,0x96); // calib_RCO
ByteWrite(0x00,(AFE_GB << 1)); // SET ANALOG FRONT END GAIN BOOST
ByteWrite(0x01,((NF_LEV << 4) | WDTH));
ByteWrite(0x03,0x00); // FRQ DIV RATIO = 1/16
CALIB_LCO();
}
void CALIB_LCO(void)
{
Serial.println();
delay(20);
OUT_STRING = "NOW CALIBRATION";
Serial.println(OUT_STRING);
OUT_STRING = " C=000pF F=500000";
Serial.println(OUT_STRING);
FREQ_COUNT(); //DUMMY
for ( byte b = 0; b < 0x10 ; b++)
{
ByteWrite(0x08,(0x80 | b));
delay(50);
FREQ_COUNT();
NOW_BUFFER = abs(freq - 3125);
if(OLD_BUFFER > NOW_BUFFER) CAP_RESULT = b;
OLD_BUFFER = NOW_BUFFER;
Serial.print("CAP = ");
Serial.print(b,DEC);
Serial.print(" freq = ");
Serial.println((freq * 16 * 10 ),DEC );
delay(300);
}
Serial.println();
Serial.print("CAP_RESULT=");
Serial.print(CAP_RESULT);
Serial.print(" ");
Serial.print(CAP_RESULT * 8);
Serial.println("pF");
ByteWrite(0x08,(0x80 | CAP_RESULT));
delay(100);
FREQ_COUNT();
OUT_STRING = "CALIBRATION DONE";
Serial.println(OUT_STRING);
ByteWrite(0x08,CAP_RESULT);
delay(3000);
}
void FREQ_COUNT(void)
{
FreqCounter::f_comp = 10;
FreqCounter::start(100);
while (FreqCounter::f_ready == 0);
freq = FreqCounter::f_freq;
}
void DISP_OPENNING(void)
{
OUT_STRING = "Lightning Sensor";
Serial.println(OUT_STRING);
OUT_STRING = " AS3935 DEMO ";
Serial.println(OUT_STRING);
delay(2000);
}
void serialDisplay(void)
{
Serial.println(OUT_STRING);
Serial.print(" reg0=");
Serial.print(reg0,HEX);
Serial.print(" reg1=");
Serial.print(reg1,HEX);
Serial.print(" reg2=");
Serial.print(reg2,HEX);
Serial.print(" reg3=");
Serial.print(reg3,HEX);
Serial.print(" reg4=");
Serial.print(reg4,HEX);
Serial.print(" reg5=");
Serial.print(reg5,HEX);
Serial.print(" reg6=");
Serial.print(reg6,HEX);
Serial.print(" reg7=");
Serial.print(reg7,HEX);
Serial.print(" reg8=");
Serial.println(reg8,HEX);
}
void serialDisplay2(void)
{
Serial.print(" reg0=");
Serial.print(reg0,HEX);
Serial.print(" reg1=");
Serial.print(reg1,HEX);
Serial.print(" reg2=");
Serial.print(reg2,HEX);
Serial.print(" reg3=");
Serial.print(reg3,HEX);
Serial.print(" reg4=");
Serial.print(reg4,HEX);
Serial.print(" reg5=");
Serial.print(reg5,HEX);
Serial.print(" reg6=");
Serial.print(reg6,HEX);
Serial.print(" reg7=");
Serial.print(reg7,HEX);
Serial.print(" reg8=");
Serial.println(reg8,HEX);
}
雷、いい時間帯に来るといいなぁ。