From ee688f17ce03509e8f40986b53511cdb61c79c41 Mon Sep 17 00:00:00 2001 From: tangjie133 <1334875503@qq.com> Date: Tue, 28 Dec 2021 16:45:32 +0800 Subject: [PATCH] V1.0.2 --- DFRobot_AS3935_I2C.cpp | 544 ++++++++---------- DFRobot_AS3935_I2C.h | 298 +++++++--- LICENSE | 525 +---------------- README_CN.md | 224 ++++++++ RaspberryPi/Python/DFRobot_AS3935_Lib.py | 241 -------- RaspberryPi/Python/README.md | 158 ----- .../Python/example/DFRobot_AS3935_detailed.py | 108 ---- .../Python/example/DFRobot_AS3935_ordinary.py | 94 --- .../DFRobotAS3935LightningSensorDetailed.ino} | 48 +- .../DFRobotAS3935LightningSensorOrdinary.ino} | 47 +- library.properties | 9 + python/raspberrypi/DFRobot_AS3935_Lib.py | 319 ++++++++++ python/raspberrypi/README.md | 179 ++++++ python/raspberrypi/README_CN.md | 173 ++++++ .../DFRobot_AS3935_detailed.py | 107 ++++ .../DFRobot_AS3935_ordinary.py | 94 +++ readme.md | 383 ++++++------ resources/images/SEN0290.png | Bin 0 -> 112375 bytes 18 files changed, 1850 insertions(+), 1701 deletions(-) create mode 100644 README_CN.md delete mode 100644 RaspberryPi/Python/DFRobot_AS3935_Lib.py delete mode 100644 RaspberryPi/Python/README.md delete mode 100644 RaspberryPi/Python/example/DFRobot_AS3935_detailed.py delete mode 100644 RaspberryPi/Python/example/DFRobot_AS3935_ordinary.py rename examples/{DFRobot_AS3935_lightning_sensor_detailed/DFRobot_AS3935_lightning_sensor_detailed.ino => DFRobotAS3935LightningSensorDetailed/DFRobotAS3935LightningSensorDetailed.ino} (79%) rename examples/{DFRobot_AS3935_lightning_sensor_ordinary/DFRobot_AS3935_lightning_sensor_ordinary.ino => DFRobotAS3935LightningSensorOrdinary/DFRobotAS3935LightningSensorOrdinary.ino} (76%) create mode 100644 library.properties create mode 100644 python/raspberrypi/DFRobot_AS3935_Lib.py create mode 100644 python/raspberrypi/README.md create mode 100644 python/raspberrypi/README_CN.md create mode 100644 python/raspberrypi/example/DFRobot_AS3935_detailed/DFRobot_AS3935_detailed.py create mode 100644 python/raspberrypi/example/DFRobot_AS3935_ordinary/DFRobot_AS3935_ordinary.py create mode 100644 resources/images/SEN0290.png diff --git a/DFRobot_AS3935_I2C.cpp b/DFRobot_AS3935_I2C.cpp index 3061d3e..af51901 100644 --- a/DFRobot_AS3935_I2C.cpp +++ b/DFRobot_AS3935_I2C.cpp @@ -1,432 +1,388 @@ +/*! + * @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); + devAdd = devAddx; + irq = irqx; + // initalize the IRQ pins + pinMode(irq, INPUT); } DFRobot_AS3935_I2C::DFRobot_AS3935_I2C(uint8_t irqx) { - irq = irqx; - // initalize the IRQ pins - // pinMode(irq, OUTPUT); - // digitalWrite(irq,1); - pinMode(irq, INPUT); - + irq = irqx; + pinMode(irq, INPUT); } void DFRobot_AS3935_I2C::setI2CAddress(uint8_t devAddx) { - if (devAddx == AS3935_ADD1) - { + if (devAddx == AS3935_ADD1){ + devAdd = devAddx; + }else if (devAddx == AS3935_ADD2){ devAdd = devAddx; - } - else if (devAddx == AS3935_ADD2) - { - devAdd = devAddx; - } - else - { - devAdd = AS3935_ADD3; - } + }else{ + devAdd = AS3935_ADD3; + } } uint8_t DFRobot_AS3935_I2C::singRegRead(uint8_t regAdd) { - // I2C address Register address num bytes - //I2c.read((uint8_t)devAdd, (uint8_t)regAdd, (uint8_t)0x01); // Use I2C library to read register - //uint8_t regData = I2c.receive(); // receive the I2C data - uint8_t buf[1]; - readReg(regAdd, buf, 1); - return buf[0]; + 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); + // 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); - //Serial.print("wrt: "); - //Serial.print(newRegData,HEX); - //Serial.print(" Act: "); - //Serial.println(singRegRead(regAdd),HEX); + // 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 + 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; + // 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 + // 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 + // 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"); + // 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"); + // 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); + // 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 // assume 0 - { - singRegWrite(0x08, 0xE0, 0x00); // clear IRQ pin display bits - } - + // 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 - } - //Serial.print("capacitance set to 8x"); - //Serial.println((singRegRead(0x08) & 0x0F)); + // 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 - + // 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; + 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; + 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; - } + // 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"); + // 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"); + // 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 + // 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 + // 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); - } + // 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); + // 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)); + // 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); + // 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)); + // 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)); + // 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); + 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"); + // 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; + 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"); + 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; + 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; } diff --git a/DFRobot_AS3935_I2C.h b/DFRobot_AS3935_I2C.h index b491db4..cce502b 100644 --- a/DFRobot_AS3935_I2C.h +++ b/DFRobot_AS3935_I2C.h @@ -1,3 +1,15 @@ + +/*! + * @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 + */ + #ifndef DFRobot_AS3935_I2C_h #define DFRobot_AS3935_I2C_h @@ -7,9 +19,9 @@ #include "Wire.h" // I2C address -#define AS3935_ADD1 0x01 // A0=high, A1=low -#define AS3935_ADD3 0x03 // A0=high, A1=high -#define AS3935_ADD2 0x02 // A0=low, A1=high +#define AS3935_ADD1 0x01 ///< A0=high, A1=low +#define AS3935_ADD3 0x03 ///< A0=high, A1=high +#define AS3935_ADD2 0x02 ///< A0=low, A1=high //#define ENABLE_DBG #ifdef ENABLE_DBG @@ -20,74 +32,226 @@ #define DBG(...) #endif -class DFRobot_AS3935_I2C -{ - public: - DFRobot_AS3935_I2C(uint8_t irqx, uint8_t devAddx); - DFRobot_AS3935_I2C(uint8_t irqx); - uint8_t begin(void); - /*! Set i2c address */ - void setI2CAddress(uint8_t devAddx); - /*! Manual calibration */ - void manualCal(uint8_t capacitance, uint8_t location, uint8_t disturber); - /*! reset registers to default */ - int defInit(void); - void disturberEn(void); - void disturberDis(void); - void setIRQOutputSource(uint8_t irqSelect); - void setTuningCaps(uint8_t capVal); - /*! 0 = unknown src, 1 = lightning detected, 2 = disturber, 3 = Noise level too high */ - uint8_t getInterruptSrc(void); - /*! Get rid of non-distance data */ - uint8_t getLightningDistKm(void); - /*! Get lightning energy intensity */ - uint32_t getStrikeEnergyRaw(void); - uint8_t setMinStrikes(uint8_t minStrk); - void clearStatistics(void); - void setIndoors(void); - void setOutdoors(void); - uint8_t getNoiseFloorLvl(void); - void setNoiseFloorLvl(uint8_t nfSel); - uint8_t getWatchdogThreshold(void); - void setWatchdogThreshold(uint8_t wdth); - uint8_t getSpikeRejection(void); - void setSpikeRejection(uint8_t srej); - void setLcoFdiv(uint8_t fdiv); - /*! View register data */ - void printAllRegs(void); - void powerUp(void); +class DFRobot_AS3935_I2C{ +public: + /** + * @fn DFRobot_AS3935_I2C + * @brief AS3935 object + * @param irqx irq pin + * @param devAddx i2c address + * @return None + */ + DFRobot_AS3935_I2C(uint8_t irqx, uint8_t devAddx); + + /** + * @fn DFRobot_AS3935_I2C + * @brief AS3935 object + * @param irqx irq pin + * @return None + */ + DFRobot_AS3935_I2C(uint8_t irqx); + + /** + * @fn begin + * @brief I2C init + * @return uint8_t type, indicates the initialization status + * @retval 0 succeed + * @retval 1 failure + */ + uint8_t begin(void); + + /** + * @fn setI2CAddress + * @brief set i2c address + * @param devAddx i2c address + * @return None + */ + void setI2CAddress(uint8_t devAddx); + + /** + * @fn manualCal + * @brief manual calibration + * @param capacitance capacitance + * @param location location + * @param disturber disturber + * @return None + */ + void manualCal(uint8_t capacitance, uint8_t location, uint8_t disturber); + + /** + * @fn defInit + * @brief reset registers to default + * @return int type,represents rest state + * @retval 0 success + */ + int defInit(void); + + /** + * @fn disturberEn + * @brief Disturber detection enabled + * @return None + */ + void disturberEn(void); + + /** + * @fn disturberDis + * @brief Disturber detection disenabled + * @return None + */ + void disturberDis(void); + + /** + * @fn setIRQOutputSource + * @brief Set interrupt source + * @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + * @return None + */ + void setIRQOutputSource(uint8_t irqSelect); + + /** + * @fn setTuningCaps + * @brief set capacitance + * @param capVal size + * @return None + */ + void setTuningCaps(uint8_t capVal); + + /** + * @fn getInterruptSrc + * @brief get interrupt source + * @return uint8_t type,returns the interrupt source type + * @retval 0 interrupt result not expected + * @retval 1 lightning caused interrupt + * @retval 2 disturber detected + * @retval 3 Noise level too high + */ + uint8_t getInterruptSrc(void); + + /** + * @fn getLightningDistKm + * @brief get lightning distance + * @return unit kilometer + */ + uint8_t getLightningDistKm(void); + + /** + * @fn getStrikeEnergyRaw + * @brief get lightning energy intensity + * @return lightning energy intensity(0-1000) + */ + uint32_t getStrikeEnergyRaw(void); + + /** + * @fn setIndoors + * @brief Set to the indoor model + * @return None + */ + void setIndoors(void); + + /** + * @fn setOutdoors + * @brief Set to the outdoor model + * @return None + */ + void setOutdoors(void); + + /** + * @fn setOutdoors + * @brief Get the noise level + * @return Return noise level + */ + uint8_t getNoiseFloorLvl(void); + + /** + * @fn setNoiseFloorLvl + * @brief Set the noise level + * @param 0~7,More than 7 will use the default value:2 + * @return None + */ + void setNoiseFloorLvl(uint8_t nfSel); + + /** + * @fn getWatchdogThreshold + * @brief read WDTH + * @return Return interference level + */ + uint8_t getWatchdogThreshold(void); + + /** + * @fn setWatchdogThreshold + * @brief Set an anti-interference rating + * @param 0~7,More than 7 will use the default value:2 + * @return None + */ + void setWatchdogThreshold(uint8_t wdth); + + /** + * @fn getSpikeRejection + * @brief read SREJ (spike rejection) + * @return Return SREJ value + */ + uint8_t getSpikeRejection(void); + + /** + * @fn setSpikeRejection + * @brief Modify SREJ (spike rejection) + * @param 0~7,More than 7 will use the default value:2 + * @return None + */ + void setSpikeRejection(uint8_t srej); + + /** + * @fn setLcoFdiv + * @brief Sets LCO_FDIV register + * @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively + * @return None + */ + void setLcoFdiv(uint8_t fdiv); + + /** + * @fn printAllRegs + * @brief view register data + * @return None + */ + void printAllRegs(void); + + /** + * @fn powerUp + * @brief Configure sensor + * @return None + */ + void powerUp(void); - private: - uint8_t irq, devAdd; - uint8_t singRegRead(uint8_t regAdd);//原始I2C数据读取 - void singRegWrite(uint8_t regAdd, uint8_t dataMask, uint8_t regData);//原始数据发送 - int reset(void); - void powerDown(void); - void calRCO(void); - - /** - * @brief Write register value through IIC bus - * - * @param reg Register address 8bits - * @param pBuf Storage cache to write data in - * @param size The length of data to be written - */ - void writeReg(uint8_t reg, void *pBuf, size_t size); - //void writeRegNoStop(uint8_t reg, void *pBuf, size_t size) - - /** - * @brief Read register value through IIC bus - * - * @param reg Register address 8bits - * @param pBuf Read data storage cache - * @param size Read the length of data - * @return Return the read length - */ - size_t readReg(uint8_t reg, void *pBuf, size_t size); +private: + uint8_t irq, devAdd; + uint8_t singRegRead(uint8_t regAdd); + void singRegWrite(uint8_t regAdd, uint8_t dataMask, uint8_t regData); + int reset(void); + void powerDown(void); + void calRCO(void); + void clearStatistics(void); + uint8_t setMinStrikes(uint8_t minStrk); + /** + * @fn writeReg + * @brief Write register value through IIC bus + * @param reg Register address 8bits + * @param pBuf Storage cache to write data in + * @param size The length of data to be written + */ + void writeReg(uint8_t reg, void *pBuf, size_t size); + //void writeRegNoStop(uint8_t reg, void *pBuf, size_t size) + /** + * @fn readReg + * @brief Read register value through IIC bus + * @param reg Register address 8bits + * @param pBuf Read data storage cache + * @param size Read the length of data + * @return Return the read length + */ + size_t readReg(uint8_t reg, void *pBuf, size_t size); }; - #endif diff --git a/LICENSE b/LICENSE index 8000a6f..d96afd5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,504 +1,21 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random - Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! +MIT License + +Copyright (c) 2020 DFRobot + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000..96d27fe --- /dev/null +++ b/README_CN.md @@ -0,0 +1,224 @@ +# DFRobot_AS3935 + +* [English Version](./README.md) + +AS3935雷电传感器可以检测雷电,显示雷电的距离和强度,不受电弧和噪声的干扰 +可设置为室内或室外模式 + +![Product Image](./resources/images/SEN0290.png) + +## 产品链接(https://www.dfrobot.com.cn/goods-1889.html) + + SKU:SEN0290 + +## 目录 + + * [概述](#概述) + * [库安装](#库安装) + * [方法](#方法) + * [兼容性](#兼容性) + * [历史](#历史) + * [创作者](#创作者) + +## 概述 + +从AS3935模块中输入命令和读取数据 + +1. 闪电传感器对半径40公里以内的雷暴活动发出警报 +2. 从头顶到风暴顶部的距离估计为40公里,每15步 +3.检测云对地和云内(云对云)闪烁 +4. 嵌入人工干扰抑制算法 +5. 可编程检测水平使阈值设置为最佳控制 +6. 三个i2c接口,自由切换避免站点冲突 + +## 库安装 + +使用此库前,请首先下载库文件,将其粘贴到\Arduino\libraries目录中,然后打开examples文件夹并在该文件夹中运行演示。 + +## 方法 + +```C++ + /** + * @fn begin + * @brief I2C初始化 + * @return uint8_t 类型, 表示初始化状态 + * @retval 0 成功 + * @retval 1 失败 + */ + uint8_t begin(void); + + /** + * @brief 设置 i2c 地址 + * @param devAddx i2c 地址 + */ + void setI2CAddress(uint8_t devAddx); + + /** + * @fn manualCal + * @brief 配置传感器 + * @param capacitance 天线调谐电容(必须是8,8 - 120pf的整数倍) + * @param location 室内或室外模式选择 + * @param disturber 启用/禁用干扰发射机检测 + * @return None + */ + void manualCal(uint8_t capacitance, uint8_t location, uint8_t disturber); + + /** + * @fn defInit + * @brief 将寄存器重置为默认值 + * @return int 类型,表示rest状态 + * @return 0 成功 + */ + int defInit(void); + + /** + * @fn disturberEn + * @brief 中断检测使能 + * @return None + */ + void disturberEn(void); + + /** + * @fn disturberDis + * @brief 中断检测失能 + * @return None + */ + void disturberDis(void); + + /** + * @fn setIRQOutputSource + * @brief 设置中断源 + * @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + * @return None + */ + void setIRQOutputSource(uint8_t irqSelect); + + /** + * @fn setTuningCaps + * @brief 设置容量 + * @param capVal 容量大小 + * @return None + */ + void setTuningCaps(uint8_t capVal); + + /** + * @fn getInterruptSrc + * @brief 获取中断源 + * @return uint8_t类型,返回中断源类型 + * @retval 0 没有中断 + * @retval 1 闪电引起的中断 + * @retval 2 干扰中断 + * @retval 3 噪声量太高 + */ + uint8_t getInterruptSrc(void); + + /** + * @fn getLightningDistKm + * @brief 获取闪电距离 + * @return 闪电距离(单位公里) + */ + uint8_t getLightningDistKm(void); + + /** + * @fn getStrikeEnergyRaw + * @brief 获取闪电能力强度 + * @return 闪电能力强度(0-1000) + */ + uint32_t getStrikeEnergyRaw(void); + + /** + * @fn setIndoors + * @brief 设置为室内模式 + * @return None + */ + void setIndoors(void); + + /** + * @fn setOutdoors + * @brief 设置为室外模式 + * @return None + */ + void setOutdoors(void); + + /** + * @fn getNoiseFloorLvl + * @brief 获取噪音等级 + * @return 返回噪声等级 + */ + uint8_t getNoiseFloorLvl(void); + + /** + * @fn setNoiseFloorLvl + * @brief 设置噪音等级 + * @param nfSel 0~7,大于7将使用默认值:2 + * @return None + */ + void setNoiseFloorLvl(uint8_t nfSel); + + /** + * @fn getWatchdogThreshold + * @brief 获取干扰等级 + * @return 返回干扰等级 + */ + uint8_t getWatchdogThreshold(void); + + /** + * @fn setWatchdogThreshold + * @brief 设置干扰等级 + * @param wdth 0~7,大于7将使用默认值:2 + * @return None + */ + void setWatchdogThreshold(uint8_t wdth); + + /** + * @fn getSpikeRejection + * @brief 获取 SREJ (毛刺抑制) + * @return 返回SREJ值 + */ + uint8_t getSpikeRejection(void); + + /** + * @fn setSpikeRejection + * @brief 修改 SREJ (毛刺抑制) + * @param 0~7,大于7将使用默认值:2 + */ + void setSpikeRejection(uint8_t srej); + + /** + * @fn setLcoFdiv + * @brief 设置 LCO_FDIV 寄存器 + * @param fdiv 设置0, 1, 2或3的比率分别为16,32,64和128 + * @return None + */ + void setLcoFdiv(uint8_t fdiv); + + /** + * @fn printAllRegs + * @brief 查看注册数据 + * @return None + */ + void printAllRegs(void); + + /** + * @fn powerUp + * @brief 配置传感器电源 + * @return None + */ + void powerUp(void); +``` +## 兼容性 + +主板 | 通过 | 未通过 | 未测试 | 备注 +------------------ | :----------: | :----------: | :---------: | ----- +Arduino uno | √ | | | + esp8266 | √ | | | + +## 历史 + +- 2021/09/30 - 1.0.2 版本 +- 2021/08/24 - 1.0.1 版本 +- 2019/09/28 - 1.0.0 版本 + +## 创作者 + +Written by TangJie(jie.Tang@dfrobot.com), 2019. (Welcome to our [website](https://www.dfrobot.com/)) diff --git a/RaspberryPi/Python/DFRobot_AS3935_Lib.py b/RaspberryPi/Python/DFRobot_AS3935_Lib.py deleted file mode 100644 index e08d8d3..0000000 --- a/RaspberryPi/Python/DFRobot_AS3935_Lib.py +++ /dev/null @@ -1,241 +0,0 @@ -import time -import smbus - -class DFRobot_AS3935: - def __init__(self, address, bus = 1): - self.address = address - self.i2cbus = smbus.SMBus(bus) - - def writeByte(self, register, value): - try: - self.i2cbus.write_byte_data(self.address, register, value) - return 1 - except: - return 0 - - def readData(self, register): - self.register = self.i2cbus.read_i2c_block_data(self.address, register) - - def manualCal(self, capacitance, location, disturber): - self.powerUp() - if location == 1: - self.setIndoors() - else: - self.setOutdoors() - - if disturber == 0: - self.disturberDis() - else: - self.disturberEn() - - self.setIrqOutputSource(0) - time.sleep(0.5) - self.setTuningCaps(capacitance) - - def setTuningCaps(self, capVal): - #Assume only numbers divisible by 8 (because that's all the chip supports) - if capVal > 120: #cap_value out of range, assume highest capacitance - self.singRegWrite(0x08, 0x0F, 0x0F) #set capacitance bits to maximum - else: - self.singRegWrite(0x08, 0x0F, capVal >> 3) #set capacitance bits - - self.singRegRead(0x08) - #print('capacitance set to 8x%d'%(self.register[0] & 0x0F)) - - def powerUp(self): - #register 0x00, PWD bit: 0 (clears PWD) - self.singRegWrite(0x00, 0x01, 0x00) - self.calRCO() #run RCO cal cmd - self.singRegWrite(0x08, 0x20, 0x20) #set DISP_SRCO to 1 - time.sleep(0.002) - self.singRegWrite(0x08, 0x20, 0x00) #set DISP_SRCO to 0 - - def powerDown(self): - #register 0x00, PWD bit: 0 (sets PWD) - self.singRegWrite(0x00, 0x01, 0x01) - - def calRCO(self): - self.writeByte(0x3D, 0x96) - time.sleep(0.002) - - def setIndoors(self): - self.singRegWrite(0x00, 0x3E, 0x24) - print("set to indoors model") - - def setOutdoors(self): - self.singRegWrite(0x00, 0x3E, 0x1C) - print("set to outdoors model") - - def disturberDis(self): - #register 0x03, PWD bit: 5 (sets MASK_DIST) - self.singRegWrite(0x03, 0x20, 0x20) - print("disenable disturber detection") - - def disturberEn(self): - #register 0x03, PWD bit: 5 (sets MASK_DIST) - self.singRegWrite(0x03, 0x20, 0x00) - print("enable disturber detection") - - def singRegWrite(self, regAdd, dataMask, regData): - #start by reading original register data (only modifying what we need to) - self.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 - newRegData = (self.register[0] & ~dataMask)|(regData & dataMask) - #finally, write the data to the register - self.writeByte(regAdd, newRegData) - #print('wrt: %02x'%newRegData) - self.singRegRead(regAdd) - #print('Act: %02x'%self.register[0]) - - def singRegRead(self,regAdd): - self.readData(regAdd) - - def getInterruptSrc(self): - #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 - time.sleep(0.03) #wait 3ms before reading (min 2ms per pg 22 of datasheet) - self.singRegRead(0x03) #read register, get rid of non-interrupt data - intSrc = self.register[0]&0x0F - if intSrc == 0x08: - return 1 #lightning caused interrupt - elif intSrc == 0x04: - return 2 #disturber detected - elif intSrc == 0x01: - return 3 #Noise level too high - else: - return 0 #interrupt result not expected - - def reset(self): - err = self.writeByte(0x3C, 0x96) - time.sleep(0.002) #wait 2ms to complete - return err - - def setLcoFdiv(self,fdiv): - self.singRegWrite(0x03, 0xC0, (fdiv & 0x03) << 6) - - def setIrqOutputSource(self, 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 irqSelect == 1: - self.singRegWrite(0x08, 0xE0, 0x20) #set only TRCO bit - elif irqSelect == 2: - self.singRegWrite(0x08, 0xE0, 0x40) #set only SRCO bit - elif irqSelect == 3: - self.singRegWrite(0x08, 0xE0, 0x80) #set only SRCO bit - else: - self.singRegWrite(0x08, 0xE0, 0x00) #clear IRQ pin display bits - - def getLightningDistKm(self): - self.singRegRead(0x07) #read register, get rid of non-distance data - return self.register[0]&0x3F - - def getStrikeEnergyRaw(self): - self.singRegRead(0x06) #MMSB, shift 8 bits left, make room for MSB - nrgyRaw = (self.register[0]&0x1F) << 8 - self.singRegRead(0x05) #read MSB - nrgyRaw |= self.register[0] - nrgyRaw <<= 8 #shift 8 bits left, make room for LSB - self.singRegRead(0x04) #read LSB, add to others - nrgyRaw |= self.register[0] - - return nrgyRaw/16777 - - def setMinStrikes(self, 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. - if minStrk < 5: - self.singRegWrite(0x02, 0x30, 0x00) - return 1 - elif minStrk < 9: - self.singRegWrite(0x02, 0x30, 0x10) - return 5 - elif minStrk < 16: - self.singRegWrite(0x02, 0x30, 0x20) - return 9 - else: - self.singRegWrite(0x02, 0x30, 0x30) - return 16 - - def clearStatistics(self): - #clear is accomplished by toggling CL_STAT bit 'high-low-high' (then set low to move on) - self.singRegWrite(0x02, 0x40, 0x40) #high - self.singRegWrite(0x02, 0x40, 0x00) #low - self.singRegWrite(0x02, 0x40, 0x40) #high - - def getNoiseFloorLv1(self): - #NF settings addres 0x01, bits 6:4 - #default setting of 010 at startup (datasheet, table 9) - self.singRegRead(0x01) #read register 0x01 - return (self.register[0] & 0x70) >> 4 #should return value from 0-7, see table 16 for info - - def setNoiseFloorLv1(self, nfSel): - #NF settings addres 0x01, bits 6:4 - #default setting of 010 at startup (datasheet, table 9) - if nfSel <= 7: #nfSel within expected range - self.singRegWrite(0x01, 0x70, (nfSel & 0x07) << 4) - else: #out of range, set to default (power-up value 010) - self.singRegWrite(0x01, 0x70, 0x20) - - def getWatchdogThreshold(self): - #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 0010 - #values should only be between 0x00 and 0x0F (0 and 7) - self.singRegRead(0x01) - return self.register[0] & 0x0F - - def setWatchdogThreshold(self, 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) - self.singRegWrite(0x01, 0x0F, wdth & 0x0F) - - def getSpikeRejection(self): - #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) - self.singRegRead(0x02) - return self.register[0] & 0x0F - - def setSpikeRejection(self, 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) - self.singRegWrite(0x02, 0x0F, srej & 0x0F) - - def printAllRegs(self): - self.singRegRead(0x00) - print("Reg 0x00: %02x"%self.register[0]) - self.singRegRead(0x01) - print("Reg 0x01: %02x"%self.register[0]) - self.singRegRead(0x02) - print("Reg 0x02: %02x"%self.register[0]) - self.singRegRead(0x03) - print("Reg 0x03: %02x"%self.register[0]) - self.singRegRead(0x04) - print("Reg 0x04: %02x"%self.register[0]) - self.singRegRead(0x05) - print("Reg 0x05: %02x"%self.register[0]) - self.singRegRead(0x06) - print("Reg 0x06: %02x"%self.register[0]) - self.singRegRead(0x07) - print("Reg 0x07: %02x"%self.register[0]) - self.singRegRead(0x08) - print("Reg 0x08: %02x"%self.register[0]) - - - diff --git a/RaspberryPi/Python/README.md b/RaspberryPi/Python/README.md deleted file mode 100644 index 58063ec..0000000 --- a/RaspberryPi/Python/README.md +++ /dev/null @@ -1,158 +0,0 @@ -## DFRobot_AS3935_Lib.py Library for Raspberry pi ---------------------------------------------------------- -This is the sample code for Gravity:Lightning Sensor, SKU: SEN0292. -## Table of Contents - -* [Installation](#installation) -* [Methods](#methods) - - - -## Installation -The Lightning Sensor should work with AS3935 -(https://github.com/DFRobot/DFRobot_AS3935/tree/master/RaspberryPi/Python) - -Run the program: - -```cpp - -$> python DFRobot_AS3935.py - -``` -## Methods - -```C++ - -/* - * @brief Init The Lightning Sensor - * - * @param address I2C address(1~3) - * bus I2C bus - */ -DFRobot_AS3935(address, bus); - -/* - * @brief Sensor reset - */ -def reset(self); - -/* - * @brief Configure sensor - * - * @param capacitance Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) - * location Indoor/outdoor mode selection - * disturber Enable/disable disturber detection - */ -def manualCal(self, capacitance, location, disturber); - -/* - * @brief Get mid-range type - * - * @return 0 Unknown src - * 1 Lightning detected - * 2 Disturber - * 3 Noise level too high - */ -def getInterruptSrc(self); - -/* - * @brief get lightning distance - * - * @return unit kilometer - */ -def getLightningDistKm(self); - -/* - * @brief get lightning energy intensity - * - * @return lightning energy intensity(0-1000) - */ -def getStrikeEnergyRaw(self); - -/* - * @brief Sets LCO_FDIV register - * - * @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively - */ -def setLcoFdiv(self,fdiv); - -/* - * @brief Set interrupt source - * - * @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO - */ -def setIrqOutputSource(self, irqSelect); - -/* - * @brief Set to the outdoor model - */ -def setOutdoors(self); - -/* - * @brief Set to the indoor model - */ -def setIndoors(self); - -/* - * @brief Disturber detection enabled - */ -def disturberEn(self); - -/* - * @brief Disturber detection disenabled - */ -def disturberDis(self); - -/* - * @brief Set the noise level - * - * @param 0~7,More than 7 will use the default value:2 - */ -def setNoiseFloorLv1(self, nfSel); - -/* - * @brief Get the noise level - * - * @return 0~7 - */ -def getNoiseFloorLv1(self); - -/* - * @brief Set an anti-interference rating - * - * @param 0~7,More than 7 will use the default value:2 - */ -def setWatchdogThreshold(self, wdth); - -/* - * @brief read WDTH - * - * @return 0~7 - */ -def getWatchdogThreshold(self); - -/* - * @brief Modify SREJ (spike rejection) - * - * @param 0~7,More than 7 will use the default value:2 - */ -def setSpikeRejection(self, srej); - -/* - * @brief read SREJ (spike rejection) - * - * @return 0~7 - */ -def getSpikeRejection(self); - -``` -## Credits - -Written by DFRobot_JH, 2018. (Welcome to our [website](https://www.dfrobot.com/)) - - - - - - - diff --git a/RaspberryPi/Python/example/DFRobot_AS3935_detailed.py b/RaspberryPi/Python/example/DFRobot_AS3935_detailed.py deleted file mode 100644 index 58a548e..0000000 --- a/RaspberryPi/Python/example/DFRobot_AS3935_detailed.py +++ /dev/null @@ -1,108 +0,0 @@ -# file DFRobot_AS3935_detailed.py -# -# SEN0290 Lightning Sensor -# This sensor can detect lightning and display the distance and intensity of the lightning within 40 km -# It can be set as indoor or outdoor mode. -# The module has three I2C, these addresses are: -# AS3935_ADD1 0x01 A0 = 1 A1 = 0 -# AS3935_ADD2 0x02 A0 = 0 A1 = 1 -# AS3935_ADD3 0x03 A0 = 1 A1 = 1 -# -# -# Copyright [DFRobot](http://www.dfrobot.com), 2018 -# Copyright GNU Lesser General Public License -# -# version V1.0 -# date 2018-11-28 - -import sys -sys.path.append('../') -import time -from DFRobot_AS3935_Lib import DFRobot_AS3935 -import RPi.GPIO as GPIO -from datetime import datetime - -#I2C address -AS3935_I2C_ADDR1 = 0X01 -AS3935_I2C_ADDR2 = 0X02 -AS3935_I2C_ADDR3 = 0X03 - -#Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) -AS3935_CAPACITANCE = 96 -IRQ_PIN = 7 - -GPIO.setmode(GPIO.BOARD) - -sensor = DFRobot_AS3935(AS3935_I2C_ADDR3, bus = 1) -if (sensor.reset()): - print("init sensor sucess.") -else: - print("init sensor fail") - while True: - pass -#Configure sensor -sensor.powerUp() - -#set indoors or outdoors models -sensor.setIndoors() -#sensor.setOutdoors() - -#disturber detection -sensor.disturberEn() -#sensor.disturberDis() - -sensor.setIrqOutputSource(0) -time.sleep(0.5) -#set capacitance -sensor.setTuningCaps(AS3935_CAPACITANCE) - -# Connect the IRQ and GND pin to the oscilloscope. -# uncomment the following sentences to fine tune the antenna for better performance. -# This will dispaly the antenna's resonance frequency/16 on IRQ pin (The resonance frequency will be divided by 16 on this pin) -# Tuning AS3935_CAPACITANCE to make the frequency within 500/16 kHz plus 3.5% to 500/16 kHz minus 3.5% -# -# sensor.setLcoFdiv(0) -# sensor.setIrqOutputSource(3) - -#Set the noise level,use a default value greater than 7 -sensor.setNoiseFloorLv1(2) -#noiseLv = sensor.getNoiseFloorLv1() - -#used to modify WDTH,alues should only be between 0x00 and 0x0F (0 and 7) -sensor.setWatchdogThreshold(2) -#wtdgThreshold = sensor.getWatchdogThreshold() - -#used to modify SREJ (spike rejection),values should only be between 0x00 and 0x0F (0 and 7) -sensor.setSpikeRejection(2) -#spikeRejection = sensor.getSpikeRejection() - -#view all register data -#sensor.printAllRegs() - -def callback_handle(channel): - global sensor - time.sleep(0.005) - intSrc = sensor.getInterruptSrc() - if intSrc == 1: - lightningDistKm = sensor.getLightningDistKm() - print('Lightning occurs!') - print('Distance: %dkm'%lightningDistKm) - - lightningEnergyVal = sensor.getStrikeEnergyRaw() - print('Intensity: %d '%lightningEnergyVal) - elif intSrc == 2: - print('Disturber discovered!') - elif intSrc == 3: - print('Noise level too high!') - else: - pass -#Set to input mode -GPIO.setup(IRQ_PIN, GPIO.IN) -#Set the interrupt pin, the interrupt function, rising along the trigger -GPIO.add_event_detect(IRQ_PIN, GPIO.RISING, callback = callback_handle) -print("start lightning detect.") - -while True: - time.sleep(1.0) - - diff --git a/RaspberryPi/Python/example/DFRobot_AS3935_ordinary.py b/RaspberryPi/Python/example/DFRobot_AS3935_ordinary.py deleted file mode 100644 index ef8e723..0000000 --- a/RaspberryPi/Python/example/DFRobot_AS3935_ordinary.py +++ /dev/null @@ -1,94 +0,0 @@ -# file DFRobot_AS3935_ordinary.py -# -# SEN0290 Lightning Sensor -# This sensor can detect lightning and display the distance and intensity of the lightning within 40 km -# It can be set as indoor or outdoor mode. -# The module has three I2C, these addresses are: -# AS3935_ADD1 0x01 A0 = 1 A1 = 0 -# AS3935_ADD2 0x02 A0 = 0 A1 = 1 -# AS3935_ADD3 0x03 A0 = 1 A1 = 1 -# -# -# Copyright [DFRobot](http://www.dfrobot.com), 2018 -# Copyright GNU Lesser General Public License -# -# version V1.0 -# date 2018-11-28 - -import sys -sys.path.append('../') -import time -from DFRobot_AS3935_Lib import DFRobot_AS3935 -import RPi.GPIO as GPIO -from datetime import datetime - -#I2C address -AS3935_I2C_ADDR1 = 0X01 -AS3935_I2C_ADDR2 = 0X02 -AS3935_I2C_ADDR3 = 0X03 - -#Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) -AS3935_CAPACITANCE = 96 -IRQ_PIN = 7 - -#Indoor/outdoor mode selection -AS3935_INDOORS = 0 -AS3935_OUTDOORS = 1 -AS3935_MODE = AS3935_INDOORS - -#Enable/disable disturber detection -AS3935_DIST_DIS = 0 -AS3935_DIST_EN = 1 -AS3935_DIST = AS3935_DIST_EN - -GPIO.setmode(GPIO.BOARD) - -sensor = DFRobot_AS3935(AS3935_I2C_ADDR3, bus = 1) -if (sensor.reset()): - print("init sensor sucess.") -else: - print("init sensor fail") - while True: - pass - -#Configure sensor -sensor.manualCal(AS3935_CAPACITANCE, AS3935_MODE, AS3935_DIST) - -# Connect the IRQ and GND pin to the oscilloscope. -# uncomment the following sentences to fine tune the antenna for better performance. -# This will dispaly the antenna's resonance frequency/16 on IRQ pin (The resonance frequency will be divided by 16 on this pin) -# Tuning AS3935_CAPACITANCE to make the frequency within 500/16 kHz plus 3.5% to 500/16 kHz minus 3.5% -# -# sensor.setLcoFdiv(0) -# sensor.setIrqOutputSource(3) - -#view all register data -#sensor.printAllRegs() - -def callback_handle(channel): - global sensor - time.sleep(0.005) - intSrc = sensor.getInterruptSrc() - if intSrc == 1: - lightningDistKm = sensor.getLightningDistKm() - print('Lightning occurs!') - print('Distance: %dkm'%lightningDistKm) - - lightningEnergyVal = sensor.getStrikeEnergyRaw() - print('Intensity: %d '%lightningEnergyVal) - elif intSrc == 2: - print('Disturber discovered!') - elif intSrc == 3: - print('Noise level too high!') - else: - pass -#Set to input mode -GPIO.setup(IRQ_PIN, GPIO.IN) -#Set the interrupt pin, the interrupt function, rising along the trigger -GPIO.add_event_detect(IRQ_PIN, GPIO.RISING, callback = callback_handle) -print("start lightning detect.") - -while True: - time.sleep(1.0) - - diff --git a/examples/DFRobot_AS3935_lightning_sensor_detailed/DFRobot_AS3935_lightning_sensor_detailed.ino b/examples/DFRobotAS3935LightningSensorDetailed/DFRobotAS3935LightningSensorDetailed.ino similarity index 79% rename from examples/DFRobot_AS3935_lightning_sensor_detailed/DFRobot_AS3935_lightning_sensor_detailed.ino rename to examples/DFRobotAS3935LightningSensorDetailed/DFRobotAS3935LightningSensorDetailed.ino index 67a3c72..40b141a 100644 --- a/examples/DFRobot_AS3935_lightning_sensor_detailed/DFRobot_AS3935_lightning_sensor_detailed.ino +++ b/examples/DFRobotAS3935LightningSensorDetailed/DFRobotAS3935LightningSensorDetailed.ino @@ -1,21 +1,20 @@ /*! - file DFRobot_AS3935_lightning_sensor.ino - - SEN0290 Lightning Sensor - This sensor can detect lightning and display the distance and intensity of the lightning within 40 km - It can be set as indoor or outdoor mode. - The module has three I2C, these addresses are: - AS3935_ADD1 0x01 A0 = 1 A1 = 0 - AS3935_ADD2 0x02 A0 = 0 A1 = 1 - AS3935_ADD3 0x03 A0 = 1 A1 = 1 - - - Copyright [DFRobot](http://www.dfrobot.com), 2018 - Copyright GNU Lesser General Public License + * @file DFRobot_AS3935_lightning_sensor_detailed.ino + * @brief SEN0290 Lightning Sensor + * @n This sensor can detect lightning and display the distance and intensity of the lightning within 40 km + * @n It can be set as indoor or outdoor mode. + * @n The module has three I2C, these addresses are: + * @n AS3935_ADD1 0x01 A0 = 1 A1 = 0 + * @n AS3935_ADD2 0x02 A0 = 0 A1 = 1 + * @n AS3935_ADD3 0x03 A0 = 1 A1 = 1 + * @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 + */ - version V1.1 - date 2021-08-24 -*/ #include "DFRobot_AS3935_I2C.h" @@ -28,8 +27,6 @@ volatile int8_t AS3935IsrTrig = 0; #define IRQ_PIN 2 #endif - - // Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) #define AS3935_CAPACITANCE 96 @@ -48,8 +45,7 @@ void setup() lightning0.setI2CAddress(AS3935_ADD3); - while (lightning0.begin() != 0) - { + while (lightning0.begin() != 0){ Serial.print("."); } lightning0.defInit(); @@ -109,8 +105,7 @@ void loop() // Get interrupt source uint8_t intSrc = lightning0.getInterruptSrc(); - if (intSrc == 1) - { + if (intSrc == 1){ // Get rid of non-distance data uint8_t lightningDistKm = lightning0.getLightningDistKm(); Serial.println("Lightning occurs!"); @@ -123,16 +118,11 @@ void loop() Serial.print("Intensity: "); Serial.print(lightningEnergyVal); Serial.println(""); - } - else if (intSrc == 2) - { + }else if (intSrc == 2){ Serial.println("Disturber discovered!"); - } - else if (intSrc == 3) - { + }else if (intSrc == 3){ Serial.println("Noise level too high!"); } - //View register data //lightning0.printAllRegs(); } diff --git a/examples/DFRobot_AS3935_lightning_sensor_ordinary/DFRobot_AS3935_lightning_sensor_ordinary.ino b/examples/DFRobotAS3935LightningSensorOrdinary/DFRobotAS3935LightningSensorOrdinary.ino similarity index 76% rename from examples/DFRobot_AS3935_lightning_sensor_ordinary/DFRobot_AS3935_lightning_sensor_ordinary.ino rename to examples/DFRobotAS3935LightningSensorOrdinary/DFRobotAS3935LightningSensorOrdinary.ino index 27949db..340826b 100644 --- a/examples/DFRobot_AS3935_lightning_sensor_ordinary/DFRobot_AS3935_lightning_sensor_ordinary.ino +++ b/examples/DFRobotAS3935LightningSensorOrdinary/DFRobotAS3935LightningSensorOrdinary.ino @@ -1,20 +1,19 @@ /*! - file DFRobot_AS3935_lightning_sensor.ino - - SEN0290 Lightning Sensor - This sensor can detect lightning and display the distance and intensity of the lightning within 40 km - It can be set as indoor or outdoor mode. - The module has three I2C, these addresses are: - AS3935_ADD1 0x01 A0 = 1 A1 = 0 - AS3935_ADD2 0x02 A0 = 0 A1 = 1 - AS3935_ADD3 0x03 A0 = 1 A1 = 1 - - Copyright [DFRobot](http://www.dfrobot.com), 2018 - Copyright GNU Lesser General Public License - - version V1.1 - date 2021-08-24 -*/ + * @file DFRobot_AS3935_lightning_sensor_ordinary.ino + * @brief SEN0290 Lightning Sensor + * @n This sensor can detect lightning and display the distance and intensity of the lightning within 40 km + * @n It can be set as indoor or outdoor mode. + * @n The module has three I2C, these addresses are: + * @n AS3935_ADD1 0x01 A0 = 1 A1 = 0 + * @n AS3935_ADD2 0x02 A0 = 0 A1 = 1 + * @n AS3935_ADD3 0x03 A0 = 1 A1 = 1 + * @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" @@ -52,8 +51,7 @@ void setup() Serial.begin(115200); Serial.println("DFRobot AS3935 lightning sensor begin!"); - while (lightning0.begin() != 0) - { + while (lightning0.begin() != 0){ Serial.print("."); } lightning0.defInit(); @@ -88,8 +86,7 @@ void loop() // Get interrupt source uint8_t intSrc = lightning0.getInterruptSrc(); - if (intSrc == 1) - { + if (intSrc == 1){ // Get rid of non-distance data uint8_t lightningDistKm = lightning0.getLightningDistKm(); Serial.println("Lightning occurs!"); @@ -102,18 +99,12 @@ void loop() Serial.print("Intensity: "); Serial.print(lightningEnergyVal); Serial.println(""); - } - else if (intSrc == 2) - { + }else if (intSrc == 2){ Serial.println("Disturber discovered!"); - } - else if (intSrc == 3) - { + }else if (intSrc == 3){ Serial.println("Noise level too high!"); } - } - //IRQ handler for AS3935 interrupts void AS3935_ISR() { diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..173384f --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=DFRobot_AS3935 +version=1.0.2 +author=DFRobot +maintainer=TangJie +sentence=DFRobot Lightning Sensor library.(SKU:SEN0290) +paragraph=DFRobot_AS3935 is the lightning sensor library of DFRobot. +category=Sensors +url=https://github.com/DFRobot/DFRobot_AS3935 +architectures=* diff --git a/python/raspberrypi/DFRobot_AS3935_Lib.py b/python/raspberrypi/DFRobot_AS3935_Lib.py new file mode 100644 index 0000000..db4e477 --- /dev/null +++ b/python/raspberrypi/DFRobot_AS3935_Lib.py @@ -0,0 +1,319 @@ +'''! + @file DFRobot_AS3935_Lib.py + @brief Define the DFRobot_AS3935 class infrastructure, the implementation of the base method + @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + @license The MIT License (MIT) + @author TangJie(jie.tamg@dfrobot.com) + @version V1.0.2 + @date 2021-9-28 + @url https://github.com/DFRobot/DFRobot_AS3935 +''' +import time +import smbus + +class DFRobot_AS3935: + def __init__(self, address, bus = 1): + self.address = address + self.i2cbus = smbus.SMBus(bus) + + def write_byte(self, register, value): + try: + self.i2cbus.write_byte_data(self.address, register, value) + return 1 + except: + return 0 + + def read_data(self, register): + self.register = self.i2cbus.read_i2c_block_data(self.address, register) + + '''! + @brief Configure sensor + @param capacitance Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) + @param location Indoor/outdoor mode selection + @param disturber Enable/disable disturber detection + ''' + def manual_cal(self, capacitance, location, disturber): + self.powerUp() + if location == 1: + self.setIndoors() + else: + self.setOutdoors() + + if disturber == 0: + self.disturberDis() + else: + self.disturberEn() + + self.setIrqOutputSource(0) + time.sleep(0.5) + self.setTuningCaps(capacitance) + + def set_tuning_caps(self, capVal): + #Assume only numbers divisible by 8 (because that's all the chip supports) + if capVal > 120: #cap_value out of range, assume highest capacitance + self.singRegWrite(0x08, 0x0F, 0x0F) #set capacitance bits to maximum + else: + self.singRegWrite(0x08, 0x0F, capVal >> 3) #set capacitance bits + self.singRegRead(0x08) + #print('capacitance set to 8x%d'%(self.register[0] & 0x0F)) + + def power_up(self): + #register 0x00, PWD bit: 0 (clears PWD) + self.singRegWrite(0x00, 0x01, 0x00) + self.calRCO() #run RCO cal cmd + self.singRegWrite(0x08, 0x20, 0x20) #set DISP_SRCO to 1 + time.sleep(0.002) + self.singRegWrite(0x08, 0x20, 0x00) #set DISP_SRCO to 0 + + def power_down(self): + #register 0x00, PWD bit: 0 (sets PWD) + self.singRegWrite(0x00, 0x01, 0x01) + + def cal_RCO(self): + self.writeByte(0x3D, 0x96) + time.sleep(0.002) + + '''! + @brief Disturber detection enabled + ''' + def set_indoors(self): + self.singRegWrite(0x00, 0x3E, 0x24) + print("set to indoors model") + + '''! + @brief Set to the outdoor model + ''' + def set_outdoors(self): + self.singRegWrite(0x00, 0x3E, 0x1C) + print("set to outdoors model") + + '''! + @brief Disturber detection disenabled + ''' + def disturber_dis(self): + #register 0x03, PWD bit: 5 (sets MASK_DIST) + self.singRegWrite(0x03, 0x20, 0x20) + print("disenable disturber detection") + + '''! + @brief Disturber detection enabled + ''' + def disturber_en(self): + #register 0x03, PWD bit: 5 (sets MASK_DIST) + self.singRegWrite(0x03, 0x20, 0x00) + print("enable disturber detection") + + def sing_reg_write(self, regAdd, dataMask, regData): + #start by reading original register data (only modifying what we need to) + self.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 + newRegData = (self.register[0] & ~dataMask)|(regData & dataMask) + #finally, write the data to the register + self.writeByte(regAdd, newRegData) + #print('wrt: %02x'%newRegData) + self.singRegRead(regAdd) + #print('Act: %02x'%self.register[0]) + + def sing_reg_read(self,regAdd): + self.readData(regAdd) + + '''! + @brief Get mid-range type + @return Return to interrupted state + @retval 0 Unknown src + @retval 1 Lightning detected + @retval 2 Disturber + @retval 3 Noise level too high + ''' + def get_interrupt_src(self): + #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 + time.sleep(0.03) #wait 3ms before reading (min 2ms per pg 22 of datasheet) + self.singRegRead(0x03) #read register, get rid of non-interrupt data + intSrc = self.register[0]&0x0F + if intSrc == 0x08: + return 1 #lightning caused interrupt + elif intSrc == 0x04: + return 2 #disturber detected + elif intSrc == 0x01: + return 3 #Noise level too high + else: + return 0 #interrupt result not expected + + '''! + @brief Sensor reset + ''' + def reset(self): + err = self.writeByte(0x3C, 0x96) + time.sleep(0.002) #wait 2ms to complete + return err + + '''! + @brief Sets LCO_FDIV register + @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively + ''' + def set_lco_fdiv(self,fdiv): + self.singRegWrite(0x03, 0xC0, (fdiv & 0x03) << 6) + + '''! + @brief Set interrupt source + @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + ''' + def set_irq_output_source(self, 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 irqSelect == 1: + self.singRegWrite(0x08, 0xE0, 0x20) #set only TRCO bit + elif irqSelect == 2: + self.singRegWrite(0x08, 0xE0, 0x40) #set only SRCO bit + elif irqSelect == 3: + self.singRegWrite(0x08, 0xE0, 0x80) #set only SRCO bit + else: + self.singRegWrite(0x08, 0xE0, 0x00) #clear IRQ pin display bits + + '''! + @brief get lightning distance + @return unit kilometer + ''' + def get_lightning_distKm(self): + self.singRegRead(0x07) #read register, get rid of non-distance data + return self.register[0]&0x3F + + '''! + @brief get lightning energy intensity + @return lightning energy intensity(0-1000) + ''' + def get_strike_energy_raw(self): + self.singRegRead(0x06) #MMSB, shift 8 bits left, make room for MSB + nrgyRaw = (self.register[0]&0x1F) << 8 + self.singRegRead(0x05) #read MSB + nrgyRaw |= self.register[0] + nrgyRaw <<= 8 #shift 8 bits left, make room for LSB + self.singRegRead(0x04) #read LSB, add to others + nrgyRaw |= self.register[0] + + return nrgyRaw/16777 + + def set_min_strikes(self, 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. + if minStrk < 5: + self.singRegWrite(0x02, 0x30, 0x00) + return 1 + elif minStrk < 9: + self.singRegWrite(0x02, 0x30, 0x10) + return 5 + elif minStrk < 16: + self.singRegWrite(0x02, 0x30, 0x20) + return 9 + else: + self.singRegWrite(0x02, 0x30, 0x30) + return 16 + + def clear_statistics(self): + #clear is accomplished by toggling CL_STAT bit 'high-low-high' (then set low to move on) + self.singRegWrite(0x02, 0x40, 0x40) #high + self.singRegWrite(0x02, 0x40, 0x00) #low + self.singRegWrite(0x02, 0x40, 0x40) #high + + '''! + @brief Get the noise level + @return 0~7 + ''' + def get_noise_floor_lv1(self): + #NF settings addres 0x01, bits 6:4 + #default setting of 010 at startup (datasheet, table 9) + self.singRegRead(0x01) #read register 0x01 + return (self.register[0] & 0x70) >> 4 #should return value from 0-7, see table 16 for info + + '''! + @brief Set the noise level + @param 0~7,More than 7 will use the default value:2 + ''' + def set_noise_floor_lv1(self, nfSel): + #NF settings addres 0x01, bits 6:4 + #default setting of 010 at startup (datasheet, table 9) + if nfSel <= 7: #nfSel within expected range + self.singRegWrite(0x01, 0x70, (nfSel & 0x07) << 4) + else: #out of range, set to default (power-up value 010) + self.singRegWrite(0x01, 0x70, 0x20) + + '''! + @brief read WDTH + @return Return interference level + ''' + def get_watchdog_threshold(self): + #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 0010 + #values should only be between 0x00 and 0x0F (0 and 7) + self.singRegRead(0x01) + return self.register[0] & 0x0F + + '''! + @brief Set an anti-interference rating + @param 0~7,More than 7 will use the default value:2 + ''' + def set_watchdog_threshold(self, 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) + self.singRegWrite(0x01, 0x0F, wdth & 0x0F) + + '''! + @brief read SREJ (spike rejection) + @return Return SREJ value + ''' + def get_spike_rejection(self): + #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) + self.singRegRead(0x02) + return self.register[0] & 0x0F + + '''! + @brief Modify SREJ (spike rejection) + @param 0~7,More than 7 will use the default value:2 + ''' + def set_spike_rejection(self, 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) + self.singRegWrite(0x02, 0x0F, srej & 0x0F) + + def print_all_regs(self): + self.singRegRead(0x00) + print("Reg 0x00: %02x"%self.register[0]) + self.singRegRead(0x01) + print("Reg 0x01: %02x"%self.register[0]) + self.singRegRead(0x02) + print("Reg 0x02: %02x"%self.register[0]) + self.singRegRead(0x03) + print("Reg 0x03: %02x"%self.register[0]) + self.singRegRead(0x04) + print("Reg 0x04: %02x"%self.register[0]) + self.singRegRead(0x05) + print("Reg 0x05: %02x"%self.register[0]) + self.singRegRead(0x06) + print("Reg 0x06: %02x"%self.register[0]) + self.singRegRead(0x07) + print("Reg 0x07: %02x"%self.register[0]) + self.singRegRead(0x08) + print("Reg 0x08: %02x"%self.register[0]) + + + diff --git a/python/raspberrypi/README.md b/python/raspberrypi/README.md new file mode 100644 index 0000000..14f465f --- /dev/null +++ b/python/raspberrypi/README.md @@ -0,0 +1,179 @@ +# DFRobot_AS3935 + + * [中文版](./README_CN.md) + +AS3935 Lightning Sensor can detect lightning and display the distance and intensity of the lightning without the disturbance of electric arc and noise. +It can be set as indoor or outdoor mode. + +![Product Image](./resources/images/SEN0290.png) + +## 产品链接(https://www.dfrobot.com/product-1828.html) + + SKU:SEN0290 + +## Table of Contents + + * [Summary](#summary) + * [Installation](#Installation) + * [Methods](#Methods) + * [Compatibility](#compatibility) + * [History](#history) + * [Credits](#credits) + +## Summary + +Input commands and read data from AS3935 modules + +1. Lightning sensor warns of lightning storm activity within a radius of 40km +2. Distance estimation to the head of the storm from overhead to 40km in 15 steps +3. Detects both cloud-to-ground and intra-cloud(cloud-to-cloud) flashes +4. Embedded man-made disturber rejection algorithm +5. Programmable detection levels enable threshold setting for optimal controls +6. Three i2c interfaces, switch freely to avoid site conflicts + +## Installation + +To use the library, first download it to Raspberry Pi, then open the routines folder.To execute a routine demox.py, type Python demox.py on the command line.For example, to execute the control_LEd.py routine, you need to enter: + +```python +python DFRobot_AS3935_detailed.py +``` + +## Methods + +```python + ''' + @brief Sensor reset + ''' + def reset(self); + + ''' + @brief Configure sensor + @param capacitance Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) + @param location Indoor/outdoor mode selection + @param disturber Enable/disable disturber detection + ''' + def manual_cal(self, capacitance, location, disturber); + + ''' + @brief Get mid-range type + @return Return to interrupted state + @retval 0 Unknown src + @retval 1 Lightning detected + @retval 2 Disturber + @retval 3 Noise level too high + ''' + def get_interrupt_src(self); + + ''' + @brief get lightning distance + @return unit kilometer + ''' + def get_lightning_distKm(self); + + ''' + @brief get lightning energy intensity + @return lightning energy intensity(0-1000) + ''' + def get_strike_energy_raw(self); + + ''' + @brief Sets LCO_FDIV register + @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively + ''' + def set_lco_fdiv(self,fdiv); + + ''' + @brief Set interrupt source + @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + ''' + def set_irq_output_source(self, irqSelect); + + ''' + @brief Set to the outdoor model + ''' + def set_outdoors(self); + + ''' + @brief Set to the indoor model + ''' + def set_indoors(self); + + ''' + @brief Disturber detection enabled + ''' + def disturber_en(self); + + ''' + @brief Disturber detection disenabled + ''' + def disturber_dis(self); + + ''' + @brief Set the noise level + @param 0~7,More than 7 will use the default value:2 + ''' + def set_noise_floor_lv1(self, nfSel); + + ''' + @brief Get the noise level + @return 0~7 + ''' + def get_noise_floor_lv1(self); + + ''' + @brief Set an anti-interference rating + @param 0~7,More than 7 will use the default value:2 + ''' + def set_watchdog_threshold(self, wdth); + + ''' + @brief read WDTH + @return 0~7 + ''' + def get_watchdog_threshold(self); + + ''' + @brief Modify SREJ (spike rejection) + @param 0~7,More than 7 will use the default value:2 + ''' + def set_spike_rejection(self, srej); + + ''' + @brief read SREJ (spike rejection) + @return 0~7 + ''' + def get_spike_rejection(self); +``` +## Compatibility + +* RaspberryPi Version + +| Board | Work Well | Work Wrong | Untested | Remarks | +| ------------ | :-------: | :--------: | :------: | ------- | +| RaspberryPi2 | | | √ | | +| RaspberryPi3 | | | √ | | +| RaspberryPi4 | √ | | | | + +* Python Version + +| Python | Work Well | Work Wrong | Untested | Remarks | +| ------- | :-------: | :--------: | :------: | ------- | +| Python2 | √ | | | | +| Python3 | √ | | | | +## History + +- 2021/09/30 - Version 1.0.2 released. +- 2021/08/24 - Version 1.0.1 released. +- 2019/09/28 - Version 1.0.0 released. + +## Credits + +Written by TangJie(jie.Tang@dfrobot.com), 2019. (Welcome to our [website](https://www.dfrobot.com/)) + + + + + + + diff --git a/python/raspberrypi/README_CN.md b/python/raspberrypi/README_CN.md new file mode 100644 index 0000000..9b0754e --- /dev/null +++ b/python/raspberrypi/README_CN.md @@ -0,0 +1,173 @@ +# DFRobot_AS3935 + +* [English Version](./README.md) + +AS3935雷电传感器可以检测雷电,显示雷电的距离和强度,不受电弧和噪声的干扰 +可设置为室内或室外模式 + +![Product Image](./resources/images/SEN0290.png) + +## 产品链接(https://www.dfrobot.com.cn/goods-1889.html) + + SKU:SEN0290 + +## 目录 + + * [概述](#概述) + * [库安装](#库安装) + * [方法](#方法) + * [兼容性](#兼容性) + * [历史](#历史) + * [创作者](#创作者) + +## 概述 + +从AS3935模块中输入命令和读取数据 + +1. 闪电传感器对半径40公里以内的雷暴活动发出警报 +2. 从头顶到风暴顶部的距离估计为40公里,每15步 +3. 检测云对地和云内(云对云)闪烁 +4. 嵌入人工干扰抑制算法 +5. 可编程检测水平使阈值设置为最佳控制 +6. 三个i2c接口,自由切换避免站点冲突 + +## 库安装 + +要使用这个库,首先将库下载到Raspberry Pi,然后打开例程文件夹。要执行一个例程demox.py,请在命令行中输入python demox.py。例如,要执行control_led.py例程,你需要输入: + +```python +python DFRobot_AS3935_detailed.py +``` + +## 方法 + +```python + ''' + @brief 传感器重启 + ''' + def reset(self); + + ''' + @brief 配置传感器 + @param capacitance 天线调谐电容(必须是8,8 - 120pf的整数倍) + @param location 室内或室外模式选择 + @param disturber 启用/禁用干扰发射机检测 + ''' + def manual_cal(self, capacitance, location, disturber); + + ''' + @brief Get mid-range type + @return 返回中断状态 + @retval 0 Unknown src + @retval 1 Lightning detected + @retval 2 Disturber + @retval 3 Noise level too high + ''' + def get_interrupt_src(self); + + ''' + @brief 获取闪电距离 + @return 闪电距离(单位公里) + ''' + def get_lightning_distKm(self); + + ''' + @brief 获取闪电能力强度 + @return 闪电能力强度(0-1000) + ''' + def get_strike_energy_raw(self); + + ''' + @brief 设置 LCO_FDIV 寄存器 + @param fdiv 设置0, 1, 2或3的比率分别为16,32,64和128 + ''' + def set_lco_fdiv(self,fdiv); + + ''' + @brief 设置中断源 + @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + ''' + def set_irq_output_source(self, irqSelect); + + ''' + @brief 设置为室外模式 + ''' + def set_outdoors(self); + + ''' + @brief 设置为室内模式 + ''' + def set_indoors(self); + + ''' + @brief 中断检测使能 + ''' + def disturber_en(self); + + ''' + @brief 中断检测失能 + ''' + def disturber_dis(self); + + ''' + @brief 设置噪音等级 + @param 0~7,大于7将使用默认值:2 + ''' + def set_noise_floor_lv1(self, nfSel); + + ''' + @brief 获取噪音等级 + @return 0~7 + ''' + def get_noise_floor_lv1(self); + + ''' + @brief 设置抗干扰等级 + @param 0~7,大于7将使用默认值:2 + ''' + def set_watchdog_threshold(self, wdth); + + ''' + @brief 获取抗干扰等级 + @return 0~7 + ''' + def get_watchdog_threshold(self); + + ''' + @brief 修改 SREJ (毛刺抑制) + @param 0~7,大于7将使用默认值:2 + ''' + def set_spike_rejection(self, srej); + + ''' + @brief r获取ead SREJ (毛刺抑制) + @return 0~7 + ''' + def get_spike_rejection(self); +``` +## 兼容性 + +* 树莓派版本 + +| Board | 通过 | 未通过 | 未测试 | 备注 | +| ------------ | :-------: | :--------: | :------: | ------- | +| RaspberryPi2 | | | √ | | +| RaspberryPi3 | | | √ | | +| RaspberryPi4 | √ | | | | + +* Python 版本 + +| Python | 通过 | 未通过 | 未测试 | 备注 | +| ------- | :-------: | :--------: | :------: | ------- | +| Python2 | √ | | | | +| Python3 | √ | | | | + +## 历史 + +- 2021/09/30 - 1.0.2 版本 +- 2021/08/24 - 1.0.1 版本 +- 2019/09/28 - 1.0.0 版本 + +## 创作者 + +Written by TangJie(jie.Tang@dfrobot.com), 2019. (Welcome to our [website](https://www.dfrobot.com/)) diff --git a/python/raspberrypi/example/DFRobot_AS3935_detailed/DFRobot_AS3935_detailed.py b/python/raspberrypi/example/DFRobot_AS3935_detailed/DFRobot_AS3935_detailed.py new file mode 100644 index 0000000..bafc648 --- /dev/null +++ b/python/raspberrypi/example/DFRobot_AS3935_detailed/DFRobot_AS3935_detailed.py @@ -0,0 +1,107 @@ +''' + # @file DFRobot_AS3935_detailed.py + # @brief SEN0290 Lightning Sensor + # @n This sensor can detect lightning and display the distance and intensity of the lightning within 40 km + # @n It can be set as indoor or outdoor mode. + # @n The module has three I2C, these addresses are: + # @n AS3935_ADD1 0x01 A0 = 1 A1 = 0 + # @n AS3935_ADD2 0x02 A0 = 0 A1 = 1 + # @n AS3935_ADD3 0x03 A0 = 1 A1 = 1 + # @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + # @licence 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 +''' +import sys +sys.path.append('../') +import time +from DFRobot_AS3935_Lib import DFRobot_AS3935 +import RPi.GPIO as GPIO +from datetime import datetime + +#I2C address +AS3935_I2C_ADDR1 = 0X01 +AS3935_I2C_ADDR2 = 0X02 +AS3935_I2C_ADDR3 = 0X03 + +#Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) +AS3935_CAPACITANCE = 96 +IRQ_PIN = 7 + +GPIO.setmode(GPIO.BOARD) + +sensor = DFRobot_AS3935(AS3935_I2C_ADDR3, bus = 1) +if (sensor.reset()): + print("init sensor sucess.") +else: + print("init sensor fail") + while True: + pass +#Configure sensor +sensor.power_up() + +#set indoors or outdoors models +sensor.set_indoors() +#sensor.set_outdoors() + +#disturber detection +sensor.disturber_en() +#sensor.disturber_dis() + +sensor.set_irq_output_source(0) +time.sleep(0.5) +#set capacitance +sensor.set_tuning_caps(AS3935_CAPACITANCE) + +# Connect the IRQ and GND pin to the oscilloscope. +# uncomment the following sentences to fine tune the antenna for better performance. +# This will dispaly the antenna's resonance frequency/16 on IRQ pin (The resonance frequency will be divided by 16 on this pin) +# Tuning AS3935_CAPACITANCE to make the frequency within 500/16 kHz plus 3.5% to 500/16 kHz minus 3.5% +# +# sensor.setLco_fdiv(0) +# sensor.setIrq_output_source(3) + +#Set the noise level,use a default value greater than 7 +sensor.set_noise_floor_lv1(2) +#noiseLv = sensor.get_noise_floor_lv1() + +#used to modify WDTH,alues should only be between 0x00 and 0x0F (0 and 7) +sensor.set_watchdog_threshold(2) +#wtdgThreshold = sensor.get_watchdog_threshold() + +#used to modify SREJ (spike rejection),values should only be between 0x00 and 0x0F (0 and 7) +sensor.set_spike_rejection(2) +#spikeRejection = sensor.get_spike_rejection() + +#view all register data +#sensor.print_all_regs() + +def callback_handle(channel): + global sensor + time.sleep(0.005) + intSrc = sensor.get_interrupt_src() + if intSrc == 1: + lightning_distKm = sensor.get_lightning_distKm() + print('Lightning occurs!') + print('Distance: %dkm'%lightning_distKm) + + lightning_energy_val = sensor.get_strike_energy_raw() + print('Intensity: %d '%lightning_energy_val) + elif intSrc == 2: + print('Disturber discovered!') + elif intSrc == 3: + print('Noise level too high!') + else: + pass +#Set to input mode +GPIO.setup(IRQ_PIN, GPIO.IN) +#Set the interrupt pin, the interrupt function, rising along the trigger +GPIO.add_event_detect(IRQ_PIN, GPIO.RISING, callback = callback_handle) +print("start lightning detect.") + +while True: + time.sleep(1.0) + + diff --git a/python/raspberrypi/example/DFRobot_AS3935_ordinary/DFRobot_AS3935_ordinary.py b/python/raspberrypi/example/DFRobot_AS3935_ordinary/DFRobot_AS3935_ordinary.py new file mode 100644 index 0000000..402ac55 --- /dev/null +++ b/python/raspberrypi/example/DFRobot_AS3935_ordinary/DFRobot_AS3935_ordinary.py @@ -0,0 +1,94 @@ +''' + # @file DFRobot_AS3935_ordinary.py + # @brief SEN0290 Lightning Sensor + # @n This sensor can detect lightning and display the distance and intensity of the lightning within 40 km + # @n It can be set as indoor or outdoor mode. + # @n The module has three I2C, these addresses are: + # @n AS3935_ADD1 0x01 A0 = 1 A1 = 0 + # @n AS3935_ADD2 0x02 A0 = 0 A1 = 1 + # @n AS3935_ADD3 0x03 A0 = 1 A1 = 1 + # @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + # @licence 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 +''' + +import sys +sys.path.append('../') +import time +from DFRobot_AS3935_Lib import DFRobot_AS3935 +import RPi.GPIO as GPIO +from datetime import datetime + +#I2C address +AS3935_I2C_ADDR1 = 0X01 +AS3935_I2C_ADDR2 = 0X02 +AS3935_I2C_ADDR3 = 0X03 + +#Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) +AS3935_CAPACITANCE = 96 +IRQ_PIN = 7 + +#Indoor/outdoor mode selection +AS3935_INDOORS = 0 +AS3935_OUTDOORS = 1 +AS3935_MODE = AS3935_INDOORS + +#Enable/disable disturber detection +AS3935_DIST_DIS = 0 +AS3935_DIST_EN = 1 +AS3935_DIST = AS3935_DIST_EN + +GPIO.setmode(GPIO.BOARD) + +sensor = DFRobot_AS3935(AS3935_I2C_ADDR3, bus = 1) +if (sensor.reset()): + print("init sensor sucess.") +else: + print("init sensor fail") + while True: + pass + +#Configure sensor +sensor.manual_cal(AS3935_CAPACITANCE, AS3935_MODE, AS3935_DIST) + +# Connect the IRQ and GND pin to the oscilloscope. +# uncomment the following sentences to fine tune the antenna for better performance. +# This will dispaly the antenna's resonance frequency/16 on IRQ pin (The resonance frequency will be divided by 16 on this pin) +# Tuning AS3935_CAPACITANCE to make the frequency within 500/16 kHz plus 3.5% to 500/16 kHz minus 3.5% +# +# sensor.setLco_fdiv(0) +# sensor.set_irq_output_source(3) + +#view all register data +#sensor.print_all_regs() + +def callback_handle(channel): + global sensor + time.sleep(0.005) + intSrc = sensor.get_interrupt_src() + if intSrc == 1: + lightning_distKm = sensor.get_lightning_distKm() + print('Lightning occurs!') + print('Distance: %dkm'%lightning_distKm) + + lightning_energy_val = sensor.get_strike_energy_raw() + print('Intensity: %d '%lightning_energy_val) + elif intSrc == 2: + print('Disturber discovered!') + elif intSrc == 3: + print('Noise level too high!') + else: + pass +#Set to input mode +GPIO.setup(IRQ_PIN, GPIO.IN) +#Set the interrupt pin, the interrupt function, rising along the trigger +GPIO.add_event_detect(IRQ_PIN, GPIO.RISING, callback = callback_handle) +print("start lightning detect.") + +while True: + time.sleep(1.0) + + diff --git a/readme.md b/readme.md index 07adc41..c72ca0c 100644 --- a/readme.md +++ b/readme.md @@ -1,202 +1,229 @@ -# AS3935 +# DFRobot_AS3935 -AS3935 Lightning Sensor can detect lightning and display the distance and intensity of the lightning without the disturbance of electric arc and noise.
-It can be set as indoor or outdoor mode.
+ * [中文版](./README_CN.md) + +AS3935 Lightning Sensor can detect lightning and display the distance and intensity of the lightning without the disturbance of electric arc and noise. +It can be set as indoor or outdoor mode. -## DFRobot_AS3934 Library for Arduino ---------------------------------------------------------- -Provide a library faciltates operations in the as3935 modules. +![Product Image](./resources/images/SEN0290.png) -## Table of Contents +## product link (https://www.dfrobot.com/product-1828.html) -* [Summary](#summary) -* [Feature](#feature) -* [Installation](#installation) -* [Methods](#methods) + SKU:SEN0290 -* [Compatibility](#compatibility) -* [Credits](#credits) - - +## Table of Contents + + * [Summary](#summary) + * [Installation](#Installation) + * [Methods](#Methods) + * [Compatibility](#compatibility) + * [History](#history) + * [Credits](#credits) ## Summary Input commands and read data from AS3935 modules -## Feature - -1. Lightning sensor warns of lightning storm activity within a radius of 40km
-2. Distance estimation to the head of the storm from overhead to 40km in 15 steps
-3. Detects both cloud-to-ground and intra-cloud(cloud-to-cloud) flashes
-4. Embedded man-made disturber rejection algorithm
-5. Programmable detection levels enable threshold setting for optimal controls
-6. Three i2c interfaces, switch freely to avoid site conflicts
+1. Lightning sensor warns of lightning storm activity within a radius of 40km +2. Distance estimation to the head of the storm from overhead to 40km in 15 steps +3. Detects both cloud-to-ground and intra-cloud(cloud-to-cloud) flashes +4. Embedded man-made disturber rejection algorithm +5. Programmable detection levels enable threshold setting for optimal controls +6. Three i2c interfaces, switch freely to avoid site conflicts ## Installation -Download the library ZIP file and unzip it to the Arduino folder of the library.
+To use this library, first download the library file, paste it into the \Arduino\libraries directory, then open the examples folder and run the demo in the folder. ## Methods ```C++ - -#include "DFRobot_AS3935_I2C.h" - -/* - * @brief AS3935 object - * - * @param irqx irq pin - * devAddx i2c address - */ -DFRobot_AS3935_I2C(uint8_t irqx, uint8_t devAddx); - -/* - * @brief AS3935 object - * - * @param irqx irq pin - */ -DFRobot_AS3935_I2C(uint8_t irqx); - -/* - * @brief reset registers to default - * - * @return 0 success - */ -int defInit(void); - -/* - * @brief set i2c address - * - * @param devAddx i2c address - */ -void setI2CAddress(uint8_t devAddx); - -/* - * @brief manual calibration - * - * @param capacitance capacitance - * location location - * disturber disturber - */ -void manualCal(uint8_t capacitance, uint8_t location, uint8_t disturber); - -/* - * @brief view register data - */ -void printAllRegs(void); - -/* - * @brief get interrupt source - * - * @return 0 interrupt result not expected - * 1 lightning caused interrupt - * 2 disturber detected - * 3 Noise level too high - */ -uint8_t getInterruptSrc(void); - -/* - * @brief get lightning distance - * - * @return unit kilometer - */ -uint8_t getLightningDistKm(void); - -/* - * @brief get lightning energy intensity - * - * @return lightning energy intensity(0-1000) - */ -uint32_t getStrikeEnergyRaw(void); - -/* - * @brief Set to the outdoor model - */ -void setOutdoors(void); - -/* - * @brief Set to the indoor model - */ -void setIndoors(void); - -/* - * @brief Disturber detection enabled - */ -void disturberEn(void); - -/* - * @brief Disturber detection disenabled - */ -void disturberDis(void); - -/* - * @brief Sets LCO_FDIV register - * - * @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively - */ -void setLcoFdiv(uint8_t fdiv); - -/* - * @brief Set interrupt source - * - * @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO - */ -void setIRQOutputSource(uint8_t irqSelect); - -/* - * @brief Set the noise level - * - * @param 0~7,More than 7 will use the default value:2 - */ -void setNoiseFloorLvl(uint8_t nfSel); - -/* - * @brief Get the noise level - * - * @return 0~7 - */ -uint8_t getNoiseFloorLvl(void); - -/* - * @brief Set an anti-interference rating - * - * @param 0~7,More than 7 will use the default value:2 - */ -void setWatchdogThreshold(uint8_t wdth); - -/* - * @brief read WDTH - * - * @return 0~7 - */ -uint8_t getWatchdogThreshold(void); - -/* - * @brief Modify SREJ (spike rejection) - * - * @param 0~7,More than 7 will use the default value:2 - */ -void setSpikeRejection(uint8_t srej); - -/* - * @brief read SREJ (spike rejection) - * - * @return 0~7 - */ -uint8_t getSpikeRejection(void); - + /** + * @fn begin + * @brief I2C init + * @return uint8_t type, indicates the initialization status + * @retval 0 succeed + * @retval 1 failure + */ + uint8_t begin(void); + + /** + * @fn setI2CAddress + * @brief set i2c address + * @param devAddx i2c address + * @return None + */ + void setI2CAddress(uint8_t devAddx); + + /** + * @fn manualCal + * @brief manual calibration + * @param capacitance capacitance + * @param location location + * @param disturber disturber + * @return None + */ + void manualCal(uint8_t capacitance, uint8_t location, uint8_t disturber); + + /** + * @fn defInit + * @brief reset registers to default + * @return int type,represents rest state + * @retval 0 success + */ + int defInit(void); + + /** + * @fn disturberEn + * @brief Disturber detection enabled + * @return None + */ + void disturberEn(void); + + /** + * @fn disturberDis + * @brief Disturber detection disenabled + * @return None + */ + void disturberDis(void); + + /** + * @fn setIRQOutputSource + * @brief Set interrupt source + * @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + * @return None + */ + void setIRQOutputSource(uint8_t irqSelect); + + /** + * @fn setTuningCaps + * @brief set capacitance + * @param capVal size + * @return None + */ + void setTuningCaps(uint8_t capVal); + + /** + * @fn getInterruptSrc + * @brief get interrupt source + * @return uint8_t type,returns the interrupt source type + * @retval 0 interrupt result not expected + * @retval 1 lightning caused interrupt + * @retval 2 disturber detected + * @retval 3 Noise level too high + */ + uint8_t getInterruptSrc(void); + + /** + * @fn getLightningDistKm + * @brief get lightning distance + * @return unit kilometer + */ + uint8_t getLightningDistKm(void); + + /** + * @fn getStrikeEnergyRaw + * @brief get lightning energy intensity + * @return lightning energy intensity(0-1000) + */ + uint32_t getStrikeEnergyRaw(void); + + /** + * @fn setIndoors + * @brief Set to the indoor model + * @return None + */ + void setIndoors(void); + + /** + * @fn setOutdoors + * @brief Set to the outdoor model + * @return None + */ + void setOutdoors(void); + + /** + * @fn setOutdoors + * @brief Get the noise level + * @return Return noise level + */ + uint8_t getNoiseFloorLvl(void); + + /** + * @fn setNoiseFloorLvl + * @brief Set the noise level + * @param 0~7,More than 7 will use the default value:2 + * @return None + */ + void setNoiseFloorLvl(uint8_t nfSel); + + /** + * @fn getWatchdogThreshold + * @brief read WDTH + * @return Return interference level + */ + uint8_t getWatchdogThreshold(void); + + /** + * @fn setWatchdogThreshold + * @brief Set an anti-interference rating + * @param 0~7,More than 7 will use the default value:2 + * @return None + */ + void setWatchdogThreshold(uint8_t wdth); + + /** + * @fn getSpikeRejection + * @brief read SREJ (spike rejection) + * @return Return SREJ value + */ + uint8_t getSpikeRejection(void); + + /** + * @fn setSpikeRejection + * @brief Modify SREJ (spike rejection) + * @param 0~7,More than 7 will use the default value:2 + * @return None + */ + void setSpikeRejection(uint8_t srej); + + /** + * @fn setLcoFdiv + * @brief Sets LCO_FDIV register + * @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively + * @return None + */ + void setLcoFdiv(uint8_t fdiv); + + /** + * @fn printAllRegs + * @brief view register data + * @return None + */ + void printAllRegs(void); + + /** + * @fn powerUp + * @brief Configure sensor + * @return None + */ + void powerUp(void); + ``` - - - ## Compatibility -MCU | Work Well | Work Wrong | Untested | Remarks ------------------- | :----------: | :----------: | :---------: | ----- -Arduino uno | √ | | | - esp8266 | √ | | | +MCU | Work Well | Work Wrong | Untested | Remarks | +------------------ | :----------: | :----------: | :---------: | :-----: | +Arduino uno | √ | | | | +esp8266 | √ | | | | +## History +- 2021/09/30 - Version 1.0.2 released. +- 2021/08/24 - Version 1.0.1 released. +- 2019/09/28 - Version 1.0.0 released. + ## Credits -Written by DFRobot_JH, 2018. (Welcome to our [website](https://www.dfrobot.com/)) +Written by TangJie(jie.Tang@dfrobot.com), 2019. (Welcome to our [website](https://www.dfrobot.com/)) + diff --git a/resources/images/SEN0290.png b/resources/images/SEN0290.png new file mode 100644 index 0000000000000000000000000000000000000000..daa1f274e4e3ec0e2f67fe661b988fe454a41f09 GIT binary patch literal 112375 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 JGynJU{{aFRL=OM} literal 0 HcmV?d00001