pull/1/head
ouki-wang 6 years ago
commit ddca4bf74f
  1. 374
      DFRobot_AS3935_I2C.cpp
  2. 63
      DFRobot_AS3935_I2C.h
  3. 728
      I2C.cpp
  4. 76
      I2C.h
  5. 111
      examples/DFRobot_AS3935_lightning_I2c/DFRobot_AS3935_lightning_I2c.ino
  6. 60
      keywords.txt
  7. 114
      readme.md

@ -0,0 +1,374 @@
#include "DFRobot_AS3935_I2c.h"
DF_AS3935_I2C::DF_AS3935_I2C(uint8_t IRQx, uint8_t SIx, uint8_t DEVADDx)
{
_devadd = DEVADDx;
_si = SIx;
_irq = IRQx;
// initalize the chip select pins
pinMode(_si, OUTPUT);
pinMode(_irq, INPUT);
// set output pin initical condition
digitalWrite(_si, HIGH); // set pin high for I2C mode
}
void DF_AS3935_I2C::AS3935_SetI2CAddress(uint8_t DEVADDx)
{
if (DEVADDx == AS3935_ADD1)
{
_devadd=DEVADDx;
}
else if (DEVADDx == AS3935_ADD2)
{
_devadd=DEVADDx;
}
else
{
_devadd=AS3935_ADD3;
}
}
uint8_t DF_AS3935_I2C::_sing_reg_read(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
return RegData;
}
void DF_AS3935_I2C::_sing_reg_write(uint8_t RegAdd, uint8_t DataMask, uint8_t RegData)
{
// start by reading original register data (only modifying what we need to)
uint8_t OrigRegData = _sing_reg_read(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));
// finally, write the data to the register
I2c.write(_devadd, RegAdd, NewRegData);
Serial.print("wrt: ");
Serial.print(NewRegData,HEX);
Serial.print(" Act: ");
Serial.println(_sing_reg_read(RegAdd),HEX);
}
void DF_AS3935_I2C::AS3935_DefInit()
{
_AS3935_Reset(); // reset registers to default
}
void DF_AS3935_I2C::_AS3935_Reset()
{
// run PRESET_DEFAULT Direct Command to set all registers in default state
I2c.write(_devadd, (uint8_t)0x3C, (uint8_t)0x96);
delay(2); // wait 2ms to complete
}
void DF_AS3935_I2C::_CalRCO()
{
// run ALIB_RCO Direct Command to cal internal RCO
I2c.write(_devadd, (uint8_t)0x3D, (uint8_t)0x96);
delay(2); // wait 2ms to complete
}
void DF_AS3935_I2C::AS3935_PowerUp(void)
{
// power-up sequence based on datasheet, pg 23/27
// register 0x00, PWD bit: 0 (clears PWD)
_sing_reg_write(0x00, 0x01, 0x00);
_CalRCO(); // run RCO cal cmd
_sing_reg_write(0x08, 0x20, 0x20); // set DISP_SRCO to 1
delay(2);
_sing_reg_write(0x08, 0x20, 0x00); // set DISP_SRCO to 0
}
void DF_AS3935_I2C::AS3935_PowerDown(void)
{
// register 0x00, PWD bit: 0 (sets PWD)
_sing_reg_write(0x00, 0x01, 0x01);
Serial.println("AS3935 powered down");
}
void DF_AS3935_I2C::AS3935_DisturberEn(void)
{
// register 0x03, PWD bit: 5 (sets MASK_DIST)
_sing_reg_write(0x03, 0x20, 0x00);
Serial.println("disturber detection enabled");
}
void DF_AS3935_I2C::AS3935_DisturberDis(void)
{
// register 0x03, PWD bit: 5 (sets MASK_DIST)
_sing_reg_write(0x03, 0x20, 0x20);
}
void DF_AS3935_I2C::AS3935_SetIRQ_Output_Source(uint8_t irq_select)
{
// 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 == irq_select)
{
_sing_reg_write(0x08, 0xE0, 0x20); // set only TRCO bit
}
else if(2 == irq_select)
{
_sing_reg_write(0x08, 0xE0, 0x40); // set only SRCO bit
}
else if(3 == irq_select)
{
_sing_reg_write(0x08, 0xE0, 0x80); // set only LCO bit
}
else // assume 0
{
_sing_reg_write(0x08, 0xE0, 0x00); // clear IRQ pin display bits
}
}
void DF_AS3935_I2C::AS3935_SetTuningCaps(uint8_t cap_val)
{
// Assume only numbers divisible by 8 (because that's all the chip supports)
if(120 < cap_val) // cap_value out of range, assume highest capacitance
{
_sing_reg_write(0x08, 0x0F, 0x0F); // set capacitance bits to maximum
}
else
{
_sing_reg_write(0x08, 0x0F, (cap_val>>3)); // set capacitance bits
}
Serial.print("capacitance set to 8x");
Serial.println((_sing_reg_read(0x08) & 0x0F));
}
uint8_t DF_AS3935_I2C::AS3935_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 int_src = (_sing_reg_read(0x03) & 0x0F); // read register, get rid of non-interrupt data
if(0x08 == int_src)
{
return 1; // lightning caused interrupt
}
else if(0x04 == int_src)
{
return 2; // disturber detected
}
else if(0x01 == int_src)
{
return 3; // Noise level too high
}
else{return 0;} // interrupt result not expected
}
uint8_t DF_AS3935_I2C::AS3935_GetLightningDistKm(void)
{
uint8_t strike_dist = (_sing_reg_read(0x07) & 0x3F); // read register, get rid of non-distance data
return strike_dist;
}
uint32_t DF_AS3935_I2C::AS3935_GetStrikeEnergyRaw(void)
{
uint32_t nrgy_raw = ((_sing_reg_read(0x06) & 0x1F) << 8); // MMSB, shift 8 bits left, make room for MSB
nrgy_raw |= _sing_reg_read(0x05); // read MSB
nrgy_raw <<= 8; // shift 8 bits left, make room for LSB
nrgy_raw |= _sing_reg_read(0x04); // read LSB, add to others
return nrgy_raw/16777;
}
uint8_t DF_AS3935_I2C::AS3935_SetMinStrikes(uint8_t min_strk)
{
// 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 > min_strk)
{
_sing_reg_write(0x02, 0x30, 0x00);
return 1;
}
else if(9 > min_strk)
{
_sing_reg_write(0x02, 0x30, 0x10);
return 5;
}
else if(16 > min_strk)
{
_sing_reg_write(0x02, 0x30, 0x20);
return 9;
}
else
{
_sing_reg_write(0x02, 0x30, 0x30);
return 16;
}
}
void DF_AS3935_I2C::AS3935_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)
_sing_reg_write(0x00, 0x3E, 0x24);
Serial.println("set up for indoor operation");
}
void DF_AS3935_I2C::AS3935_SetOutdoors(void)
{
// AFE settings addres 0x00, bits 5:1 (01110, based on datasheet, pg 19, table 15)
_sing_reg_write(0x00, 0x3E, 0x1C);
Serial.println("set up for outdoor operation");
}
void DF_AS3935_I2C::AS3935_ClearStatistics(void)
{
// clear is accomplished by toggling CL_STAT bit 'high-low-high' (then set low to move on)
_sing_reg_write(0x02, 0x40, 0x40); // high
_sing_reg_write(0x02, 0x40, 0x00); // low
_sing_reg_write(0x02, 0x40, 0x40); // high
}
uint8_t DF_AS3935_I2C::AS3935_GetNoiseFloorLvl(void)
{
// NF settings addres 0x01, bits 6:4
// default setting of 010 at startup (datasheet, table 9)
uint8_t reg_raw = _sing_reg_read(0x01); // read register 0x01
return ((reg_raw & 0x70)>>4); // should return value from 0-7, see table 16 for info
}
void DF_AS3935_I2C::AS3935_SetNoiseFloorLvl(uint8_t nf_sel)
{
// NF settings addres 0x01, bits 6:4
// default setting of 010 at startup (datasheet, table 9)
if(7 >= nf_sel) // nf_sel within expected range
{
_sing_reg_write(0x01, 0x70, ((nf_sel & 0x07)<<4));
}
else
{ // out of range, set to default (power-up value 010)
_sing_reg_write(0x01, 0x70, 0x20);
}
}
uint8_t DF_AS3935_I2C::AS3935_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 reg_raw = _sing_reg_read(0x01);
return (reg_raw & 0x0F);
}
void DF_AS3935_I2C::AS3935_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 0001
// values should only be between 0x00 and 0x0F (0 and 7)
_sing_reg_write(0x01, 0x0F, (wdth & 0x0F));
}
uint8_t DF_AS3935_I2C::AS3935_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 reg_raw = _sing_reg_read(0x02);
return (reg_raw & 0x0F);
}
void DF_AS3935_I2C::AS3935_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)
_sing_reg_write(0x02, 0x0F, (srej & 0x0F));
}
void DF_AS3935_I2C::AS3935_SetLCO_FDIV(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.
_sing_reg_write(0x03, 0xC0, ((fdiv & 0x03) << 5));
}
void DF_AS3935_I2C::AS3935_PrintAllRegs(void)
{
Serial.print("Reg 0x00: ");
Serial.println(_sing_reg_read(0x00));
Serial.print("Reg 0x01: ");
Serial.println(_sing_reg_read(0x01));
Serial.print("Reg 0x02: ");
Serial.println(_sing_reg_read(0x02));
Serial.print("Reg 0x03: ");
Serial.println(_sing_reg_read(0x03));
Serial.print("Reg 0x04: ");
Serial.println(_sing_reg_read(0x04));
Serial.print("Reg 0x05: ");
Serial.println(_sing_reg_read(0x05));
Serial.print("Reg 0x06: ");
Serial.println(_sing_reg_read(0x06));
Serial.print("Reg 0x07: ");
Serial.println(_sing_reg_read(0x07));
Serial.print("Reg 0x08: ");
Serial.println(_sing_reg_read(0x08));
uint32_t nrgy_val = AS3935_GetStrikeEnergyRaw();
Serial.println(nrgy_val);
}
void DF_AS3935_I2C::AS3935_ManualCal(uint8_t capacitance, uint8_t location, uint8_t disturber)
{
// start by powering up
AS3935_PowerUp();
// indoors/outdoors next...
if(1 == location) // set outdoors if 1
{
AS3935_SetOutdoors();
}
else // set indoors if anything but 1
{
AS3935_SetIndoors();
}
// disturber cal
if(0 == disturber) // disabled if 0
{
AS3935_DisturberDis();
}
else // enabled if anything but 0
{
AS3935_DisturberEn();
}
AS3935_SetIRQ_Output_Source(0);
delay(500);
// capacitance first... directly write value here
AS3935_SetTuningCaps(capacitance);
Serial.println("AS3935 manual cal complete");
}
// a nice function would be to read the last 'x' strike data values....

@ -0,0 +1,63 @@
#ifndef DF_AS3935_I2C_h
#define DF_AS3935_I2C_h
#include "Arduino.h"
#include "avr/pgmspace.h"
#include "util/delay.h"
#include "stdlib.h"
#include "I2C.h"
// I2c address
#define AS3935_ADD3 0x03 // x03 - A0->high A1->high
#define AS3935_ADD2 0x02 // x02 - A0->low A1->high
#define AS3935_ADD1 0x01 // x01 - A0->high A1->low
class DF_AS3935_I2C
{
public:
DF_AS3935_I2C(uint8_t IRQx, uint8_t SIx, uint8_t DEVADDx);
/*! Set i2c address */
void AS3935_SetI2CAddress(uint8_t DEVADDx);
/*! Manual calibration */
void AS3935_ManualCal(uint8_t capacitance, uint8_t location, uint8_t disturber);
/*! reset registers to default */
void AS3935_DefInit(void);
void AS3935_PowerUp(void);
void AS3935_PowerDown(void);
void AS3935_DisturberEn(void);
void AS3935_DisturberDis(void);
void AS3935_SetIRQ_Output_Source(uint8_t irq_select);
void AS3935_SetTuningCaps(uint8_t cap_val);
/*! 0 = unknown src, 1 = lightning detected, 2 = disturber, 3 = Noise level too high */
uint8_t AS3935_GetInterruptSrc(void);
/*! Get rid of non-distance data */
uint8_t AS3935_GetLightningDistKm(void);
/*! Get lightning energy intensity */
uint32_t AS3935_GetStrikeEnergyRaw(void);
uint8_t AS3935_SetMinStrikes(uint8_t min_strk);
void AS3935_ClearStatistics(void);
void AS3935_SetIndoors(void);
void AS3935_SetOutdoors(void);
uint8_t AS3935_GetNoiseFloorLvl(void);
void AS3935_SetNoiseFloorLvl(uint8_t nf_sel);
uint8_t AS3935_GetWatchdogThreshold(void);
void AS3935_SetWatchdogThreshold(uint8_t wdth);
uint8_t AS3935_GetSpikeRejection(void);
void AS3935_SetSpikeRejection(uint8_t srej);
void AS3935_SetLCO_FDIV(uint8_t fdiv);
/*! View register data */
void AS3935_PrintAllRegs(void);
private:
uint8_t _irq, _si, _devadd;
uint8_t _sing_reg_read(uint8_t RegAdd);
void _sing_reg_write(uint8_t RegAdd, uint8_t DataMask, uint8_t RegData);
void _AS3935_Reset(void);
void _CalRCO(void);
};
#endif

@ -0,0 +1,728 @@
/*
I2C.cpp - I2C library
Copyright (c) 2011-2012 Wayne Truchsess. All right reserved.
Rev 5.0 - January 24th, 2012
- Removed the use of interrupts completely from the library
so TWI state changes are now polled.
- Added calls to lockup() function in most functions
to combat arbitration problems
- Fixed scan() procedure which left timeouts enabled
and set to 80msec after exiting procedure
- Changed scan() address range back to 0 - 0x7F
- Removed all Wire legacy functions from library
- A big thanks to Richard Baldwin for all the testing
and feedback with debugging bus lockups!
Rev 4.0 - January 14th, 2012
- Updated to make compatible with 8MHz clock frequency
Rev 3.0 - January 9th, 2012
- Modified library to be compatible with Arduino 1.0
- Changed argument type from boolean to uint8_t in pullUp(),
setSpeed() and receiveByte() functions for 1.0 compatability
- Modified return values for timeout feature to report
back where in the transmission the timeout occured.
- added function scan() to perform a bus scan to find devices
attached to the I2C bus. Similar to work done by Todbot
and Nick Gammon
Rev 2.0 - September 19th, 2011
- Added support for timeout function to prevent
and recover from bus lockup (thanks to PaulS
and CrossRoads on the Arduino forum)
- Changed return type for stop() from void to
uint8_t to handle timeOut function
Rev 1.0 - August 8th, 2011
This is a modified version of the Arduino Wire/TWI
library. Functions were rewritten to provide more functionality
and also the use of Repeated Start. Some I2C devices will not
function correctly without the use of a Repeated Start. The
initial version of this library only supports the Master.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <inttypes.h>
#include "I2C.h"
uint8_t I2C::bytesAvailable = 0;
uint8_t I2C::bufferIndex = 0;
uint8_t I2C::totalBytes = 0;
uint16_t I2C::timeOutDelay = 0;
I2C::I2C()
{
}
////////////// Public Methods ////////////////////////////////////////
void I2C::begin()
{
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
// activate internal pull-ups for twi
// as per note from atmega8 manual pg167
sbi(PORTC, 4);
sbi(PORTC, 5);
#else
// activate internal pull-ups for twi
// as per note from atmega128 manual pg204
sbi(PORTD, 0);
sbi(PORTD, 1);
#endif
// initialize twi prescaler and bit rate
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
TWBR = ((F_CPU / 100000) - 16) / 2;
// enable twi module and acks
TWCR = _BV(TWEN) | _BV(TWEA);
}
void I2C::end()
{
TWCR = 0;
}
void I2C::timeOut(uint16_t _timeOut)
{
timeOutDelay = _timeOut;
}
void I2C::setSpeed(uint8_t _fast)
{
if(!_fast)
{
TWBR = ((F_CPU / 100000) - 16) / 2;
}
else
{
TWBR = ((F_CPU / 400000) - 16) / 2;
}
}
void I2C::pullup(uint8_t activate)
{
if(activate)
{
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
// activate internal pull-ups for twi
// as per note from atmega8 manual pg167
sbi(PORTC, 4);
sbi(PORTC, 5);
#else
// activate internal pull-ups for twi
// as per note from atmega128 manual pg204
sbi(PORTD, 0);
sbi(PORTD, 1);
#endif
}
else
{
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
// deactivate internal pull-ups for twi
// as per note from atmega8 manual pg167
cbi(PORTC, 4);
cbi(PORTC, 5);
#else
// deactivate internal pull-ups for twi
// as per note from atmega128 manual pg204
cbi(PORTD, 0);
cbi(PORTD, 1);
#endif
}
}
void I2C::scan()
{
uint16_t tempTime = timeOutDelay;
timeOut(80);
uint8_t totalDevicesFound = 0;
Serial.println(F("Scanning for devices...please wait"));
Serial.println();
for(uint8_t s = 0; s <= 0x7F; s++)
{
returnStatus = 0;
returnStatus = start();
if(!returnStatus)
{
returnStatus = sendAddress(SLA_W(s));
}
if(returnStatus)
{
if(returnStatus == 1)
{
Serial.println(F("There is a problem with the bus, could not complete scan"));
timeOutDelay = tempTime;
return;
}
}
else
{
Serial.print(F("Found device at address - "));
Serial.print(F(" 0x"));
Serial.println(s,HEX);
totalDevicesFound++;
}
stop();
}
if(!totalDevicesFound){Serial.println(F("No devices found"));}
timeOutDelay = tempTime;
}
uint8_t I2C::available()
{
return(bytesAvailable);
}
uint8_t I2C::receive()
{
bufferIndex = totalBytes - bytesAvailable;
if(!bytesAvailable)
{
bufferIndex = 0;
return(0);
}
bytesAvailable--;
return(data[bufferIndex]);
}
/*return values for new functions that use the timeOut feature
will now return at what point in the transmission the timeout
occurred. Looking at a full communication sequence between a
master and slave (transmit data and then readback data) there
a total of 7 points in the sequence where a timeout can occur.
These are listed below and correspond to the returned value:
1 - Waiting for successful completion of a Start bit
2 - Waiting for ACK/NACK while addressing slave in transmit mode (MT)
3 - Waiting for ACK/NACK while sending data to the slave
4 - Waiting for successful completion of a Repeated Start
5 - Waiting for ACK/NACK while addressing slave in receiver mode (MR)
6 - Waiting for ACK/NACK while receiving data from the slave
7 - Waiting for successful completion of the Stop bit
All possible return values:
0 Function executed with no errors
1 - 7 Timeout occurred, see above list
8 - 0xFF See datasheet for exact meaning */
/////////////////////////////////////////////////////
uint8_t I2C::write(uint8_t address, uint8_t registerAddress)
{
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_W(address));
if(returnStatus)
{
if(returnStatus == 1){return(2);}
return(returnStatus);
}
returnStatus = sendByte(registerAddress);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
uint8_t I2C::write(int address, int registerAddress)
{
return(write((uint8_t) address, (uint8_t) registerAddress));
}
uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t data)
{
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_W(address));
if(returnStatus)
{
if(returnStatus == 1){return(2);}
return(returnStatus);
}
returnStatus = sendByte(registerAddress);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
returnStatus = sendByte(data);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
uint8_t I2C::write(int address, int registerAddress, int data)
{
return(write((uint8_t) address, (uint8_t) registerAddress, (uint8_t) data));
}
uint8_t I2C::write(uint8_t address, uint8_t registerAddress, char *data)
{
uint8_t bufferLength = strlen(data);
returnStatus = 0;
returnStatus = write(address, registerAddress, (uint8_t*)data, bufferLength);
return(returnStatus);
}
uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t *data, uint8_t numberBytes)
{
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_W(address));
if(returnStatus)
{
if(returnStatus == 1){return(2);}
return(returnStatus);
}
returnStatus = sendByte(registerAddress);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
for (uint8_t i = 0; i < numberBytes; i++)
{
returnStatus = sendByte(data[i]);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
uint8_t I2C::read(int address, int numberBytes)
{
return(read((uint8_t) address, (uint8_t) numberBytes));
}
uint8_t I2C::read(uint8_t address, uint8_t numberBytes)
{
bytesAvailable = 0;
bufferIndex = 0;
if(numberBytes == 0){numberBytes++;}
nack = numberBytes - 1;
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_R(address));
if(returnStatus)
{
if(returnStatus == 1){return(5);}
return(returnStatus);
}
for(uint8_t i = 0; i < numberBytes; i++)
{
if( i == nack )
{
returnStatus = receiveByte(0);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_NACK){return(returnStatus);}
}
else
{
returnStatus = receiveByte(1);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_ACK){return(returnStatus);}
}
data[i] = TWDR;
bytesAvailable = i+1;
totalBytes = i+1;
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
uint8_t I2C::read(int address, int registerAddress, int numberBytes)
{
return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes));
}
uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes)
{
bytesAvailable = 0;
bufferIndex = 0;
if(numberBytes == 0){numberBytes++;}
nack = numberBytes - 1;
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_W(address));
if(returnStatus)
{
if(returnStatus == 1){return(2);}
return(returnStatus);
}
returnStatus = sendByte(registerAddress);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
returnStatus = start();
if(returnStatus)
{
if(returnStatus == 1){return(4);}
return(returnStatus);
}
returnStatus = sendAddress(SLA_R(address));
if(returnStatus)
{
if(returnStatus == 1){return(5);}
return(returnStatus);
}
for(uint8_t i = 0; i < numberBytes; i++)
{
if( i == nack )
{
returnStatus = receiveByte(0);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_NACK){return(returnStatus);}
}
else
{
returnStatus = receiveByte(1);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_ACK){return(returnStatus);}
}
data[i] = TWDR;
bytesAvailable = i+1;
totalBytes = i+1;
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer)
{
bytesAvailable = 0;
bufferIndex = 0;
if(numberBytes == 0){numberBytes++;}
nack = numberBytes - 1;
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_R(address));
if(returnStatus)
{
if(returnStatus == 1){return(5);}
return(returnStatus);
}
for(uint8_t i = 0; i < numberBytes; i++)
{
if( i == nack )
{
returnStatus = receiveByte(0);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_NACK){return(returnStatus);}
}
else
{
returnStatus = receiveByte(1);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_ACK){return(returnStatus);}
}
dataBuffer[i] = TWDR;
bytesAvailable = i+1;
totalBytes = i+1;
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes, uint8_t *dataBuffer)
{
bytesAvailable = 0;
bufferIndex = 0;
if(numberBytes == 0){numberBytes++;}
nack = numberBytes - 1;
returnStatus = 0;
returnStatus = start();
if(returnStatus){return(returnStatus);}
returnStatus = sendAddress(SLA_W(address));
if(returnStatus)
{
if(returnStatus == 1){return(2);}
return(returnStatus);
}
returnStatus = sendByte(registerAddress);
if(returnStatus)
{
if(returnStatus == 1){return(3);}
return(returnStatus);
}
returnStatus = start();
if(returnStatus)
{
if(returnStatus == 1){return(4);}
return(returnStatus);
}
returnStatus = sendAddress(SLA_R(address));
if(returnStatus)
{
if(returnStatus == 1){return(5);}
return(returnStatus);
}
for(uint8_t i = 0; i < numberBytes; i++)
{
if( i == nack )
{
returnStatus = receiveByte(0);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_NACK){return(returnStatus);}
}
else
{
returnStatus = receiveByte(1);
if(returnStatus == 1){return(6);}
if(returnStatus != MR_DATA_ACK){return(returnStatus);}
}
dataBuffer[i] = TWDR;
bytesAvailable = i+1;
totalBytes = i+1;
}
returnStatus = stop();
if(returnStatus)
{
if(returnStatus == 1){return(7);}
return(returnStatus);
}
return(returnStatus);
}
/////////////// Private Methods ////////////////////////////////////////
uint8_t I2C::start()
{
unsigned long startingTime = millis();
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
if(!timeOutDelay){continue;}
if((millis() - startingTime) >= timeOutDelay)
{
lockUp();
return(1);
}
}
if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START))
{
return(0);
}
if (TWI_STATUS == LOST_ARBTRTN)
{
uint8_t bufferedStatus = TWI_STATUS;
lockUp();
return(bufferedStatus);
}
return(TWI_STATUS);
}
uint8_t I2C::sendAddress(uint8_t i2cAddress)
{
TWDR = i2cAddress;
unsigned long startingTime = millis();
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
if(!timeOutDelay){continue;}
if((millis() - startingTime) >= timeOutDelay)
{
lockUp();
return(1);
}
}
if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK))
{
return(0);
}
uint8_t bufferedStatus = TWI_STATUS;
if ((TWI_STATUS == MT_SLA_NACK) || (TWI_STATUS == MR_SLA_NACK))
{
stop();
return(bufferedStatus);
}
else
{
lockUp();
return(bufferedStatus);
}
}
uint8_t I2C::sendByte(uint8_t i2cData)
{
TWDR = i2cData;
unsigned long startingTime = millis();
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
if(!timeOutDelay){continue;}
if((millis() - startingTime) >= timeOutDelay)
{
lockUp();
return(1);
}
}
if (TWI_STATUS == MT_DATA_ACK)
{
return(0);
}
uint8_t bufferedStatus = TWI_STATUS;
if (TWI_STATUS == MT_DATA_NACK)
{
stop();
return(bufferedStatus);
}
else
{
lockUp();
return(bufferedStatus);
}
}
uint8_t I2C::receiveByte(uint8_t ack)
{
unsigned long startingTime = millis();
if(ack)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
}
else
{
TWCR = (1<<TWINT) | (1<<TWEN);
}
while (!(TWCR & (1<<TWINT)))
{
if(!timeOutDelay){continue;}
if((millis() - startingTime) >= timeOutDelay)
{
lockUp();
return(1);
}
}
if (TWI_STATUS == LOST_ARBTRTN)
{
uint8_t bufferedStatus = TWI_STATUS;
lockUp();
return(bufferedStatus);
}
return(TWI_STATUS);
}
uint8_t I2C::receiveByte(uint8_t ack, uint8_t *target)
{
uint8_t stat = I2C::receiveByte(ack);
if (stat == 1)
{
return(6);
}
if (ack)
{
if(stat != MR_DATA_ACK)
{
*target = 0x0;
return(stat);
}
}
else
{
if(stat != MR_DATA_NACK)
{
*target = 0x0;
return(stat);
}
}
*target = TWDR;
// I suppose that if we get this far we're ok
return 0;
}
uint8_t I2C::stop()
{
unsigned long startingTime = millis();
TWCR = (1<<TWINT)|(1<<TWEN)| (1<<TWSTO);
while ((TWCR & (1<<TWSTO)))
{
if(!timeOutDelay){continue;}
if((millis() - startingTime) >= timeOutDelay)
{
lockUp();
return(1);
}
}
return(0);
}
void I2C::lockUp()
{
TWCR = 0; //releases SDA and SCL lines to high impedance
TWCR = _BV(TWEN) | _BV(TWEA); //reinitialize TWI
}
I2C I2c = I2C();

