Skip to content

Instantly share code, notes, and snippets.

@teddokano
Created June 11, 2023 03:16
Show Gist options
  • Save teddokano/c0ffc88eed47a24c5cbc2bc1467dac86 to your computer and use it in GitHub Desktop.
Save teddokano/c0ffc88eed47a24c5cbc2bc1467dac86 to your computer and use it in GitHub Desktop.
Pressure sensor comparison: MPL115A1 and MPL3115A2S
from machine import I2C, SPI, Pin, Timer
from utime import sleep, localtime
from struct import unpack
import os
class MPL3115A2S:
def __init__( self, i2c, addr = 0xC0 >> 1 ):
self.i2c = i2c
self.addr = addr
self.data_ready = True
"""
self.i2c.writeto( self.addr, bytearray( [ 0x26, 0x38 ] ) )
self.i2c.writeto( self.addr, bytearray( [ 0x13, 0x07 ] ) )
self.i2c.writeto( self.addr, bytearray( [ 0x26, 0x39 ] ) )
self.i2c.writeto( self.addr, bytearray( [ 0x26, 0x3B ] ) )
"""
self.i2c.writeto( self.addr, bytearray( [ 0x26, 0x00 ] ) )
self.i2c.writeto( self.addr, bytearray( [ 0x13, 0x07 ] ) )
self.i2c.writeto( self.addr, bytearray( [ 0x26, 0x01 ] ) )
self.i2c.writeto( self.addr, bytearray( [ 0x26, 0x03 ] ) )
def measurement_start( self ):
pass
def pressure( self ):
while True:
self.i2c.writeto( self.addr, bytearray( [ 0x00 ] ), False ) # pointer byte write
val = self.i2c.readfrom( self.addr, 1 )
if val[ 0 ] & 0x08:
break
self.i2c.writeto( self.addr, bytearray( [ 0x01 ] ), False ) # pointer byte write
val = self.i2c.readfrom( self.addr, 5 )
p = ((val[ 0 ] << 16) | (val[ 1 ] << 8) | val[ 2 ]) / 6400
t = val[ 3 ] + (val[ 4 ] >> 4) / 4
#print( f"{val[0]:02X} {val[1]:02X} {val[2]:02X}" )
self.t = t
return p
class MPL115A1:
def __init__( self, spi, cs ):
self.spi = spi
self.cs = cs
self.in_meas = False
self.data_ready = False
self.timer = None
self._get_coeff()
def measurement_start( self ):
if self.in_meas or self.data_ready:
return
self.in_meas = True
self._cs_ctrl( 0 )
self.spi.write( bytearray( [ 0x24, 0x00 ] ) )
self._cs_ctrl( 1 )
"""
Timer( -1, mode = Timer.ONE_SHOT, period = 3, callback = self._set_ready_flag )
"""
if not self.timer:
self.timer = Timer( -1 )
self.timer.init( mode = Timer.ONE_SHOT, period = 3, callback = self._set_ready_flag )
def pressure( self ):
self.measurement_start()
while not self.data_ready:
pass
p_adc, t_adc = self._pressure_temp()
p_comp = self.a0 + (self.b1 + self.c12 * t_adc) * p_adc + self.b2 * t_adc
return (p_comp * ((115 - 50) / 1023) + 50) * 10
def _get_coeff( self ):
data = self._insert_zero_bytes( [ 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94, 0x96 ] )
self._cs_ctrl( 0 )
self.spi.write_readinto( data, data )
self._cs_ctrl( 1 )
self.a0, self.b1, self.b2, self.c12 = unpack( ">hhhh", self._collect_odd_bytes( data ) )
self.a0 /= 2**3
self.b1 /= 2**13
self.b2 /= 2**14
self.c12 /= 2**24
def _pressure_temp( self ):
data = self._insert_zero_bytes( [ 0x80, 0x82, 0x84, 0x86 ] )
self._cs_ctrl( 0 )
self.spi.write_readinto( data, data )
self._cs_ctrl( 1 )
self.data_ready = False
p, t = unpack( ">HH", self._collect_odd_bytes( data ) )
p >>= 6
t >>= 6
return ( p, t )
def _collect_odd_bytes( self, data ):
# doing similar to data = data[1::2] because MicroPython doesn't support "::2"
return bytearray( [ x for i, x in enumerate( data ) if i % 2 ] )
def _insert_zero_bytes( self, data ):
return bytearray( sum( [ [x, 0x00] for x in data ], [] ) + [ 0x00 ] )
def _cs_ctrl( self, state ):
if self.cs:
self.cs.value( state )
def _set_ready_flag( self, _ ):
self.in_meas = False
self.data_ready = True
def callback( x ):
global timer_flag
timer_flag = True
def main():
global timer_flag
timer_flag = False
LOG_FILE = "mpl3155.csv"
I2C_FREQ = 400000
SPI_FREQ = 1000000
SAMPLING = 10
if "MIMXRT" in os.uname().machine:
spi = SPI( 0, SPI_FREQ, cs = 0 )
s0 = MPL115A1( spi, None )
i2c = I2C( 0, I2C_FREQ )
s1 = MPL3115A2S( i2c )
led = Pin( "D4", Pin.OUT )
elif "Raspberry Pi Pico" in os.uname().machine:
spi = SPI( 1, SPI_FREQ, sck = Pin( 10 ), mosi = Pin( 11 ), miso = Pin( 12 ) )
s0 = MPL115A1( spi, Pin( 13, Pin.OUT ) )
i2c = I2C( 0, sda = Pin( 0 ), scl = Pin( 1 ), freq = I2C_FREQ )
s1 = MPL3115A2S( i2c )
led = Pin( "LED", Pin.OUT )
Timer( -1, mode = Timer.PERIODIC, freq = SAMPLING, callback = callback )
count = 0
while True:
if timer_flag:
timer_flag = False
led.value( 1 )
p0 = s0.pressure()
p1 = s1.pressure()
dt = localtime()
p_str = "{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}, {}, {}, {}".format( dt[ 0 ], dt[ 1 ], dt[ 2 ], dt[ 3 ], dt[ 4 ], dt[ 5 ], p0, p1, count )
print( p_str )
with open( LOG_FILE, "a" ) as f:
print( p_str, file = f )
count += 1
led.value( 0 )
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment