Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added depth and pressure, updated README #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,32 @@ Get the most recent pressure measurement.

Returns the most recent pressure in bar. Call read() to update.

You can change the units of pressure by specifying a unit:

sensor.pressure('Pa')
sensor.pressure('bar')
sensor.pressure('mbar')

### temperature()

Get the most recent temperature measurement.

sensor.temperature()

Returns the most recent temperature in degrees Centigrade. Call read() to update.

### depth()

Get the most recent depth measurement.

sensor.depth()

Returns the most recent depth in meters below sea level. Call read() to update.

### altitude()

Get the most recent altitude measurement.

sensor.altitude()

Returns the most recent altitude in meters above sea level. Call read() to update.
6 changes: 3 additions & 3 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
while True:
try:
sensor.read()
print("pressure: %7.4f bar\ttemperature: %0.2f C" % (sensor.pressure(), sensor.temperature()))
print("pressure: %7.4f bar\ttemperature: %0.2f C\tdepth: %4.2f m\taltitude %4.2f m" % (sensor.pressure(), sensor.temperature(), sensor.depth(), sensor.altitude()))
time.sleep(0.2)
except Exception as e:
print(e)
except KeyboardInterrupt:
break
58 changes: 45 additions & 13 deletions kellerLD.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ class KellerLD(object):
"PAA Mode, Absolute Gauge" # Zero at vacuum
)
_P_MODE_OFFSETS = (1.01325, 1.0, 0.0)
PRESSURE_CONVERSION = {
"Pa" : 100000,
"mbar" : 1000,
"bar" : 1,
}

def __init__(self, bus=1):
self._bus = None
self._fluid_density = 1029 # kg/m^3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably use set_fluid_density (e.g. in case someone changes the function to include logging later), and should probably also have a parameter in the __init__ definition (e.g. def __init__(self, bus=1, fluid_density=1029):) so it's settable directly on object instantiation.


try:
self._bus = smbus.SMBus(bus)
Expand All @@ -30,8 +36,8 @@ def init(self):
if self._bus is None:
print("No bus!")
return False
# Read out pressure-mode to determine relevant offset

# Read out pressure-mode to determine relevant offset
self._bus.write_byte(self._SLAVE_ADDRESS, 0x12)
time.sleep(0.001)
# read three bytes (status, P MSB, P LSB)
Expand All @@ -41,26 +47,26 @@ def init(self):
# E=(0:checksum okay, 1:memory error)
# X=(don't care)
data = self._bus.read_i2c_block_data(self._SLAVE_ADDRESS, 0, 3)

scaling0 = data[1] << 8 | data[2]
self.debug(("0x12:", scaling0, data))

pModeID = scaling0 & 0b11
self.pMode = self._P_MODES[pModeID]
self.pModeOffset = self._P_MODE_OFFSETS[pModeID]
self.debug(("pMode", self.pMode, "pressure offset [bar]", self.pModeOffset))

self.year = scaling0 >> 11
self.month = (scaling0 & 0b0000011110000000) >> 7
self.day = (scaling0 & 0b0000000001111100) >> 2
self.debug(("calibration date", self.year, self.month, self.day))

# Read out minimum pressure reading
time.sleep(0.001)
self._bus.write_byte(self._SLAVE_ADDRESS, 0x13)
time.sleep(0.001)
data = self._bus.read_i2c_block_data(self._SLAVE_ADDRESS, 0, 3)

MSWord = data[1] << 8 | data[2]
self.debug(("0x13:", MSWord, data))

Expand All @@ -80,7 +86,7 @@ def init(self):
self._bus.write_byte(self._SLAVE_ADDRESS, 0x15)
time.sleep(0.001)
data = self._bus.read_i2c_block_data(self._SLAVE_ADDRESS, 0, 3)

MSWord = data[1] << 8 | data[2]
self.debug(("0x15:", MSWord, data))

Expand All @@ -94,7 +100,7 @@ def init(self):

self.pMax = MSWord << 16 | LSWord
self.debug(("pMax", self.pMax))

# 'I' for 32bit unsigned int
self.pMin = struct.unpack('f', struct.pack('I', self.pMin))[0]
self.pMax = struct.unpack('f', struct.pack('I', self.pMax))[0]
Expand All @@ -106,7 +112,7 @@ def read(self):
if self._bus is None:
print("No bus!")
return False

if self.pMin is None or self.pMax is None:
print("Init required!")
print("Call init() at least one time before attempting to read()")
Expand Down Expand Up @@ -141,10 +147,23 @@ def read(self):

self._pressure = (pressureRaw - 16384) * (self.pMax - self.pMin) / 32768 + self.pMin + self.pModeOffset
self._temperature = ((temperatureRaw >> 4) - 24) * 0.05 - 50
self._depth = ((self._pressure * self.PRESSURE_CONVERSION["Pa"]) - 101325) / (self._fluid_density * 9.80665)
self._altitude = (1-((self._pressure * self.PRESSURE_CONVERSION["mbar"] / 1013.25)**0.190284)) * 145366.45 * .3048

self.debug(("data:", data))
self.debug(("pressureRaw:", pressureRaw, "pressure:", self._pressure))
self.debug(("temperatureRaw", temperatureRaw, "temperature:", self._temperature))
self.debug(("depth:", self._depth))
self.debug(("altitude:", self._altitude))

return True

def set_fluid_density(self, fluid_density):
'''
Provide the density of the working fluid in kg/m^3. Default is for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, because the fluid_density parameter has no default value - the "default" mentioned in the docstring is instead a default from class instantiation (which is outside the scope of this function, and likely isn't relevant to mention here).

It may also be worth adding a few string-based defaults, either just 'fresh'->997 and 'sea'->1029, or could make use of wikipedia's salinity levels by water type overview. Not essential, just could be nice to have (although those levels could also be implemented separately in a Water class or something, which may be more appropriate).

seawater. Should be 997 for freshwater.
'''
self._fluid_density = fluid_density

return True

Expand All @@ -155,16 +174,29 @@ def temperature(self):
return
return self._temperature

def pressure(self):
def pressure(self, conversion = "bar"):
assert self.PRESSURE_CONVERSION.get(conversion) is not None, "Invalid Pressure Unit: {}".format(conversion)
if self._pressure is None:
print("Call read() first to get a measurement")
return
return self._pressure
return self._pressure * self.PRESSURE_CONVERSION[conversion]

def depth(self):
if self._depth is None:
print("Call read() first to get a measurement")
return
return self._depth

def altitude(self):
if self._altitude is None:
print("Call read() first to get a measurement")
return
return self._altitude

def debug(self, msg):
if self._DEBUG:
print(msg)

def __str__(self):
return ("Keller LD I2C Pressure/Temperature Transmitter\n" +
"\ttype: {}\n".format(self.pMode) +
Expand Down