76
I2C.h

@ -0,0 +1,76 @@
#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <inttypes.h>
#ifndef I2C_h
#define I2C_h
#define START 0x08
#define REPEATED_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NACK 0x58
#define LOST_ARBTRTN 0x38
#define TWI_STATUS (TWSR & 0xF8)
#define SLA_W(address) (address << 1)
#define SLA_R(address) ((address << 1) + 0x01)
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define MAX_BUFFER_SIZE 32
class I2C
{
public:
I2C();
void begin();
void end();
void timeOut(uint16_t);
void setSpeed(uint8_t);
void pullup(uint8_t);
void scan();
uint8_t available();
uint8_t receive();
uint8_t write(uint8_t, uint8_t);
uint8_t write(int, int);
uint8_t write(uint8_t, uint8_t, uint8_t);
uint8_t write(int, int, int);
uint8_t write(uint8_t, uint8_t, char*);
uint8_t write(uint8_t, uint8_t, uint8_t*, uint8_t);
uint8_t read(uint8_t, uint8_t);
uint8_t read(int, int);
uint8_t read(uint8_t, uint8_t, uint8_t);
uint8_t read(int, int, int);
uint8_t read(uint8_t, uint8_t, uint8_t*);
uint8_t read(uint8_t, uint8_t, uint8_t, uint8_t*);
uint8_t start();
uint8_t sendAddress(uint8_t);
uint8_t sendByte(uint8_t);
uint8_t receiveByte(uint8_t);
uint8_t receiveByte(uint8_t, uint8_t *target);
uint8_t stop();
private:
void lockUp();
uint8_t returnStatus;
uint8_t nack;
uint8_t data[MAX_BUFFER_SIZE];
static uint8_t bytesAvailable;
static uint8_t bufferIndex;
static uint8_t totalBytes;
static uint16_t timeOutDelay;
};
extern I2C I2c;
#endif

