You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
DFRobot_AS393DFRobot_AS39355/DFRobot_AS3935_I2C.cpp

388 lines
12 KiB

/*!
* @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;
}