commit
ddca4bf74f
@ -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(); |
||||
|
@ -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…
Reference in new issue