Repository navigation
Expand file tree
/
Copy pathRPi_AS3935.py
More file actions
234 lines (197 loc) · 7.21 KB
/
Copy pathRPi_AS3935.py
File metadata and controls
234 lines (197 loc) · 7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import time
class RPi_AS3935:
"""A basic class used for interacting with the AS3935 lightning
sensor from a Raspberry Pi over I2C"""
def __init__(self, address, bus=0):
self.address = address
import smbus
self.i2cbus = smbus.SMBus(bus)
def calibrate(self, tun_cap=None):
"""Calibrate the lightning sensor - this takes up to half a second
and is blocking.
The value of tun_cap should be between 0 and 15, and is used to set
the internal tuning capacitors (0-120pF in steps of 8pF)
"""
time.sleep(0.08)
self.read_data()
if tun_cap is not None:
if tun_cap < 0x10 and tun_cap > -1:
self.set_byte(0x08, (self.registers[0x08] & 0xF0) | tun_cap)
time.sleep(0.002)
else:
raise Exception("Value of TUN_CAP must be between 0 and 15")
self.set_byte(0x3D, 0x96)
time.sleep(0.002)
self.read_data()
self.set_byte(0x08, self.registers[0x08] | 0x20)
time.sleep(0.002)
self.set_byte(0x08, self.registers[0x08] & 0xDF)
time.sleep(0.002)
def reset(self):
"""Reset all registers to their default power on values
"""
self.set_byte(0x3C, 0x96)
def get_interrupt(self):
"""Get the value of the interrupt register
0x01 - Too much noise
0x04 - Disturber
0x08 - Lightning
"""
self.read_data()
return self.registers[0x03] & 0x0F
def get_distance(self):
"""Get the estimated distance of the most recent lightning event
"""
self.read_data()
if self.registers[0x07] & 0x3F == 0x3F:
return False
else:
return self.registers[0x07] & 0x3F
def get_energy(self):
"""Get the calculated energy of the most recent lightning event
"""
self.read_data()
return ((self.registers[0x06] & 0x1F) << 16) | (self.registers[0x05] << 8) | self.registers[0x04]
def get_noise_floor(self):
"""Get the noise floor value.
Actual voltage levels used in the sensor are located in Table 16
of the data sheet.
"""
self.read_data()
return (self.registers[0x01] & 0x70) >> 4
def set_noise_floor(self, noisefloor):
"""Set the noise floor value.
Actual voltage levels used in the sensor are located in Table 16
of the data sheet.
"""
self.read_data()
noisefloor = (noisefloor & 0x07) << 4
write_data = (self.registers[0x01] & 0x8F) + noisefloor
self.set_byte(0x01, write_data)
def lower_noise_floor(self, min_noise=0):
"""Lower the noise floor by one step.
min_noise is the minimum step that the noise_floor should be
lowered to.
"""
floor = self.get_noise_floor()
if floor > min_noise:
floor = floor - 1
self.set_noise_floor(floor)
return floor
def raise_noise_floor(self, max_noise=7):
"""Raise the noise floor by one step
max_noise is the maximum step that the noise_floor should be
raised to.
"""
floor = self.get_noise_floor()
if floor < max_noise:
floor = floor + 1
self.set_noise_floor(floor)
return floor
def get_min_strikes(self):
"""Get the number of lightning detections required before an
interrupt is raised.
"""
self.read_data()
value = (self.registers[0x02] >> 4) & 0x03
if value == 0:
return 1
elif value == 1:
return 5
elif value == 2:
return 9
elif value == 3:
return 16
def set_min_strikes(self, minstrikes):
"""Set the number of lightning detections required before an
interrupt is raised.
Valid values are 1, 5, 9, and 16, any other raises an exception.
"""
if minstrikes == 1:
minstrikes = 0
elif minstrikes == 5:
minstrikes = 1
elif minstrikes == 9:
minstrikes = 2
elif minstrikes == 16:
minstrikes = 3
else:
raise Exception("Value must be 1, 5, 9, or 16")
self.read_data()
minstrikes = (minstrikes & 0x03) << 4
write_data = (self.registers[0x02] & 0xCF) + minstrikes
self.set_byte(0x02, write_data)
def get_indoors(self):
"""Determine whether or not the sensor is configured for indoor
use or not.
Returns True if configured to be indoors, otherwise False.
"""
self.read_data()
if self.registers[0x00] & 0x20 == 0x20:
return True
else:
return False
def set_indoors(self, indoors):
"""Set whether or not the sensor should use an indoor configuration.
"""
self.read_data()
if indoors:
write_value = (self.registers[0x00] & 0xC1) | 0x24
else:
write_value = (self.registers[0x00] & 0xC1) | 0x1C
self.set_byte(0x00, write_value)
def set_mask_disturber(self, mask_dist):
"""Set whether or not disturbers should be masked (no interrupts for
what the sensor determines are man-made events)
"""
self.read_data()
if mask_dist:
write_value = self.registers[0x03] | 0x20
else:
write_value = self.registers[0x03] & 0xDF
self.set_byte(0x03, write_value)
def get_mask_disturber(self):
"""Get whether or not disturbers are masked or not.
Returns True if interrupts are masked, false otherwise
"""
self.read_data()
if self.registers[0x03] & 0x20 == 0x20:
return True
else:
return False
def set_disp_lco(self, display_lco):
"""Have the internal LC oscillator signal displayed on the interrupt pin for
measurement.
Passing display_lco=True enables the output, False disables it.
"""
self.read_data()
if display_lco:
self.set_byte(0x08, (self.registers[0x08] | 0x80))
else:
self.set_byte(0x08, (self.registers[0x08] & 0x7F))
time.sleep(0.002)
def get_disp_lco(self):
"""Determine whether or not the internal LC oscillator is displayed on the
interrupt pin.
Returns True if the LC oscillator is being displayed on the interrupt pin,
False otherwise
"""
self.read_data()
if self.registers[0x08] & 0x80 == 0x80:
return True
else:
return False
def set_byte(self, register, value):
"""Write a byte to a particular address on the sensor.
This method should rarely be used directly.
"""
self.i2cbus.write_byte_data(self.address, register, value)
def read_data(self):
"""
Read a block of data from the sensor and store it.
This doesn't read exact registers because the library used by
smbus doesn't support repeated I2C starts (required to read
registers directly on the sensor)
This method should rarely be called directly.
"""
self.registers = self.i2cbus.read_i2c_block_data(self.address, 0x00)