ltr390uv

Форк
0
/
ltr390uv.py 
254 строки · 12.9 Кб
1
"""Модуль управления LTR-390UV-01, это датчик внешней освещенности и датчик ультрафиолетового света (UVS)"""
2
import time
3

4
# micropython
5
# mail: goctaprog@gmail.com
6
# MIT license
7
# import struct
8

9
from sensor_pack_2 import bus_service
10
from sensor_pack_2.base_sensor import BaseSensorEx, Iterator, get_error_str, check_value
11
# from machine import Pin  # I2C, SPI,
12
# import micropython
13
from sensor_pack_2.bitfield import bit_field_info
14
# from micropython import const
15
from collections import namedtuple
16
from sensor_pack_2.bitfield import BitFields
17
from sensor_pack_2.regmod import RegistryRO, RegistryRW
18

19
# power_on - (1) Power on event and all interrupt threshold settings in the registers
20
#               have been reset to power on default states and should be
21
#               examined if necessary.
22
# int_status - (1) Interrupt is triggered and will be cleared after read
23
# data_status - (1) UVS/ALS data is new data (Data has not been read and will be
24
#               cleared after read)
25
sensor_status = namedtuple("sensor_status", "power_on int_status data_status")
26

27
'''
28
Address R/W     Register Name       Description                                                 Reset Value
29
0x00    R/W     MAIN_CTRL           ALS/UVS operation mode control, SW reset                    0x00
30
0x04    R/W     ALS_UVS_MEAS_RATE   ALS/UVS measurement rate and resolution in Active Mode      0x22
31
0x05    R/W     ALS_UVS_GAIN        ALS/UVS analog Gain range                                   0x01
32
0x06    R       PART_ID             Part number ID and revision ID                              0xB2
33
0x07    R       MAIN_STATUS         Power-On status, Interrupt status, Data status              0x20
34
0x0D    R       ALS_DATA_0          ALS ADC measurement data, LSB                               0x0
35
0x0E    R       ALS_DATA_1          ALS ADC measurement data                                    0x0
36
0x0F    R       ALS_DATA_2          ALS ADC measurement data, MSB                               0x0
37
0x10    R       UVS_DATA_0          UVS ADC measurement data, LSB                               0x0
38
0x11    R       UVS_DATA_1          UVS ADC measurement data                                    0x0
39
0x12    R       UVS_DATA_2          UVS ADC measurement data, MSB                               0x0
40
'''
41

42
# регистр режимов работы датчика
43
_main_control_reg = (bit_field_info(name='soft_reset', position=range(4, 5), valid_values=None),
44
                     bit_field_info(name='UVS_mode', position=range(3, 4), valid_values=None),
45
                     bit_field_info(name='ALS_UVS_enable', position=range(1, 2), valid_values=None))
46

47
# регистр периода/частоты измерений
48
_meas_rate_reg = (bit_field_info(name='resolution', position=range(4, 7), valid_values=range(6)),
49
                  bit_field_info(name='meas_rate', position=range(3), valid_values=range(6)))
50

51
# регистр усиления
52
_gain_reg = (bit_field_info(name='gain', position=range(3), valid_values=range(5)),)
53

54
# Part ID and Revision ID
55
_id_reg = (bit_field_info(name='part_id', position=range(4, 8), valid_values=None),
56
           bit_field_info(name='rev_id', position=range(4), valid_values=None))
57

58
# регистр состояния
59
_main_status_reg = (bit_field_info(name='power_on', position=range(5, 6), valid_values=None),
60
                    bit_field_info(name='int_status', position=range(4, 5), valid_values=None),
61
                    bit_field_info(name='data_status', position=range(3, 4), valid_values=None))
62

63

64
class LTR390UV(BaseSensorEx, Iterator):
65
    """Класс, управляющий ALS&UV датчиком LTR-390UV"""
66

67
    def __init__(self, adapter: bus_service.BusAdapter, address=0x53):
68
        """i2c - объект класса I2C; address - адрес датчика на шине"""
69
        super().__init__(adapter, address, False)
70
        self._id_reg = RegistryRO(device=self, address=0x06, fields=BitFields(_id_reg), byte_len=None)
71
        self._status_reg = RegistryRO(device=self, address=0x07, fields=BitFields(_main_status_reg), byte_len=None)
72
        self._meas_rate_reg = RegistryRW(device=self, address=0x04, fields=BitFields(_meas_rate_reg), byte_len=None)
73
        self._gain_reg = RegistryRW(device=self, address=0x05, fields=BitFields(_gain_reg), byte_len=None)
74
        self.ctrl_reg = RegistryRW(device=self, address=0x00, fields=BitFields(_main_control_reg), byte_len=None)
75
        # буфер на 3 байта
76
        self._buf_3 = bytearray((0 for _ in range(3)))
77
        # настройки, обновляются методом xxx!
78
        self._uv_sens = 2300    # чувствительность датчика в UV диапазоне для разрешения отсчета в 18..20 бит!
79
        #
80
        self._uv_mode = None
81
        self._resolution = None
82
        self._meas_rate = None
83
        self._gain = None
84
        self._enabled = None
85

86
    def get_status(self) -> sensor_status:
87
        """Возвращает состояние датчика"""
88
        _reg = self._status_reg
89
        _reg.read()
90
        return sensor_status(power_on=_reg['power_on'], int_status=_reg['int_status'], data_status=_reg['data_status'])
91

92
    def get_conversion_cycle_time(self) -> int:
93
        """возвращает время преобразования датчика в [мc]. Первым должен быть вызван метод start_measurement!"""
94
        return LTR390UV._meas_rate_to_ms(self.meas_rate)
95

96
    @staticmethod
97
    def _meas_rate_to_resolution(meas_rate: int) -> int:
98
        """возвращает разрешение в условных единицах, соответствующее meas_rate.
99
        Значение разрешения 13 Bit не используется!!!
100
        meas_rate/ms       resolution/bit in sample/conversion time ms
101
        0/25               4/16/25
102
        1/50               3/17/50
103
        2/100              2/18/100
104
        3/200              1/19/200
105
        4/500              0/20/400
106
        5/1000             0/20/400
107
        """
108
        vr = range(6)
109
        check_value(meas_rate, vr, get_error_str("meas_rate", meas_rate, vr))
110
        # 0 - 20 bit
111
        _resol = 4, 3, 2, 1, 0, 0
112
        return _resol[meas_rate]
113

114
    @staticmethod
115
    def _meas_rate_to_ms(meas_rate: int) -> int:
116
        """возвращает частоту преобразования(условные единицы) во время преобразования(conversion time) в мс"""
117
        vr = range(6)
118
        check_value(meas_rate, vr, get_error_str("meas_rate", meas_rate, vr))
119
        _conv_time = 25, 50, 100, 200, 500, 1000
120
        return _conv_time[meas_rate]
121

122
    def get_id(self) -> tuple:
123
        """Возвращает Part_ID, Revision_ID"""
124
        _reg = self._id_reg
125
        _reg.read()
126
        return _reg['part_id'], _reg['rev_id']
127

128
    def soft_reset(self):
129
        """Производит програмный сброс датчика"""
130
        _reg = self.ctrl_reg
131
        _reg['soft_reset'] = 1
132
        _reg.write()
133
        # чтение с ожиданием
134
        for i in range(3):
135
            time.sleep_ms(10)
136
            try:
137
                _reg.read()
138
                if not _reg['soft_reset']:
139
                    break
140
            except OSError as ex:
141
                if 110 == ex.errno:
142
                    pass
143
                else:
144
                    raise ex
145
        else:       # for. break не был выполнен! ошибка программного сброса датчика
146
            raise ValueError("soft_reset error!")
147
        # выход по break. програмный сброс успешно произведен.
148

149
    @property
150
    def gain(self) -> [int, None]:
151
        """Возвращает усиление в условных единицах от 0 до 4 включительно"""
152
        return self._gain
153

154
    @property
155
    def meas_rate(self) -> [int, None]:
156
        """Возвращает период обновления данных датчиком в условных единицах от 0 до 6 включительно"""
157
        return self._meas_rate
158

159
    @property
160
    def resolution(self) -> [int, None]:
161
        """Возвращает кол-во бит в отсчете в условных единицах от 0 до 5 включительно.
162
        resolution вычисляется автоматически по значению поля meas_rate метода start_measurement"""
163
        return self._resolution
164

165
    @property
166
    def uv_mode(self) -> [bool, None]:
167
        return self._uv_mode
