INA_TI
225 строк · 10.8 Кб
1# micropython
2# MIT license
3# Copyright (c) 2022 Roman Shevchik goctaprog@gmail.com
4import struct
5import micropython
6from sensor_pack_2 import bus_service
7from machine import Pin
8
9
10@micropython.native
11def check_value(value: [int, None], valid_range: [range, tuple], error_msg: str) -> [int, None]:
12if value is None:
13return value
14if value not in valid_range:
15raise ValueError(error_msg)
16return value
17
18
19def get_error_str(val_name: str, val: int, rng: [range, tuple]) -> str:
20"""Возвращает подробное сообщение об ошибке.
21val_name - имя переменной в коде;
22val - значение переменной val_name;
23rng - допустимый диапазон переменной"""
24if isinstance(rng, range):
25return f"Значение {val} параметра {val_name} вне диапазона [{rng.start}..{rng.stop - 1}]!"
26# tuple
27return f"Значение {val} параметра {val_name} вне диапазона: {rng}!"
28
29
30def all_none(*args):
31"""возвращает Истина, если все входные параметры в None.
32Добавил 25.01.2024"""
33for element in args:
34if element is not None:
35return False
36return True
37
38
39class Device:
40"""Класс - основа датчика"""
41
42def __init__(self, adapter: bus_service.BusAdapter, address: [int, Pin], big_byte_order: bool):
43"""Базовый класс Устройство.
44Если big_byte_order равен True -> порядок байтов в регистрах устройства «big»
45(Порядок от старшего к младшему), в противном случае порядок байтов в регистрах "little"
46(Порядок от младшего к старшему)
47address - адрес устройства на шине.
48
49Base device class. if big_byte_order is True -> register values byteorder is 'big'
50else register values byteorder is 'little'
51address - address of the device on the bus."""
52self.adapter = adapter
53self.address = address
54# for I2C. byte order in register of device
55self.big_byte_order = big_byte_order
56# for SPI ONLY. При передаче данных по SPI: SPI.firstbit can be SPI.MSB or SPI.LSB
57# передавать первым битом старший или младший
58# для каждого устройства!
59self.msb_first = True
60
61def _get_byteorder_as_str(self) -> tuple:
62"""Return byteorder as string"""
63if self.is_big_byteorder():
64return 'big', '>'
65return 'little', '<'
66
67def pack(self, fmt_char: str, *values) -> bytes:
68if not fmt_char:
69raise ValueError("Invalid fmt_char parameter!")
70bo = self._get_byteorder_as_str()[1]
71return struct.pack(bo + fmt_char, values)
72
73def unpack(self, fmt_char: str, source: bytes, redefine_byte_order: str = None) -> tuple:
74"""распаковка массива, считанного из датчика.
75Если redefine_byte_order != None, то bo (смотри ниже) = redefine_byte_order
76fmt_char: c, b, B, h, H, i, I, l, L, q, Q. pls see: https://docs.python.org/3/library/struct.html"""
77if not fmt_char:
78raise ValueError("Invalid fmt_char parameter!")
79bo = self._get_byteorder_as_str()[1]
80if redefine_byte_order is not None:
81bo = redefine_byte_order[0]
82return struct.unpack(bo + fmt_char, source)
83
84@micropython.native
85def is_big_byteorder(self) -> bool:
86return self.big_byte_order
87
88
89class DeviceEx(Device):
90"""Класс - основа датчика. Добавил общие методы доступа к шине. 30.01.2024"""
91
92def read_reg(self, reg_addr: int, bytes_count=2) -> bytes:
93"""считывает из регистра датчика значение.
94bytes_count - размер значения в байтах.
95Должна быть реализована во всех классах - адаптерах шин, наследников BusAdapter.
96Добавил 25.01.2024"""
97return self.adapter.read_register(self.address, reg_addr, bytes_count)
98
99# BaseSensor
100def write_reg(self, reg_addr: int, value: [int, bytes, bytearray], bytes_count) -> int:
101"""записывает данные value в датчик, по адресу reg_addr.
102bytes_count - кол-во записываемых данных.
103Добавил 25.01.2024"""
104byte_order = self._get_byteorder_as_str()[0]
105return self.adapter.write_register(self.address, reg_addr, value, bytes_count, byte_order)
106
107def read(self, n_bytes: int) -> bytes:
108"""Читает из устройства n_bytes байт. Добавил 25.01.2024"""
109return self.adapter.read(self.address, n_bytes)
110
111def read_to_buf(self, buf) -> bytes:
112"""Чтение из устройства в буфер"""
113return self.adapter.read_to_buf(self.address, buf)
114
115def write(self, buf: bytes):
116"""Записывает в устройство информацию из buf. Добавил 25.01.2024"""
117return self.adapter.write(self.address, buf)
118
119def read_buf_from_mem(self, address: int, buf, address_size: int = 1):
120"""Читает из устройства, начиная с адреса address в буфер.
121Кол-во читаемых байт равно "длине" буфера в байтах!
122address_size - определяет размер адреса в байтах."""
123return self.adapter.read_buf_from_memory(self.address, address, buf, address_size)
124
125def write_buf_to_mem(self, mem_addr, buf):
126"""Записывает в устройство все байты из буфера buf.
127Запись начинается с адреса в устройстве: mem_addr."""
128return self.adapter.write_buf_to_memory(self.address, mem_addr, buf)
129
130
131class BaseSensor(Device):
132"""Класс - основа датчика с дополнительными методами"""
133
134def get_id(self):
135raise NotImplementedError
136
137def soft_reset(self):
138raise NotImplementedError
139
140
141class BaseSensorEx(DeviceEx):
142"""Класс - основа датчика"""
143
144def get_id(self):
145raise NotImplementedError
146
147def soft_reset(self):
148raise NotImplementedError
149
150
151class Iterator:
152def __iter__(self):
153return self
154
155def __next__(self):
156raise NotImplementedError
157
158
159class ITemperatureSensor:
160"""Вспомогательный или основной датчик температуры"""
161
162def enable_temp_meas(self, enable: bool = True):
163"""Включает измерение температуры при enable в Истина
164Для переопределения программистом!!!"""
165raise NotImplementedError
166
167def get_temperature(self) -> [int, float]:
168"""Возвращает температуру корпуса датчика в градусах Цельсия!
169Для переопределения программистом!!!"""
170raise NotImplementedError
171
172
173# 0 - устройство выполняет все свои функции (максимальное энергопотребление)
174# maximum (на ваш выбор) - устройство выполняет минимум своих функций (минимальное энергопотребление)
175#
176class IPower:
177"""интерфейс управления мощностью потребления устройства"""
178
179def set_power_level(self, level: [int, None] = 0) -> int:
180"""level >=0 or None
181Устанавливает режим мощности.
182level равен 0 - устройство выполняет все свои функции (максимальное энергопотребление)
183level равен maximum (на ваш выбор) - устройство выполняет минимум своих функций (минимальное энергопотребление)
184Возвращает текущий уровень потребления устройства.
185Если level в None, то метод должен возвратить текущий уровень потребления устройства!
186Если значение из регистра устройства не совпадет со шкалой 0-все включено...максимум-все выключено, то
187преобразуйте его!
188"""
189raise NotImplemented
190
191# def power_on(self, on: bool = True) -> int:
192# """Полностью включает (on в Истина), либо полностью ВЫключает (on в Ложь)
193# Возвращает текущий режим потребления устройства."""
194# raise NotImplemented
195
196
197class IBaseSensorEx:
198"""интерфейсы, обязательные для большинства датчиков"""
199
200def get_conversion_cycle_time(self) -> int:
201"""Возвращает время в мс или мкс преобразования сигнала в цифровой код и готовности его для чтения по шине!
202Для текущих настроек датчика. При изменении настроек следует заново вызвать этот метод!"""
203raise NotImplemented
204
205def start_measurement(self):
206"""Настраивает параметры датчика и запускает процесс измерения"""
207raise NotImplemented
208
209def get_measurement_value(self):
210"""Возвращает измеренное датчиком значение(значения)"""
211raise NotImplemented
212
213# def is_data_ready(self) -> bool:
214# """Возвращает Истина, если данные доступны для считывания"""
215# raise NotImplemented
216
217def is_single_shot_mode(self) -> bool:
218"""Возвращает Истина, когда датчик находится в режиме однократных измерений,
219каждое из которых запускается методом start_measurement"""
220raise NotImplemented
221
222def is_continuously_mode(self) -> bool:
223"""Возвращает Истина, когда датчик находится в режиме многократных измерений,
224производимых автоматически. Процесс запускается методом start_measurement"""
225raise NotImplemented
226