-
Notifications
You must be signed in to change notification settings - Fork 2
/
MPL3115A2.py
377 lines (294 loc) · 9.21 KB
/
MPL3115A2.py
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
#!/usr/bin/env python
"""
__author__ = "D.Qendri"
__copyright__ = "Copyright 2015 Sensorian"
__license__ = "GPL V3"
__version__ = "1.0"
"""
import sys
import smbus
import time
import math
from ctypes import *
MPL = CDLL("./libMPL.so")
MPL3115A2_ADDRESS = 0x60 #7-bit I2C address for sensor
#Sensor Memory map
STATUS = 0x00
OUT_P_MSB = 0x01
OUT_P_CSB = 0x02
OUT_P_LSB = 0x03
OUT_T_MSB = 0x04
OUT_T_LSB = 0x05
DR_STATUS = 0x06
OUT_P_DELTA_MSB = 0x07
OUT_P_DELTA_CSB = 0x08
OUT_P_DELTA_LSB = 0x09
OUT_T_DELTA_MSB = 0x0A
OUT_T_DELTA_LSB = 0x0B
WHO_AM_I = 0x0C
F_STATUS = 0x0D
F_DATA = 0x0E
F_SETUP = 0x0F
TIME_DLY = 0x10
SYSMOD = 0x11
INT_SOURCE = 0x12
PT_DATA_CFG = 0x13
BAR_IN_MSB = 0x14
BAR_IN_LSB = 0x15
P_TGT_MSB = 0x16
P_TGT_LSB = 0x17
T_TGT = 0x18
P_WND_MSB = 0x19
P_WND_LSB = 0x1A
T_WND = 0x1B
P_MIN_MSB = 0x1C
P_MIN_CSB = 0x1D
P_MIN_LSB = 0x1E
T_MIN_MSB = 0x1F
T_MIN_LSB = 0x20
P_MAX_MSB = 0x21
P_MAX_CSB = 0x22
P_MAX_LSB = 0x23
T_MAX_MSB = 0x24
T_MAX_LSB = 0x25
CTRL_REG1 = 0x26
CTRL_REG2 = 0x27
CTRL_REG3 = 0x28
CTRL_REG4 = 0x29
CTRL_REG5 = 0x2A
OFF_P = 0x2B
OFF_T = 0x2C
OFF_H = 0x2D
#*********************Status **************************************/
PTDR = 0x04 #Pressure/Altitude OR Temperature data ready
PDR = 0x02 #Pressure/Altitude new data available
TDR = 0x01 #Temperature new Data Available.
#*********************Control Register 1****************************/
ALT = 0x80
RAW = 0x40
OS2 = 0x20
OS1 = 0x10
OS0 = 0x08
RST = 0x04
OST = 0x02
SBYB = 0x01 #Active mode
# Oversample Ratio 1
OS_1 = 0x00 # 6 ms min between samples
OS_2 = OS0 # 10 ms
OS_4 = OS1 # 18 ms
OS_8 = OS1 | OS0 # 34 ms
OS_16 = OS2 # 66 ms
OS_32 = OS2 | OS0 # 130 ms
OS_64 = OS2 | OS1 # 258 ms
OS_128 = OS2 | OS1 | OS2 # 512 ms
BAR_MASK = 0x80
ALT_MASK = 0xEF
ACTIVE_MASK = 0xF1
STANDBY_MASK = 0xFE
#*********************Control Register 5****************************/
DISABLED = 0x00
CIRCULAR = 0x40
FULL_STOP = 0x80
F_MODE = DISABLED
#*****************PT_DATA_CFG - Sensor data event flag register***********/
DREM = 0x04 # Data Ready Event Mode
PDEFE = 0x02 # Pressure Data Event Flag Enabled
TDEFE = 0x01 # Temperature Data Event Flag Enabled
class MPL3115A2(object):
def __init__(self):
"""
Initializes I2C bus if not initizalized and configures sensor in active mode.
:param none:
:returns none:
"""
self._address = MPL3115A2_ADDRESS
MPL.I2C_Initialize()
MPL.MPL3115A2_Initialize()
def GetMode(self):
"""
Return a bool value indicating wheather the sensor is in Active or Standby mode.
:param none:
:returns Mode: 1 if in Active mode, 0 otherwise
"""
return MPL.MPL3115A2_Mode()
def GetID(self):
"""
Returns the Factory Sensor ID.
:param none:
:returns id: Factory ID
"""
a = MPL.MPL3115A2_ID()
return int(a)
def ReadBarometricPressure(self):
"""
Reads the current pressure in Pa.
:param none:
:returns none: Returns -1 if no new data is available
"""
# return sensor.MPL3115A2_ReadBarometricPressure()
status = MPL.MPL3115A2_ReadByte(self._address,STATUS)
#Check PDR bit, if it's not set then toggle OST
if((status & (1<< PDR)) == 0):
MPL.MPL3115A2_ToggleOneShot() #Toggle the OST bit causing the sensor to immediately take another reading
m_pressure = MPL.MPL3115A2_ReadByte(self._address,OUT_P_MSB)
c_pressure = MPL.MPL3115A2_ReadByte(self._address,OUT_P_CSB)
l_pressure = MPL.MPL3115A2_ReadByte(self._address,OUT_P_LSB)
pressure_whole = long (m_pressure<<16) | long(c_pressure<<8) | long (l_pressure) # Pressure comes back as a left shifted 20 bit number
pressure_whole >>= 6 #Pressure is an 18 bit number with 2 bits of decimal. Get rid of decimal portion.
c_pressure &= 0b00110000 # Bits 5/4 represent the fractional component
c_pressure >>= 4 # Get it right aligned
pressure_decimal = float(((c_pressure&0x30)>>4)/4.0) # Turn it into fraction
pressure = float(pressure_whole + pressure_decimal)
return pressure
def ReadTemperature(self):
"""
Reads the current temperature in degrees Celcius.
:param none:
:returns temp: Returns temperature as a float.
"""
# return sensor.MPL3115A2_ReadTemperature()
t_MSB = MPL.MPL3115A2_ReadByte(self._address,OUT_T_MSB)
t_LSB = MPL.MPL3115A2_ReadByte(self._address,OUT_T_LSB)
templsb = float((t_LSB >>4) / 16.0) #temp, fraction of a degree
temperature = float(t_MSB + templsb) #
return temperature
def BarometerMode(self):
"""
Sets the sensor in Barometer mode.
:param none:
:returns none:
"""
MPL.MPL3115A2_BarometerMode()
def AltimeterMode(self):
"""
Sets the mode in Altimeter mode.
:param none:
:returns none:
"""
ctrl_reg = MPL.MPL3115A2_ReadByte(self._address,CTRL_REG1) #Read current settings
ctrl_reg &= ~(SBYB) #Go to Standby mode
MPL.MPL3115A2_WriteByte(self._address,CTRL_REG1, ctrl_reg)
ctrl_reg = ALT|OS_128 #Set ALT bit to one and enable back Active mode
MPL.MPL3115A2_WriteByte(self._address,CTRL_REG1, ctrl_reg)
def ReadAltitude(self):
"""
Returns the number of meters above sea level.
:param none:
:returns none: Returns altitude as a float
"""
m_altitude = MPL.MPL3115A2_ReadByte(self._address,OUT_P_MSB) #Read altitude data
c_altitude = MPL.MPL3115A2_ReadByte(self._address,OUT_P_CSB)
l_altitude = MPL.MPL3115A2_ReadByte(self._address,OUT_P_LSB)
altitude = ((m_altitude << 24) | (c_altitude << 16) | (l_altitude))*10
return( float(altitude/65536))
def GetAltitude(self):
"""
Returns the number of meters above sea level.
:param none:
:returns none: Returns altitude as a float
"""
alt = MPL.MPL3115A2_ReadAltitude()
alt_m = alt >> 8
alt_l = alt & 0xff
if (alt_l > 99):
alt_l = alt_l / 1000.0
else:
alt_l = alt_l / 100.0
return self.twosToInt(alt_m, 16) + alt_l
def StandbyMode(self):
"""
Puts the sensor in standby mode. This is needed whenever one wants to modify the control registers.
:param none:
:returns none:
"""
MPL.MPL3115A2_StandbyMode()
def ActiveMode(self):
"""
Put the sensor in active mode.
:param none:
:returns none:
"""
MPL.MPL3115A2_ActiveMode()
def OversampleRate(self, sampleRate):
"""
Sets the ovsersampling rate.
:param sampleRate: sampleRate is from 0 to 7
:returns none:
"""
MPL.MPL3115A2_OversampleRate()
def SetAcquisitionTimeStep(self,ST_Value):
"""
Set the acquisition time step.
:param ST_Value: Time Step value
:returns none:
"""
MPL.MPL3115A2_SetAcquisitionTimeStep(ST_Value)
def EnableEventFlags(self):
"""
Enables the pressure and temp measurement event flags so that we can
test against them. This is recommended in datasheet during setup.
:param none:
:returns none:
"""
MPL.MPL3115A2_enableEventFlags()
def ToggleOneShot(self):
"""
Clears then sets the OST bit which causes the sensor to immediately take another reading
Needed to sample faster than 1Hz.
:param none:
:returns none:
"""
MPL.MPL3115A2_toggleOneShot()
def CofigureInterruptPin(self,interrupt,pin):
"""
Configure the interrupt pin.
:param interrupt: Type of interrupt
:param pin: Only pin 1 is used
:returns none:
"""
MPL.MPL3115A2_CofigureInterruptPin()
def WriteByte(self,address,reg,data):
"""
Write byte value from register.
:param address: Sensori address
:param reg: Register address
:param data: Register value
:returns none:
"""
MPL.I2C_WriteByteRegister(address,reg,data)
def ReadByte(self,address,reg):
"""
Read byte value from register.
:param address: Sensor address
:param reg: Register address
:returns none:
"""
MPL.I2C_ReadByteRegister(address,reg)
def ReadByteArray(self,address, reg, buffer, length):
"""Read a byte array from the sensor.
:param address: Sensor address
:param reg: Register address
:param buffer: Data buffer
:param length: Data length
:returns array: Byte array
"""
MPL.I2C_ReadByteArray(address,reg,buffer,length)
def WriteByteArray(self, address, reg, buffer):
"""
Writes an array of bytes to the sensor.
:param address: Sensor address
:param reg: Register address
:param buffer: Data buffer
:param length: buffer length
:returns none:
"""
MPL.MPL3115A2_WriteByteArray(address,reg,buffer,length)
def TwosToInt(self, val, len):
"""
Convert twos complement to integer.
:param val:
:param len:
:returns complememt: integer value of two's complement
"""
if(val & (1 << len - 1)):
val = val - (1<<len)