parent
38f851e63d
commit
70efa9f99d
@ -0,0 +1,245 @@ |
||||
import utime |
||||
from machine import Pin, I2C |
||||
|
||||
class DFRobot_AS3935: |
||||
def __init__(self, address, i2c): |
||||
self.address = address |
||||
self.i2cbus = i2c |
||||
|
||||
def writeByte(self, register, value): |
||||
try: |
||||
self.i2cbus.writeto_mem(self.address, register, bytes([value])) |
||||
return 1 |
||||
except: |
||||
return 0 |
||||
|
||||
def readData(self, register): |
||||
self.register = self.i2cbus.readfrom_mem(self.address, register, 1) |
||||
|
||||
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) |
||||
utime.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 |
||||
utime.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) |
||||
utime.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 |
||||
utime.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) |
||||
utime.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]) |
||||
self.singRegRead(0x3A) |
||||
print("Reg 0x3A: %02x"%self.register[0]) |
||||
self.singRegRead(0x3B) |
||||
print("Reg 0x3B: %02x"%self.register[0]) |
||||
|
||||
|
||||
|
@ -0,0 +1,153 @@ |
||||
## DFRobot_AS3935_Lib.py Library for MicroPython |
||||
--------------------------------------------------------- |
||||
This is the sample code for Gravity:Lightning Sensor, SKU: SEN0292. |
||||
## Table of Contents |
||||
|
||||
* [Installation](#installation) |
||||
* [Methods](#methods) |
||||
<snippet> |
||||
<content> |
||||
|
||||
## Installation |
||||
The Lightning Sensor should work with AS3935 |
||||
(https://github.com/DFRobot/DFRobot_AS3935/tree/master/MicroPython) |
||||
|
||||
Copy the library (DFRobot_AS3935_Lib.py) and the example code (DFRobot_AS3935_detailed.py as main.py) to a microcontroller running MicroPython (https://micropython.org): |
||||
|
||||
## Methods |
||||
|
||||
```python |
||||
|
||||
/* |
||||
* @brief Init The Lightning Sensor |
||||
* |
||||
* @param address I2C address(1~3) |
||||
* i2c I2C object (machine.I2C) |
||||
*/ |
||||
DFRobot_AS3935(address, i2c); |
||||
|
||||
/* |
||||
* @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/)) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,111 @@ |
||||
# 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 |
||||
|
||||
from DFRobot_AS3935_Lib import DFRobot_AS3935 |
||||
from machine import Pin, I2C |
||||
import utime |
||||
|
||||
#I2C address |
||||
AS3935_I2C_ADDR1 = 0X01 |
||||
AS3935_I2C_ADDR2 = 0X02 |
||||
AS3935_I2C_ADDR3 = 0X03 |
||||
|
||||
# I2C HW ID or -1 for SW I2C |
||||
I2C_ID = 1 |
||||
I2C_SCL_PIN = 22 |
||||
I2C_SDA_PIN = 23 |
||||
|
||||
#Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) |
||||
AS3935_CAPACITANCE = 120 |
||||
IRQ_PIN = 12 |
||||
|
||||
# Initialize |
||||
i2c = I2C(I2C_ID, scl=Pin(I2C_SCL_PIN), sda=Pin(I2C_SDA_PIN), freq=400000) |
||||
sensor = DFRobot_AS3935(AS3935_I2C_ADDR3, i2c) |
||||
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) |
||||
utime.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 |
||||
utime.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 |
||||
pinirq = Pin(IRQ_PIN, Pin.IN) |
||||
#Set the interrupt pin, the interrupt function, rising along the trigger |
||||
pinirq.irq(trigger=Pin.IRQ_RISING, handler=callback_handle) |
||||
print("start lightning detect.") |
||||
|
||||
while True: |
||||
utime.sleep(1.0) |
||||
|
||||
|
Loading…
Reference in new issue