168

169
    @property
170
    def in_standby(self) -> bool:
171
        """Если возвратит Истина, то устройство находится в режиме standby"""
172
        return not self._enabled
173

174
    @property
175
    def uv_sensitivity(self) -> int:
176
        """Возвращает чувствительность датчика в UV диапазоне в условных единицах"""
177
        return self._uv_sens
178

179
    @uv_sensitivity.setter
180
    def uv_sensitivity(self, value: int):
181
        """Устанавливает чувствительность датчика в UV диапазоне в условных единицах"""
182
        rng = range(1, 10_000)
183
        check_value(value, rng, get_error_str("UV sensitivity", value, rng))
184
        self._uv_sens = value
185

186
    def set_active(self, value: bool = True):
187
        """Если value в Истина, то датчик в режиме работа, иначе в режиме ожидания/standby"""
188
        _reg = self.ctrl_reg
189
        _reg.read()
190
        _reg['ALS_UVS_enable'] = value
191
        _reg.write()
192
        #
193
        _reg.read()
194
        self._enabled = _reg['ALS_UVS_enable']
195

196
    def start_measurement(self, uv_mode: bool, meas_rate: int = 1, gain: int = 3, enable: bool = True):
197
        """Производит настройку параметров измерения.
198
        Если uv_mode в Истина, то датчик измеряет освещенность в УФ диапазоне, иначе в видимом диапазоне!
199
        meas_rate - период обновления датчиком информации, от 0 до 5 включительно. 0 - 25 мс, 5 - 2000 мс.
200
        resolution - вычисляется по meas_rate! Значение разрешения 13 Bit не используется!!!
201
        gain - коэффициент усиления. от 0 до 4 включительно. 0 - 1, 4 - 18"""
202
        _reg = self._meas_rate_reg
203
        _reg.read()
204
        _reg['meas_rate'] = meas_rate
205
        _reg['resolution'] = LTR390UV._meas_rate_to_resolution(meas_rate)
206
        _reg.write()    # запись в регистр meas_rate
207
        #
208
        _reg = self._gain_reg
209
        _reg.read()
210
        _reg['gain'] = gain
211
        _reg.write()    # запись в регистр gain
212
        #
213
        _reg = self.ctrl_reg
214
        _reg.read()
215
        _reg['ALS_UVS_enable'] = enable
216
        _reg['UVS_mode'] = uv_mode
217
        _reg.write()    # запись в регистр управления
218
        # читаю настройки из датчика
219
        _reg = self._meas_rate_reg
220
        _reg.read()     # чтение регистра meas_rate
221
        self._meas_rate = _reg['meas_rate']
222
        self._resolution = _reg['resolution']
223
        #
224
        _reg = self._gain_reg
225
        _reg.read()     # чтение регистра gain
226
        self._gain = _reg['gain']
227
        #
228
        _reg = self.ctrl_reg
229
        _reg.read()     # чтение регистра управления
230
        self._uv_mode = _reg['UVS_mode']
231
        self._enabled = _reg['ALS_UVS_enable']
232

233
    def get_illumination(self, raw: bool = True, w_fac: float = 1.0) -> [int, float]:
234
        """Возвращает освещенность в 'сырых' единицах если raw в Истина, или в люксах, если raw в Ложь"""
235
        addr = 0x10 if self.uv_mode else 0x0D
236
        buf = self._buf_3
237
        self.read_buf_from_mem(addr, buf, 1)
238
        val = buf[0] + 256 * buf[1] + 65536 * buf[2]
239
        # для режима UV значения в UVI недоступны. Производитель привел формулу, которая, по моему мнению, неверна!
240
        # поэтому, при переключении в uv_mode вы будете получать от датчика только 'сырые' значения!
241
        if raw or self.uv_mode:
242
            return val
243
        _gain = 1, 3, 6, 9, 18  # для пересчета gain
244
        x = 0.25 * 2 ** self.resolution
245
        _tmp = _gain[self.gain] * x
246
        # lux. als
247
        return 0.6 * w_fac * val / _tmp   # lux
248

249
    # Iterator
250
    def __next__(self) -> [float, int, None]:
251
        """Часть протокола итератора"""
252
        if self.uv_mode is None:
253
            return None
254
        return self.get_illumination(raw=False)
255

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

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

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

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