@ -0,0 +1,111 @@
/*!
* file as3935_lightning_i2c_nocal.ino
*
* On The Lightning Sensor
* This 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.
* The module has three I2C, the addresses are:
* 0x03 A0-High A1-High
* 0x02 A0-Low A1-High
* 0x01 A0-High A1-Low
*
* Copyright [DFRobot](http://www.dfrobot.com), 2018
* Copyright GNU Lesser General Public License
*
* version V0.1
* date 2018-9-6
*/
#include "I2C.h"
#include "DFRobot_AS3935_I2C.h"
volatile int8_t AS3935_ISR_Trig = 0;
#define SI_PIN 9
#define IRQ_PIN 2
#define AS3935_CAPACITANCE 72
#define AS3935_INDOORS 0
#define AS3935_OUTDOORS 1
#define AS3935_DIST_DIS 0
#define AS3935_DIST_EN 1
void AS3935_ISR();
DF_AS3935_I2C lightning0((uint8_t)IRQ_PIN, (uint8_t)SI_PIN, (uint8_t)AS3935_ADD3);
void setup()
{
Serial.begin(115200);
Serial.println("Playing With DFRobot: AS3935 Lightning Sensor");
Serial.println("beginning boot procedure....");
// Setup for the the I2C library: (enable pullups, set speed to 400kHz)
I2c.begin();
I2c.pullup(true);
I2c.setSpeed(1);
delay(2);
//lightning0.AS3935_I2CAddress(AS3935_ADD1); // x01 - A0->high A1->low
//lightning0.AS3935_I2CAddress(AS3935_ADD2); // x02 - A0->low A1->high
//lightning0.AS3935_I2CAddress(AS3935_ADD3); // x03 - A0->high A1->high
lightning0.AS3935_SetI2CAddress(AS3935_ADD3);
// Set registers to default
lightning0.AS3935_DefInit();
// Now update sensor cal for your application and power up chip
lightning0.AS3935_ManualCal(AS3935_CAPACITANCE, AS3935_INDOORS, AS3935_DIST_EN);
// Enable interrupt (hook IRQ pin to Arduino Uno/Mega interrupt input: 0 -> pin 2, 1 -> pin 3 )
attachInterrupt(0, AS3935_ISR, RISING);
// For debug, view register data
lightning0.AS3935_PrintAllRegs();
// Clear trigger
AS3935_ISR_Trig = 0;
}
void loop()
{
// It does nothing until an interrupt is detected on the IRQ pin.
while(0 == AS3935_ISR_Trig){}
delay(5);
// Reset interrupt flag
AS3935_ISR_Trig = 0;
// Now get interrupt source
uint8_t int_src = lightning0.AS3935_GetInterruptSrc();
if(1 == int_src)
{
// Get rid of non-distance data
uint8_t lightning_dist_km = lightning0.AS3935_GetLightningDistKm();
Serial.print("发生闪电啦! 闪电发生距离: ");
Serial.print(lightning_dist_km);
Serial.println(" km");
// Get lightning energy intensity
uint32_t lightning_energy_val = lightning0.AS3935_GetStrikeEnergyRaw();
Serial.print("雷电强度:");
Serial.print(lightning_energy_val);
Serial.println("");
}
else if(2 == int_src)
{
Serial.println("发现干扰源");
}
else if(3 == int_src)
{
Serial.println("噪音强度过高");
}
lightning0.AS3935_PrintAllRegs();
Serial.println("");
}
// This is irq handler for AS3935 interrupts, has to return void and take no arguments
// always make code in interrupt handlers fast and short
void AS3935_ISR()
{
AS3935_ISR_Trig = 1;
}

