gabriel becker
2 years ago
4 changed files with 281 additions and 15 deletions
@ -0,0 +1,252 @@ |
|||||||
|
# The MIT License (MIT) |
||||||
|
# |
||||||
|
# Copyright (c) 2016 Radomir Dopieralski (@deshipu), |
||||||
|
# 2017 Robert Hammelrath (@robert-hh) |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in |
||||||
|
# all copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||||
|
# THE SOFTWARE. |
||||||
|
# |
||||||
|
import utime as time |
||||||
|
|
||||||
|
_REGISTER_MASK = const(0x03) |
||||||
|
_REGISTER_CONVERT = const(0x00) |
||||||
|
_REGISTER_CONFIG = const(0x01) |
||||||
|
_REGISTER_LOWTHRESH = const(0x02) |
||||||
|
_REGISTER_HITHRESH = const(0x03) |
||||||
|
|
||||||
|
_OS_MASK = const(0x8000) |
||||||
|
_OS_SINGLE = const(0x8000) # Write: Set to start a single-conversion |
||||||
|
_OS_BUSY = const(0x0000) # Read: Bit=0 when conversion is in progress |
||||||
|
_OS_NOTBUSY = const(0x8000) # Read: Bit=1 when no conversion is in progress |
||||||
|
|
||||||
|
_MUX_MASK = const(0x7000) |
||||||
|
_MUX_DIFF_0_1 = const(0x0000) # Differential P = AIN0, N = AIN1 (default) |
||||||
|
_MUX_DIFF_0_3 = const(0x1000) # Differential P = AIN0, N = AIN3 |
||||||
|
_MUX_DIFF_1_3 = const(0x2000) # Differential P = AIN1, N = AIN3 |
||||||
|
_MUX_DIFF_2_3 = const(0x3000) # Differential P = AIN2, N = AIN3 |
||||||
|
_MUX_SINGLE_0 = const(0x4000) # Single-ended AIN0 |
||||||
|
_MUX_SINGLE_1 = const(0x5000) # Single-ended AIN1 |
||||||
|
_MUX_SINGLE_2 = const(0x6000) # Single-ended AIN2 |
||||||
|
_MUX_SINGLE_3 = const(0x7000) # Single-ended AIN3 |
||||||
|
|
||||||
|
_PGA_MASK = const(0x0E00) |
||||||
|
_PGA_6_144V = const(0x0000) # +/-6.144V range = Gain 2/3 |
||||||
|
_PGA_4_096V = const(0x0200) # +/-4.096V range = Gain 1 |
||||||
|
_PGA_2_048V = const(0x0400) # +/-2.048V range = Gain 2 (default) |
||||||
|
_PGA_1_024V = const(0x0600) # +/-1.024V range = Gain 4 |
||||||
|
_PGA_0_512V = const(0x0800) # +/-0.512V range = Gain 8 |
||||||
|
_PGA_0_256V = const(0x0A00) # +/-0.256V range = Gain 16 |
||||||
|
|
||||||
|
_MODE_MASK = const(0x0100) |
||||||
|
_MODE_CONTIN = const(0x0000) # Continuous conversion mode |
||||||
|
_MODE_SINGLE = const(0x0100) # Power-down single-shot mode (default) |
||||||
|
|
||||||
|
_DR_MASK = const(0x00E0) # Values ADS1015/ADS1115 |
||||||
|
_DR_128SPS = const(0x0000) # 128 /8 samples per second |
||||||
|
_DR_250SPS = const(0x0020) # 250 /16 samples per second |
||||||
|
_DR_490SPS = const(0x0040) # 490 /32 samples per second |
||||||
|
_DR_920SPS = const(0x0060) # 920 /64 samples per second |
||||||
|
_DR_1600SPS = const(0x0080) # 1600/128 samples per second (default) |
||||||
|
_DR_2400SPS = const(0x00A0) # 2400/250 samples per second |
||||||
|
_DR_3300SPS = const(0x00C0) # 3300/475 samples per second |
||||||
|
_DR_860SPS = const(0x00E0) # - /860 samples per Second |
||||||
|
|
||||||
|
_CMODE_MASK = const(0x0010) |
||||||
|
_CMODE_TRAD = const(0x0000) # Traditional comparator with hysteresis (default) |
||||||
|
_CMODE_WINDOW = const(0x0010) # Window comparator |
||||||
|
|
||||||
|
_CPOL_MASK = const(0x0008) |
||||||
|
_CPOL_ACTVLOW = const(0x0000) # ALERT/RDY pin is low when active (default) |
||||||
|
_CPOL_ACTVHI = const(0x0008) # ALERT/RDY pin is high when active |
||||||
|
|
||||||
|
_CLAT_MASK = const(0x0004) # Determines if ALERT/RDY pin latches once asserted |
||||||
|
_CLAT_NONLAT = const(0x0000) # Non-latching comparator (default) |
||||||
|
_CLAT_LATCH = const(0x0004) # Latching comparator |
||||||
|
|
||||||
|
_CQUE_MASK = const(0x0003) |
||||||
|
_CQUE_1CONV = const(0x0000) # Assert ALERT/RDY after one conversions |
||||||
|
_CQUE_2CONV = const(0x0001) # Assert ALERT/RDY after two conversions |
||||||
|
_CQUE_4CONV = const(0x0002) # Assert ALERT/RDY after four conversions |
||||||
|
# Disable the comparator and put ALERT/RDY in high state (default) |
||||||
|
_CQUE_NONE = const(0x0003) |
||||||
|
|
||||||
|
_GAINS = ( |
||||||
|
_PGA_6_144V, # 2/3x |
||||||
|
_PGA_4_096V, # 1x |
||||||
|
_PGA_2_048V, # 2x |
||||||
|
_PGA_1_024V, # 4x |
||||||
|
_PGA_0_512V, # 8x |
||||||
|
_PGA_0_256V # 16x |
||||||
|
) |
||||||
|
|
||||||
|
_GAINS_V = ( |
||||||
|
6.144, # 2/3x |
||||||
|
4.096, # 1x |
||||||
|
2.048, # 2x |
||||||
|
1.024, # 4x |
||||||
|
0.512, # 8x |
||||||
|
0.256 # 16x |
||||||
|
) |
||||||
|
|
||||||
|
_CHANNELS = { |
||||||
|
(0, None): _MUX_SINGLE_0, |
||||||
|
(1, None): _MUX_SINGLE_1, |
||||||
|
(2, None): _MUX_SINGLE_2, |
||||||
|
(3, None): _MUX_SINGLE_3, |
||||||
|
(0, 1): _MUX_DIFF_0_1, |
||||||
|
(0, 3): _MUX_DIFF_0_3, |
||||||
|
(1, 3): _MUX_DIFF_1_3, |
||||||
|
(2, 3): _MUX_DIFF_2_3, |
||||||
|
} |
||||||
|
|
||||||
|
_RATES = ( |
||||||
|
_DR_128SPS, # 128/8 samples per second |
||||||
|
_DR_250SPS, # 250/16 samples per second |
||||||
|
_DR_490SPS, # 490/32 samples per second |
||||||
|
_DR_920SPS, # 920/64 samples per second |
||||||
|
_DR_1600SPS, # 1600/128 samples per second (default) |
||||||
|
_DR_2400SPS, # 2400/250 samples per second |
||||||
|
_DR_3300SPS, # 3300/475 samples per second |
||||||
|
_DR_860SPS # - /860 samples per Second |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
class ADS1115: |
||||||
|
def __init__(self, i2c, address=0x48, gain=1): |
||||||
|
self.i2c = i2c |
||||||
|
self.address = address |
||||||
|
self.gain = gain |
||||||
|
self.temp2 = bytearray(2) |
||||||
|
|
||||||
|
def _write_register(self, register, value): |
||||||
|
self.temp2[0] = value >> 8 |
||||||
|
self.temp2[1] = value & 0xff |
||||||
|
self.i2c.writeto_mem(self.address, register, self.temp2) |
||||||
|
|
||||||
|
def _read_register(self, register): |
||||||
|
self.i2c.readfrom_mem_into(self.address, register, self.temp2) |
||||||
|
return (self.temp2[0] << 8) | self.temp2[1] |
||||||
|
|
||||||
|
def raw_to_v(self, raw): |
||||||
|
v_p_b = _GAINS_V[self.gain] / 32767 |
||||||
|
return raw * v_p_b |
||||||
|
|
||||||
|
def set_conv(self, rate=4, channel1=0, channel2=None): |
||||||
|
"""Set mode for read_rev""" |
||||||
|
self.mode = (_CQUE_NONE | _CLAT_NONLAT | |
||||||
|
_CPOL_ACTVLOW | _CMODE_TRAD | _RATES[rate] | |
||||||
|
_MODE_SINGLE | _OS_SINGLE | _GAINS[self.gain] | |
||||||
|
_CHANNELS[(channel1, channel2)]) |
||||||
|
|
||||||
|
def read(self, rate=4, channel1=0, channel2=None): |
||||||
|
"""Read voltage between a channel and GND. |
||||||
|
Time depends on conversion rate.""" |
||||||
|
self._write_register(_REGISTER_CONFIG, (_CQUE_NONE | _CLAT_NONLAT | |
||||||
|
_CPOL_ACTVLOW | _CMODE_TRAD | _RATES[rate] | |
||||||
|
_MODE_SINGLE | _OS_SINGLE | _GAINS[self.gain] | |
||||||
|
_CHANNELS[(channel1, channel2)])) |
||||||
|
while not self._read_register(_REGISTER_CONFIG) & _OS_NOTBUSY: |
||||||
|
time.sleep_ms(1) |
||||||
|
res = self._read_register(_REGISTER_CONVERT) |
||||||
|
return res if res < 32768 else res - 65536 |
||||||
|
|
||||||
|
def read_rev(self): |
||||||
|
"""Read voltage between a channel and GND. and then start |
||||||
|
the next conversion.""" |
||||||
|
res = self._read_register(_REGISTER_CONVERT) |
||||||
|
self._write_register(_REGISTER_CONFIG, self.mode) |
||||||
|
return res if res < 32768 else res - 65536 |
||||||
|
|
||||||
|
def alert_start(self, rate=4, channel1=0, channel2=None, |
||||||
|
threshold_high=0x4000, threshold_low=0, latched=False) : |
||||||
|
"""Start continuous measurement, set ALERT pin on threshold.""" |
||||||
|
self._write_register(_REGISTER_LOWTHRESH, threshold_low) |
||||||
|
self._write_register(_REGISTER_HITHRESH, threshold_high) |
||||||
|
self._write_register(_REGISTER_CONFIG, _CQUE_1CONV | |
||||||
|
_CLAT_LATCH if latched else _CLAT_NONLAT | |
||||||
|
_CPOL_ACTVLOW | _CMODE_TRAD | _RATES[rate] | |
||||||
|
_MODE_CONTIN | _GAINS[self.gain] | |
||||||
|
_CHANNELS[(channel1, channel2)]) |
||||||
|
|
||||||
|
def conversion_start(self, rate=4, channel1=0, channel2=None): |
||||||
|
"""Start continuous measurement, trigger on ALERT/RDY pin.""" |
||||||
|
self._write_register(_REGISTER_LOWTHRESH, 0) |
||||||
|
self._write_register(_REGISTER_HITHRESH, 0x8000) |
||||||
|
self._write_register(_REGISTER_CONFIG, _CQUE_1CONV | _CLAT_NONLAT | |
||||||
|
_CPOL_ACTVLOW | _CMODE_TRAD | _RATES[rate] | |
||||||
|
_MODE_CONTIN | _GAINS[self.gain] | |
||||||
|
_CHANNELS[(channel1, channel2)]) |
||||||
|
|
||||||
|
def alert_read(self): |
||||||
|
"""Get the last reading from the continuous measurement.""" |
||||||
|
res = self._read_register(_REGISTER_CONVERT) |
||||||
|
return res if res < 32768 else res - 65536 |
||||||
|
|
||||||
|
|
||||||
|
class ADS1113(ADS1115): |
||||||
|
def __init__(self, i2c, address=0x48): |
||||||
|
super().__init__(i2c, address, 1) |
||||||
|
|
||||||
|
def raw_to_v(self, raw): |
||||||
|
return super().raw_to_v(raw) |
||||||
|
|
||||||
|
def read(self, rate=4): |
||||||
|
return super().read(rate, 0, 1) |
||||||
|
|
||||||
|
def alert_start(self, rate=4, threshold_high=0x4000, threshold_low=0, latched=False): |
||||||
|
return super().alert_start(rate, 0, 1, threshold_high, threshold_low, latched) |
||||||
|
|
||||||
|
def alert_read(self): |
||||||
|
return super().alert_read() |
||||||
|
|
||||||
|
|
||||||
|
class ADS1114(ADS1115): |
||||||
|
def __init__(self, i2c, address=0x48, gain=1): |
||||||
|
super().__init__(i2c, address, gain) |
||||||
|
|
||||||
|
def raw_to_v(self, raw): |
||||||
|
return super().raw_to_v(raw) |
||||||
|
|
||||||
|
def read(self, rate=4): |
||||||
|
return super().read(rate, 0, 1) |
||||||
|
|
||||||
|
def alert_start(self, rate=4, threshold_high=0x4000, threshold_low=0, latched=False): |
||||||
|
return super().alert_start(rate, 0, 1, threshold_high, |
||||||
|
threshold_low, latched) |
||||||
|
|
||||||
|
def alert_read(self): |
||||||
|
return super().alert_read() |
||||||
|
|
||||||
|
|
||||||
|
class ADS1015(ADS1115): |
||||||
|
def __init__(self, i2c, address=0x48, gain=1): |
||||||
|
super().__init__(i2c, address, gain) |
||||||
|
|
||||||
|
def raw_to_v(self, raw): |
||||||
|
return super().raw_to_v(raw << 4) |
||||||
|
|
||||||
|
def read(self, rate=4, channel1=0, channel2=None): |
||||||
|
return super().read(rate, channel1, channel2) >> 4 |
||||||
|
|
||||||
|
def alert_start(self, rate=4, channel1=0, channel2=None, threshold_high=0x400, |
||||||
|
threshold_low=0, latched=False): |
||||||
|
return super().alert_start(rate, channel1, channel2, threshold_high << 4, |
||||||
|
threshold_low << 4, latched) |
||||||
|
|
||||||
|
def alert_read(self): |
||||||
|
return super().alert_read() >> 4 |
@ -1,15 +1,17 @@ |
|||||||
"""RASPBERRY PICO PINS""" |
"""RASPBERRY PICO PINS""" |
||||||
"""PINOUTS""" |
"""PINOUTS""" |
||||||
PRESSURE_SENSOR_PIN = 26 |
|
||||||
HALL_SENSOR_PIN = 27 |
HALL_SENSOR_PIN = 27 |
||||||
RESET_BUTTON_PIN = 22 |
RESET_BUTTON_PIN = 22 |
||||||
BUZZER_PIN = 15 |
BUZZER_PIN = 15 |
||||||
|
ALARM_LED_PIN = 26 |
||||||
LCD_SDA = 0 |
LCD_SDA = 0 |
||||||
LCD_SCL = 1 |
LCD_SCL = 1 |
||||||
|
PRESSURE_SENSOR_ADC_SDA = 10 |
||||||
|
PRESSURE_SENSOR_ADC_SCL = 11 |
||||||
|
|
||||||
|
|
||||||
"""FIXED NUMBERS""" |
"""FIXED NUMBERS""" |
||||||
ANNOYTING_BUZZER_TONE = 51250 |
ANNOYTING_BUZZER_TONE = 51250 |
||||||
NORMAL_BUZZER_TONE = 200 |
NORMAL_BUZZER_TONE = 200 |
||||||
ADC_RESOLUTION = 65535.0 |
ADC_RESOLUTION = 32768.0 |
||||||
MAX_VOTLAGE = 3.3 |
MAX_PRESSURE_SENSOR_VOTLAGE = 6.144 |
||||||
|
@ -1,14 +1,26 @@ |
|||||||
from machine import ADC, Pin |
from machine import I2C, Pin, Timer |
||||||
|
import ads1x15 |
||||||
|
|
||||||
import constants |
import constants |
||||||
import parameters |
import parameters |
||||||
|
|
||||||
|
|
||||||
pressure_sensor = ADC(Pin(constants.PRESSURE_SENSOR_PIN, mode=Pin.IN)) |
class PressureSensor: |
||||||
|
|
||||||
|
_I2C = I2C(1, scl=Pin(constants.PRESSURE_SENSOR_ADC_SCL), sda=Pin(constants.PRESSURE_SENSOR_ADC_SDA), freq=400000) |
||||||
|
_I2C_ADDR = _I2C.scan()[0] |
||||||
|
_ADC = ads1x15.ADS1115(_I2C, _I2C_ADDR, 0) |
||||||
|
_SMOOTH_FACTOR = parameters.PRESSURE_SMOOTH_LENGTH * constants.ADC_RESOLUTION / constants.MAX_PRESSURE_SENSOR_VOTLAGE |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def read(): |
||||||
|
measure = PressureSensor._ADC.read(0) |
||||||
|
return measure |
||||||
|
|
||||||
def get_pressure(): |
@staticmethod |
||||||
global pressure_sensor |
def get_pressure(): |
||||||
pressure_value = 0 |
pressure_value = 0 |
||||||
for i in range(parameters.PRESSURE_SMOOTH_LENGTH): |
for i in range(parameters.PRESSURE_SMOOTH_LENGTH): |
||||||
pressure_value += pressure_sensor.read_u16() |
pressure_value += PressureSensor.read() |
||||||
pressure_measure = float(pressure_value) / parameters.PRESSURE_SMOOTH_LENGTH / constants.ADC_RESOLUTION * constants.MAX_VOTLAGE |
pressure_measure = float(pressure_value) / PressureSensor._SMOOTH_FACTOR |
||||||
return pressure_measure |
return pressure_measure |
||||||
|
Loading…
Reference in new issue