Ported Raspberry Pi library to MicroPython

pull/2/head
Jochen Schaeuble 5 years ago
parent 38f851e63d
commit 70efa9f99d
  1. 245
      MicroPython/DFRobot_AS3935_Lib.py
  2. 153
      MicroPython/README.md
  3. 111
      MicroPython/example/DFRobot_AS3935_detailed.py

@ -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…
Cancel
Save