@ -0,0 +1,60 @@
#######################################
# Syntax Coloring DFRobot_AS3935
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
DF_AS3935_I2C KEYWORD1
I2C KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
timeOut KEYWORD2
setSpeed KEYWORD2
pullup KEYWORD2
scan KEYWORD2
write KEYWORD2
read KEYWORD2
available KEYWORD2
receive KEYWORD2
AS3935_DefInit KEYWORD2
AS3935_DefInit KEYWORD2
_AS3935_Reset KEYWORD2
_CalRCO KEYWORD2
AS3935_PowerUp KEYWORD2
AS3935_PowerDown KEYWORD2
AS3935_DisturberEn KEYWORD2
AS3935_DisturberDis KEYWORD2
AS3935_SetIRQ_Output_Source KEYWORD2
AS3935_SetTuningCaps KEYWORD2
AS3935_GetInterruptSrc KEYWORD2
AS3935_GetLightningDistKm KEYWORD2
AS3935_SetMinStrikes KEYWORD2
AS3935_SetIndoors KEYWORD2
AS3935_SetOutdoors KEYWORD2
AS3935_ClearStatistics KEYWORD2
AS3935_GetNoiseFloorLvl KEYWORD2
AS3935_SetNoiseFloorLvl KEYWORD2
AS3935_GetWatchdogThreshold KEYWORD2
AS3935_SetWatchdogThreshold KEYWORD2
AS3935_GetSpikeRejection KEYWORD2
AS3935_SetSpikeRejection KEYWORD2
AS3935_SetLCO_FDIV KEYWORD2
AS3935_PrintAllRegs KEYWORD2
AS3935_ManualCal KEYWORD2
AS3935_SetI2CAddress KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
AS3935_ADD1 LITERAL1
AS3935_ADD2 LITERAL1
AS3935_ADD3 LITERAL1

