forked from DFRobot/DFRobot_AS3935
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DFRobot_AS3935_I2C.cpp
388 lines (351 loc) · 12.1 KB
/
DFRobot_AS3935_I2C.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
/*!
* @file DFRobot_AS3935_I2C.h
* @brief This is a library for AS3935_I2C from DFRobot
* @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
* @license The MIT License (MIT)
* @author [TangJie](jie.tang@dfrobot.com)
* @version V1.0.2
* @date 2019-09-28
* @url https://github.com/DFRobor/DFRobot_AS3935
*/
#include "DFRobot_AS3935_I2C.h"
DFRobot_AS3935_I2C::DFRobot_AS3935_I2C(uint8_t irqx, uint8_t devAddx)
{
devAdd = devAddx;
irq = irqx;
// initalize the IRQ pins
pinMode(irq, INPUT);
}
DFRobot_AS3935_I2C::DFRobot_AS3935_I2C(uint8_t irqx)
{
irq = irqx;
pinMode(irq, INPUT);
}
void DFRobot_AS3935_I2C::setI2CAddress(uint8_t devAddx)
{
if (devAddx == AS3935_ADD1){
devAdd = devAddx;
}else if (devAddx == AS3935_ADD2){
devAdd = devAddx;
}else{
devAdd = AS3935_ADD3;
}
}
uint8_t DFRobot_AS3935_I2C::singRegRead(uint8_t regAdd)
{
uint8_t buf[1];
readReg(regAdd, buf, 1);
return buf[0];
}
void DFRobot_AS3935_I2C::singRegWrite(uint8_t regAdd, uint8_t dataMask, uint8_t regData)
{
// start by reading original register data (only modifying what we need to)
uint8_t origRegData = singRegRead(regAdd);
// calculate new register data... 'delete' old targeted data, replace with new data
// note: 'DataMask' must be bits targeted for replacement
// add'l note: this function does NOT shift values into the proper place... they need to be there already
uint8_t newRegData = ((origRegData & ~dataMask) | (regData & dataMask));
uint8_t buf[1];
buf[0] = newRegData;
// finally, write the data to the register
//I2c.write(devAdd, regAdd, newRegData);
writeReg(regAdd, buf, 1);
}
int DFRobot_AS3935_I2C::defInit()
{
return reset(); // reset registers to default
}
int DFRobot_AS3935_I2C::reset()
{
// run PRESET_DEFAULT Direct Command to set all registers in default state
//int error = I2c.write(devAdd, (uint8_t)0x3C, (uint8_t)0x96);
uint8_t buf[1];
buf[0] = 0x96;
writeReg(0x3c, buf, 1);
return 0;
}
void DFRobot_AS3935_I2C::calRCO()
{
// run ALIB_RCO Direct Command to cal internal RCO
//I2c.write(devAdd, (uint8_t)0x3D, (uint8_t)0x96);
uint8_t buf[1];
buf[0] = 0x96;
writeReg(0x3D, buf, 1);
delay(2); // wait 2ms to complete
}
void DFRobot_AS3935_I2C::powerUp(void)
{
// power-up sequence based on datasheet, pg 23/27
// register 0x00, PWD bit: 0 (clears PWD)
singRegWrite(0x00, 0x01, 0x00);
calRCO(); // run RCO cal cmd
singRegWrite(0x08, 0x20, 0x20); // set DISP_SRCO to 1
delay(2);
singRegWrite(0x08, 0x20, 0x00); // set DISP_SRCO to 0
}
void DFRobot_AS3935_I2C::powerDown(void)
{
// register 0x00, PWD bit: 0 (sets PWD)
singRegWrite(0x00, 0x01, 0x01);
Serial.println("AS3935 powered down");
}
void DFRobot_AS3935_I2C::disturberEn(void)
{
// register 0x03, PWD bit: 5 (sets MASK_DIST)
singRegWrite(0x03, 0x20, 0x00);
Serial.println("disturber detection enabled");
}
void DFRobot_AS3935_I2C::disturberDis(void)
{
// register 0x03, PWD bit: 5 (sets MASK_DIST)
singRegWrite(0x03, 0x20, 0x20);
}
void DFRobot_AS3935_I2C::setIRQOutputSource(uint8_t irqSelect)
{
// set interrupt source - what to display on IRQ pin
// reg 0x08, bits 5 (TRCO), 6 (SRCO), 7 (LCO)
// only one should be set at once, I think
// 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO
if(1 == irqSelect){
singRegWrite(0x08, 0xE0, 0x20); // set only TRCO bit
}else if(2 == irqSelect){
singRegWrite(0x08, 0xE0, 0x40); // set only SRCO bit
}else if(3 == irqSelect){
singRegWrite(0x08, 0xE0, 0x80); // set only LCO bit
}else{
singRegWrite(0x08, 0xE0, 0x00); // clear IRQ pin display bits
}
}
void DFRobot_AS3935_I2C::setTuningCaps(uint8_t capVal)
{
// Assume only numbers divisible by 8 (because that's all the chip supports)
if(120 < capVal){ // cap_value out of range, assume highest capacitance
singRegWrite(0x08, 0x0F, 0x0F); // set capacitance bits to maximum
}else{
singRegWrite(0x08, 0x0F, (capVal >> 3)); // set capacitance bits
}
}
uint8_t DFRobot_AS3935_I2C::getInterruptSrc(void)
{
// definition of interrupt data on table 18 of datasheet
// for this function:
// 0 = unknown src, 1 = lightning detected, 2 = disturber, 3 = Noise level too high
delay(10); // wait 3ms before reading (min 2ms per pg 22 of datasheet)
uint8_t intSrc = (singRegRead(0x03) & 0x0F); // read register, get rid of non-interrupt data
if(0x08 == intSrc){
return 1; // lightning caused interrupt
}else if(0x04 == intSrc){
return 2; // disturber detected
}else if(0x01 == intSrc){
return 3; // Noise level too high
}else{
return 0;
} // interrupt result not expected
}
uint8_t DFRobot_AS3935_I2C::getLightningDistKm(void)
{
uint8_t strikeDist = (singRegRead(0x07) & 0x3F); // read register, get rid of non-distance data
return strikeDist;
}
uint32_t DFRobot_AS3935_I2C::getStrikeEnergyRaw(void)
{
uint32_t nrgyRaw = ((singRegRead(0x06) & 0x1F) << 8); // MMSB, shift 8 bits left, make room for MSB
nrgyRaw |= singRegRead(0x05); // read MSB
nrgyRaw <<= 8; // shift 8 bits left, make room for LSB
nrgyRaw |= singRegRead(0x04); // read LSB, add to others
return nrgyRaw/16777;
}
uint8_t DFRobot_AS3935_I2C::setMinStrikes(uint8_t minStrk)
{
// This function sets min strikes to the closest available number, rounding to the floor,
// where necessary, then returns the physical value that was set. Options are 1, 5, 9 or 16 strikes.
// see pg 22 of the datasheet for more info (#strikes in 17 min)
if(5 > minStrk){
singRegWrite(0x02, 0x30, 0x00);
return 1;
}else if(9 > minStrk){
singRegWrite(0x02, 0x30, 0x10);
return 5;
}else if(16 > minStrk){
singRegWrite(0x02, 0x30, 0x20);
return 9;
}else{
singRegWrite(0x02, 0x30, 0x30);
return 16;
}
}
void DFRobot_AS3935_I2C::setIndoors(void)
{
// AFE settings addres 0x00, bits 5:1 (10010, based on datasheet, pg 19, table 15)
// this is the default setting at power-up (AS3935 datasheet, table 9)
singRegWrite(0x00, 0x3E, 0x24);
Serial.println("set up for indoor operation");
}
void DFRobot_AS3935_I2C::setOutdoors(void)
{
// AFE settings addres 0x00, bits 5:1 (01110, based on datasheet, pg 19, table 15)
singRegWrite(0x00, 0x3E, 0x1C);
Serial.println("set up for outdoor operation");
}
void DFRobot_AS3935_I2C::clearStatistics(void)
{
// clear is accomplished by toggling CL_STAT bit 'high-low-high' (then set low to move on)
singRegWrite(0x02, 0x40, 0x40); // high
singRegWrite(0x02, 0x40, 0x00); // low
singRegWrite(0x02, 0x40, 0x40); // high
}
uint8_t DFRobot_AS3935_I2C::getNoiseFloorLvl(void)
{
// NF settings addres 0x01, bits 6:4
// default setting of 010 at startup (datasheet, table 9)
uint8_t regRaw = singRegRead(0x01); // read register 0x01
return ((regRaw & 0x70) >> 4); // should return value from 0-7, see table 16 for info
}
void DFRobot_AS3935_I2C::setNoiseFloorLvl(uint8_t nfSel)
{
// NF settings addres 0x01, bits 6:4
// default setting of 010 at startup (datasheet, table 9)
if(7 >= nfSel){ // nfSel within expected range
singRegWrite(0x01, 0x70, ((nfSel & 0x07) << 4));
}else{ // out of range, set to default (power-up value 010)
singRegWrite(0x01, 0x70, 0x20);
}
}
uint8_t DFRobot_AS3935_I2C::getWatchdogThreshold(void)
{
// This function is used to read WDTH. It is used to increase robustness to disturbers,
// though will make detection less efficient (see page 19, Fig 20 of datasheet)
// WDTH register: add 0x01, bits 3:0
// default value of 0001
// values should only be between 0x00 and 0x0F (0 and 7)
uint8_t regRaw = singRegRead(0x01);
return (regRaw & 0x0F);
}
void DFRobot_AS3935_I2C::setWatchdogThreshold(uint8_t wdth)
{
// This function is used to modify WDTH. It is used to increase robustness to disturbers,
// though will make detection less efficient (see page 19, Fig 20 of datasheet)
// WDTH register: add 0x01, bits 3:0
// default value of 0010
// values should only be between 0x00 and 0x0F (0 and 7)
singRegWrite(0x01, 0x0F, (wdth & 0x0F));
}
uint8_t DFRobot_AS3935_I2C::getSpikeRejection(void)
{
// This function is used to read SREJ (spike rejection). Similar to the Watchdog threshold,
// it is used to make the system more robust to disturbers, though will make general detection
// less efficient (see page 20-21, especially Fig 21 of datasheet)
// SREJ register: add 0x02, bits 3:0
// default value of 0010
// values should only be between 0x00 and 0x0F (0 and 7)
uint8_t regRaw = singRegRead(0x02);
return (regRaw & 0x0F);
}
void DFRobot_AS3935_I2C::setSpikeRejection(uint8_t srej)
{
// This function is used to modify SREJ (spike rejection). Similar to the Watchdog threshold,
// it is used to make the system more robust to disturbers, though will make general detection
// less efficient (see page 20-21, especially Fig 21 of datasheet)
// WDTH register: add 0x02, bits 3:0
// default value of 0010
// values should only be between 0x00 and 0x0F (0 and 7)
singRegWrite(0x02, 0x0F, (srej & 0x0F));
}
void DFRobot_AS3935_I2C::setLcoFdiv(uint8_t fdiv)
{
// This function sets LCO_FDIV register. This is useful in the tuning of the antenna
// LCO_FDIV register: add 0x03, bits 7:6
// default value: 00
// set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively.
// See pg 23, Table 20 for more info.
singRegWrite(0x03, 0xC0, ((fdiv & 0x03) << 6));
}
void DFRobot_AS3935_I2C::printAllRegs(void)
{
Serial.print("Reg 0x00: ");
Serial.println(singRegRead(0x00));
Serial.print("Reg 0x01: ");
Serial.println(singRegRead(0x01));
Serial.print("Reg 0x02: ");
Serial.println(singRegRead(0x02));
Serial.print("Reg 0x03: ");
Serial.println(singRegRead(0x03));
Serial.print("Reg 0x04: ");
Serial.println(singRegRead(0x04));
Serial.print("Reg 0x05: ");
Serial.println(singRegRead(0x05));
Serial.print("Reg 0x06: ");
Serial.println(singRegRead(0x06));
Serial.print("Reg 0x07: ");
Serial.println(singRegRead(0x07));
Serial.print("Reg 0x08: ");
Serial.println(singRegRead(0x08));
uint32_t nrgyVal = getStrikeEnergyRaw();
Serial.println(nrgyVal);
}
void DFRobot_AS3935_I2C::manualCal(uint8_t capacitance, uint8_t location, uint8_t disturber)
{
// start by powering up
powerUp();
// indoors/outdoors next...
if(1 == location){ // set outdoors if 1
setOutdoors();
}else{ // set indoors if anything but 1
setIndoors();
}
// disturber cal
if(0 == disturber){ // disabled if 0
disturberDis();
}else{ // enabled if anything but 0
disturberEn();
}
setIRQOutputSource(0);
delay(500);
// capacitance first... directly write value here
setTuningCaps(capacitance);
Serial.println("AS3935 manual cal complete");
}
// a nice function would be to read the last 'x' strike data values....
uint8_t DFRobot_AS3935_I2C::begin(void)
{
uint8_t buf[2];
Wire.begin();
Wire.setClock(400000);
DBG("i2c init");
if(readReg(0, buf, 2) == 2){
DBG("return");
return 0;
}
return 1;
}
void DFRobot_AS3935_I2C::writeReg(uint8_t reg, void *pBuf, size_t size)
{
if(pBuf == NULL){
DBG("pBuf ERROR!! :null pointer");
}
uint8_t *_pBuf = (uint8_t*)pBuf;
Wire.beginTransmission(devAdd);
Wire.write(reg);
for(size_t i = 0; i < size; i++){
Wire.write(_pBuf[i]);
}
Wire.endTransmission();
DBG("i2c write");
}
size_t DFRobot_AS3935_I2C::readReg(uint8_t reg, void *pBuf, size_t size)
{
if(pBuf == NULL){
DBG("pBuf ERROR!!:null pointer");
return 0;
}
uint8_t *_pBuf = (uint8_t*)pBuf;
Wire.beginTransmission(devAdd);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(devAdd, size);
for(size_t i = 0; i < size; i++){
_pBuf[i] = Wire.read();
DBG(_pBuf[i], HEX);
}
return size;
}