SHT4X

Форк
0
/
sht4xmod.py 
152 строки · 7.8 Кб
1
"""SHT4x Sensirion module"""
2
import time
3

4
from sensor_pack_2 import bus_service
5
from sensor_pack_2.base_sensor import BaseSensorEx, IBaseSensorEx, check_value
6
from sensor_pack_2.crc_mod import crc8
7

8
def _calc_crc(sequence) -> int:
9
    """Обертка для короткого вызова."""
10
    return crc8(sequence, polynomial=0x31, init_value=0xFF)
11

12
class SHT4xSensirion(BaseSensorEx, IBaseSensorEx):
13
    """Class for work with Sensirion SHT4x sensor"""
14
    cmd_get_id = 0x89
15
    cmd_soft_reset = 0x94
16
    magic = -1 + 2 ** 16
17

18
    def __init__(self, adapter: bus_service.BusAdapter, address=0x44, check_crc: bool = True):
19
        """Если check_crc в Истина, то каждый, принятый от датчика пакет данных, проверяется на правильность путем
20
        расчета контрольной суммы."""
21
        check_value(address, range(0x44, 0x47), f"Неверный адрес устройства: {address}")
22
        super().__init__(adapter, address, True)
23
        self._check_crc = check_crc
24
        self._last_cmd_code = None
25
        #
26
        self._with_heater = None
27
        self._value = None
28
        self._long_pulse = None
29
        #
30
        self._buf_1 = bytearray(1)
31
        self._buf_6 = bytearray(6)
32

33
    #@staticmethod
34
    #def get_answer_len(command_code: int) -> int:
35
    #    """Возвращает количество байт в ответе датчика"""
36
    #    if SHT4xSensirion.cmd_soft_reset == command_code:
37
    #        return 0
38
    #    return 6
39

40
    def get_last_cmd_code(self) -> int:
41
        """Возвращает последний код команды, переданный по шине данных в датчик"""
42
        return self._last_cmd_code
43

44
    def _send_command(self, command_code: int):
45
        """Передает команду датчику по шине"""
46
        check_value(command_code, range(0x100), f"Неверный код команды: {command_code}")
47
        _local = self._buf_1
48
        _local[0] = command_code
49
        self.write(_local)
50
        self._last_cmd_code = command_code
51

52
    def _read_answer(self) -> [bytes, None]:
53
        """Читает ответ на команду, переданную методом _send_command.
54
        Возвращает ссылку на буфер с принятыми данными.
55
        Проверяет CRC"""
56
        _cmd = self.get_last_cmd_code()
57
        if SHT4xSensirion.cmd_soft_reset == _cmd:
58
            return None
59
        _buf = self._buf_6
60
        self.read_to_buf(_buf)
61
        # ответ считан
62
        if self._check_crc:
63
            crc_from_buf = [_buf[i] for i in (2, 5)]  # список со значениями CRC
64
            calculated_crc = [_calc_crc(_buf[rng.start:rng.stop]) for rng in (range(2), range(3, 5))]
65
            if crc_from_buf != calculated_crc:
66
                raise ValueError(f"Неверная CRC! Вычислено: {calculated_crc}. Из буфера: {crc_from_buf};")
67
        return _buf
68

69
    def get_id(self) -> tuple[int, int]:
70
        _cmd = SHT4xSensirion.cmd_get_id
71
        self._send_command(_cmd)
72
        # этот 'чудо-датчик' не может сразу отдать прошитый в нем номер! Приходится вызывать sleep_us!
73
        time.sleep_us(110)
74
        _buf = self._read_answer()
75
        t = self.unpack("HBH", _buf)
76
        # отбрасываю CRC
77
        return t[0], t[2]
78

79
    def soft_reset(self):
80
        """Программный сброс датчика. После сброса датчик переходит в состояние простоя, idle state!"""
81
        self._send_command(SHT4xSensirion.cmd_soft_reset)
82

83
    def get_conversion_cycle_time(self) -> int:
84
        """Возвращает время в мкс(!) преобразования сигнала в цифровой код и готовности его для чтения по шине!
85
        Для текущих настроек датчика. При изменении настроек следует заново вызвать этот метод!"""
86
        if not self._with_heater:   # работа без нагрева!
87
            _val = self._value  # 0..2; 0 - низкая, 1 - средняя, 2 - высокая повторяемость/точность
88
            _ms = 1_600, 4_500, 8_300
89
            return _ms[_val]
90

91
        if self._long_pulse:    # работа с нагревом!
92
            return 1_100_000
93
        # короткий импульс нагрева
94
        return 110_000
95

96
    def start_measurement(self, with_heater: bool = False, value: int = 0, long_pulse: bool = False):
97
        """Настраивает параметры датчика и запускает процесс измерения.
98
        with_heater - если Истина, то измерение будет проходить c нагревом (НЕ обычный режим)
99
        value - повторяемость, если with_heater is False:
100
            0       - низкая (самая низкая точность)
101
            1       - средняя (средняя точность)
102
            2       - высокая (высокая точность)
103
        value - мощность нагрева, если with_heater is True:
104
            0       -   20 мВт
105
            1       -   110 мВт
106
            2       -   200 мВт
107
        long_pulse - продолжительность нагрева, используется если with_heater is True:
108
            False   -   0.1 сек
109
            True    -   1.0 сек"""
110
        check_value(value, range(3), f"Неверное значение value: {value}")
111

112
        _cmd = None
113
        if not with_heater:
114
            # нагреватель НЕ используется! 0xE0, 0xF6, 0xFD
115
            _t = 0xE0, 0xF6, 0xFD
116
            _cmd = _t[value]
117

118
        if with_heater:
119
            # используется нагреватель! (0x15, 0x1E), (0x24, 0x2F), (0x32, 0x39)
120
            _t = (0x15, 0x1E), (0x24, 0x2F), (0x32, 0x39)
121
            _cmd = _t[value][long_pulse]
122

123
        # передаю в датчик код команды
124
        self._send_command(_cmd)
125
        # запоминаю для get_conversion_cycle_time
126
        self._with_heater = with_heater
127
        self._value = value
128
        self._long_pulse = long_pulse
129

130
    def get_measurement_value(self) -> [None, tuple[float, float]]:
131
        """Возвращает измеренное датчиком значение/значения"""
132
        _cmd = self.get_last_cmd_code()
133
        if SHT4xSensirion.cmd_get_id == _cmd:
134
            return
135
        _buf = self._read_answer()
136
        _t = self.unpack("HBH", _buf)
137
        t = 175.0 * _t[0] / SHT4xSensirion.magic - 45.0    # температура в градусах Цельсия!
138
        rh = 125.0 * _t[2] / SHT4xSensirion.magic - 6.0    # относительная влажность в процентах!
139
        return t, rh
140

141
    def is_single_shot_mode(self) -> bool:
142
        """Возвращает Истина, когда датчик находится в режиме однократных измерений,
143
        каждое из которых запускается методом start_measurement"""
144
        return True
145

146
    def is_continuously_mode(self) -> bool:
147
        """Возвращает Истина, когда датчик находится в режиме многократных измерений,
148
        производимых автоматически. Процесс запускается методом start_measurement"""
149
        return False
150

151
    # Iterator
152
    # Поскольку разработчики не завезли автоматический режим работы датчика, у меня нет для вас итератора :-)

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.