@ -0,0 +1,114 @@
# AS3935
AS3935 Lightning Sensor can detect lightning and display the distance and intensity of the lightning without the disturbance of electric arc and noise.<br>
It can be set as indoor or outdoor mode.<br>
## DFRobot_AS3934 Library for Arduino
---------------------------------------------------------
Provide a library faciltates operations in the as3935 modules.
## Table of Contents
* [Summary](#summary)
* [Feature](#feature)
* [Installation](#installation)
* [Methods](#methods)
* [Compatibility](#compatibility)
* [Credits](#credits)
<snippet>
<content>
## Summary
Input commands and read data from AS3935 modules
## Feature
1. test <br>
2. test <br>
3. test <br>
## Installation
Download the library ZIP file and unzip it to the Arduino folder of the library.<br>
## Methods
```C++
#include "DFRobot_AS3935_I2C.h"
/*
* @brief AS3935 object
*
* @param IRQx irq pin
* SIx si pin
* DEVADDx i2c address
*/
DF_AS3935_I2C(uint8_t IRQx, uint8_t SIx, uint8_t DEVADDx);
/*
* @brief reset registers to default
*/
void AS3935_DefInit(void);
/*
* @brief set i2c address
*
* @param DEVADDx i2c address
*/
void AS3935_SetI2CAddress(uint8_t DEVADDx);
/*
* @brief manual calibration
*
* @param capacitance capacitance
* location location
* disturber disturber
*/
void AS3935_ManualCal(uint8_t capacitance, uint8_t location, uint8_t disturber);
/*
* @brief view register data
*/
void AS3935_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 AS3935_GetInterruptSrc(void);
/*
* @brief manual calibration
*
* @param
*/
uint8_t AS3935_GetLightningDistKm(void);
/*
* @brief get rid of non-distance data
*
* @return Unit kilometer
*/
uint32_t AS3935_GetStrikeEnergyRaw(void);
```
## Compatibility
MCU | Work Well | Work Wrong | Untested | Remarks
------------------ | :----------: | :----------: | :---------: | -----
Arduino uno | √ | | |
## Credits
Written by DFRobot, 2018. (Welcome to our [website](https://www.dfrobot.com/))
Loading…
Cancel
Save