'''! @file DFRobot_AS3935_Lib.py @brief Define the basic structure of the DFRobot_AS3935 class, the implementation of the basic methods. @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) @license The MIT License (MIT) @author TangJie(jie.tamg@dfrobot.com) @version V1.0.2 @date 2021-9-28 @url https://github.com/DFRobot/DFRobot_AS3935 ''' import time import smbus class DFRobot_AS3935: def __init__(self, address, bus = 1): self.address = address self.i2cbus = smbus.SMBus(bus) def write_byte(self, register, value): try: self.i2cbus.write_byte_data(self.address, register, value) return 1 except: return 0 def read_data(self, register): self.register = self.i2cbus.read_i2c_block_data(self.address, register) '''! @brief Configure sensor @param capacitance Antenna tuning capcitance (must be integer multiple of 8, 8 - 120 pf) @param location Indoor/outdoor mode selection @param disturber Enable/disable disturber detection ''' def manual_cal(self, capacitance, location, disturber): self.power_up() if location == 0: self.set_indoors() else: self.set_outdoors() if disturber == 0: self.disturber_dis() else: self.disturber_en() self.set_irq_output_source(0) time.sleep(0.5) self.set_tuning_caps(capacitance) def set_tuning_caps(self, capVal): #Assume only numbers divisible by 8 (because that's all the chip supports) if capVal > 120: #cap_value out of range, assume highest capacitance self.sing_reg_write(0x08, 0x0F, 0x0F) #set capacitance bits to maximum else: self.sing_reg_write(0x08, 0x0F, capVal >> 3) #set capacitance bits self.sing_reg_read(0x08) #print('capacitance set to 8x%d'%(self.register[0] & 0x0F)) def power_up(self): #register 0x00, PWD bit: 0 (clears PWD) self.sing_reg_write(0x00, 0x01, 0x00) self.cal_RCO() #run RCO cal cmd self.sing_reg_write(0x08, 0x20, 0x20) #set DISP_SRCO to 1 time.sleep(0.002) self.sing_reg_write(0x08, 0x20, 0x00) #set DISP_SRCO to 0 def power_down(self): #register 0x00, PWD bit: 0 (sets PWD) self.sing_reg_write(0x00, 0x01, 0x01) def cal_RCO(self): self.write_byte(0x3D, 0x96) time.sleep(0.002) '''! @brief Set to the indoor model ''' def set_indoors(self): self.sing_reg_write(0x00, 0x3E, 0x24) print("set to indoors model") '''! @brief Set to the outdoor model ''' def set_outdoors(self): self.sing_reg_write(0x00, 0x3E, 0x1C) print("set to outdoors model") '''! @brief Disturber detection disenabled ''' def disturber_dis(self): #register 0x03, PWD bit: 5 (sets MASK_DIST) self.sing_reg_write(0x03, 0x20, 0x20) print("disenable disturber detection") '''! @brief Disturber detection enabled ''' def disturber_en(self): #register 0x03, PWD bit: 5 (sets MASK_DIST) self.sing_reg_write(0x03, 0x20, 0x00) print("enable disturber detection") def sing_reg_write(self, regAdd, dataMask, regData): #start by reading original register data (only modifying what we need to) self.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 newRegData = (self.register[0] & ~dataMask)|(regData & dataMask) #finally, write the data to the register self.write_byte(regAdd, newRegData) #print('wrt: %02x'%newRegData) self.sing_reg_read(regAdd) #print('Act: %02x'%self.register[0]) def sing_reg_read(self,regAdd): self.read_data(regAdd) '''! @brief Get mid-range type @return 返回中断状态 @retval 0 Unknown src @retval 1 Lightning detected @retval 2 Disturber @retval 3 Noise level too high ''' def get_interrupt_src(self): #definition of interrupt data on table 18 of datasheet #for this function: #0 = unknown src, 1 = lightning detected, 2 = disturber, 3 = Noise level too high time.sleep(0.03) #wait 3ms before reading (min 2ms per pg 22 of datasheet) self.sing_reg_read(0x03) #read register, get rid of non-interrupt data intSrc = self.register[0]&0x0F if intSrc == 0x08: return 1 #lightning caused interrupt elif intSrc == 0x04: return 2 #disturber detected elif intSrc == 0x01: return 3 #Noise level too high else: return 0 #interrupt result not expected '''! @brief Sensor reset ''' def reset(self): err = self.write_byte(0x3C, 0x96) time.sleep(0.002) #wait 2ms to complete return err '''! @brief Sets LCO_FDIV register @param fdiv Set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively ''' def set_lco_fdiv(self,fdiv): self.sing_reg_write(0x03, 0xC0, (fdiv & 0x03) << 6) '''! @brief Set interrupt source @param irqSelect 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO ''' def set_irq_output_source(self, irqSelect): #set interrupt source - what to display on IRQ pin #reg 0x08, bits 5 (TRCO), 6 (SRCO), 7 (LCO) #only one should be set at once, I think #0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO if irqSelect == 1: self.sing_reg_write(0x08, 0xE0, 0x20) #set only TRCO bit elif irqSelect == 2: self.sing_reg_write(0x08, 0xE0, 0x40) #set only SRCO bit elif irqSelect == 3: self.sing_reg_write(0x08, 0xE0, 0x80) #set only SRCO bit else: self.sing_reg_write(0x08, 0xE0, 0x00) #clear IRQ pin display bits '''! @brief get lightning distance @return unit kilometer ''' def get_lightning_distKm(self): self.sing_reg_read(0x07) #read register, get rid of non-distance data return self.register[0]&0x3F '''! @brief get lightning energy intensity @return lightning energy intensity(0-1000) ''' def get_strike_energy_raw(self): self.sing_reg_read(0x06) #MMSB, shift 8 bits left, make room for MSB nrgyRaw = (self.register[0]&0x1F) << 8 self.sing_reg_read(0x05) #read MSB nrgyRaw |= self.register[0] nrgyRaw <<= 8 #shift 8 bits left, make room for LSB self.sing_reg_read(0x04) #read LSB, add to others nrgyRaw |= self.register[0] return nrgyRaw/16777 def set_min_strikes(self, minStrk): #This function sets min strikes to the closest available number, rounding to the floor, #where necessary, then returns the physical value that was set. Options are 1, 5, 9 or 16 strikes. if minStrk < 5: self.sing_reg_write(0x02, 0x30, 0x00) return 1 elif minStrk < 9: self.sing_reg_write(0x02, 0x30, 0x10) return 5 elif minStrk < 16: self.sing_reg_write(0x02, 0x30, 0x20) return 9 else: self.sing_reg_write(0x02, 0x30, 0x30) return 16 def clear_statistics(self): #clear is accomplished by toggling CL_STAT bit 'high-low-high' (then set low to move on) self.sing_reg_write(0x02, 0x40, 0x40) #high self.sing_reg_write(0x02, 0x40, 0x00) #low self.sing_reg_write(0x02, 0x40, 0x40) #high '''! @brief Get the noise level @return 0~7 ''' def get_noise_floor_lv1(self): #NF settings addres 0x01, bits 6:4 #default setting of 010 at startup (datasheet, table 9) self.sing_reg_read(0x01) #read register 0x01 return (self.register[0] & 0x70) >> 4 #should return value from 0-7, see table 16 for info '''! @brief Set the noise level @param 0~7,More than 7 will use the default value:2 ''' def set_noise_floor_lv1(self, nfSel): #NF settings addres 0x01, bits 6:4 #default setting of 010 at startup (datasheet, table 9) if nfSel <= 7: #nfSel within expected range self.sing_reg_write(0x01, 0x70, (nfSel & 0x07) << 4) else: #out of range, set to default (power-up value 010) self.sing_reg_write(0x01, 0x70, 0x20) '''! @brief read WDTH @return 返回干扰等级 ''' def get_watchdog_threshold(self): #This function is used to read WDTH. It is used to increase robustness to disturbers, #though will make detection less efficient (see page 19, Fig 20 of datasheet) #WDTH register: add 0x01, bits 3:0 #default value of 0010 #values should only be between 0x00 and 0x0F (0 and 7) self.sing_reg_read(0x01) return self.register[0] & 0x0F '''! @brief Set an anti-interference rating @param 0~7,More than 7 will use the default value:2 ''' def set_watchdog_threshold(self, wdth): #This function is used to modify WDTH. It is used to increase robustness to disturbers, #though will make detection less efficient (see page 19, Fig 20 of datasheet) #WDTH register: add 0x01, bits 3:0 #default value of 0010 #values should only be between 0x00 and 0x0F (0 and 7) self.sing_reg_write(0x01, 0x0F, wdth & 0x0F) '''! @brief read SREJ (spike rejection) @return 返回SREJ值 ''' def get_spike_rejection(self): #This function is used to read SREJ (spike rejection). Similar to the Watchdog threshold, #it is used to make the system more robust to disturbers, though will make general detection #less efficient (see page 20-21, especially Fig 21 of datasheet) #SREJ register: add 0x02, bits 3:0 #default value of 0010 #values should only be between 0x00 and 0x0F (0 and 7) self.sing_reg_read(0x02) return self.register[0] & 0x0F '''! @brief Modify SREJ (spike rejection) @param 0~7,More than 7 will use the default value:2 ''' def set_spike_rejection(self, srej): #This function is used to modify SREJ (spike rejection). Similar to the Watchdog threshold, #it is used to make the system more robust to disturbers, though will make general detection #less efficient (see page 20-21, especially Fig 21 of datasheet) #WDTH register: add 0x02, bits 3:0 #default value of 0010 #values should only be between 0x00 and 0x0F (0 and 7) self.sing_reg_write(0x02, 0x0F, srej & 0x0F) def print_all_regs(self): self.sing_reg_read(0x00) print("Reg 0x00: %02x"%self.register[0]) self.sing_reg_read(0x01) print("Reg 0x01: %02x"%self.register[0]) self.sing_reg_read(0x02) print("Reg 0x02: %02x"%self.register[0]) self.sing_reg_read(0x03) print("Reg 0x03: %02x"%self.register[0]) self.sing_reg_read(0x04) print("Reg 0x04: %02x"%self.register[0]) self.sing_reg_read(0x05) print("Reg 0x05: %02x"%self.register[0]) self.sing_reg_read(0x06) print("Reg 0x06: %02x"%self.register[0]) self.sing_reg_read(0x07) print("Reg 0x07: %02x"%self.register[0]) self.sing_reg_read(0x08) print("Reg 0x08: %02x"%self.register[0])