scietex.hal.adc 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scietex/hal/adc/__init__.py +6 -0
- scietex/hal/adc/base/__init__.py +5 -0
- scietex/hal/adc/base/adc.py +88 -0
- scietex/hal/adc/base/data.py +69 -0
- scietex/hal/adc/base/rs485/__init__.py +5 -0
- scietex/hal/adc/base/rs485/adc.py +152 -0
- scietex/hal/adc/py.typed +0 -0
- scietex/hal/adc/scietex/__init__.py +5 -0
- scietex/hal/adc/scietex/utils.py +21 -0
- scietex/hal/adc/scietex/vdp_adc.py +149 -0
- scietex/hal/adc/version.py +8 -0
- scietex_hal_adc-0.0.1.dist-info/METADATA +56 -0
- scietex_hal_adc-0.0.1.dist-info/RECORD +16 -0
- scietex_hal_adc-0.0.1.dist-info/WHEEL +5 -0
- scietex_hal_adc-0.0.1.dist-info/licenses/LICENSE +21 -0
- scietex_hal_adc-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""ADC abstract interface."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from .data import ADCError, ADCParameters, VoltageTuple
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ADC(ABC):
|
|
9
|
+
"""ADC interface class."""
|
|
10
|
+
|
|
11
|
+
channels_number: int = 1
|
|
12
|
+
|
|
13
|
+
error_codes: dict[int, ADCError] = {0: ADCError(code=0, message="No error")}
|
|
14
|
+
error_codes_com: dict[int, ADCError] = {0: ADCError(code=0, message="No error")}
|
|
15
|
+
|
|
16
|
+
# Error processing methods
|
|
17
|
+
@abstractmethod
|
|
18
|
+
async def get_error_code(self, comm: bool = False) -> int:
|
|
19
|
+
"""Read error code from the device"""
|
|
20
|
+
|
|
21
|
+
def parse_error_code(self, code: int, comm: bool = False) -> ADCError:
|
|
22
|
+
"""Parse error code from the device"""
|
|
23
|
+
if comm:
|
|
24
|
+
if code in self.error_codes_com:
|
|
25
|
+
return self.error_codes_com[code]
|
|
26
|
+
else:
|
|
27
|
+
if code in self.error_codes:
|
|
28
|
+
return self.error_codes[code]
|
|
29
|
+
return ADCError(code=code, message="Unknown error")
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
async def clear_error(self, comm: bool = False) -> int:
|
|
33
|
+
"""Clear error from the device."""
|
|
34
|
+
|
|
35
|
+
# Device information methods
|
|
36
|
+
@abstractmethod
|
|
37
|
+
async def get_vendor(self) -> str:
|
|
38
|
+
"""Get device vendor name."""
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
async def get_product_name(self) -> str:
|
|
42
|
+
"""Get device product name."""
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
async def get_serial_number(self) -> str:
|
|
46
|
+
"""Get device serial number."""
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
async def get_version(self) -> str:
|
|
50
|
+
"""get device firmware version."""
|
|
51
|
+
|
|
52
|
+
# ADC measurement setup
|
|
53
|
+
|
|
54
|
+
# @abstractmethod
|
|
55
|
+
# async def get_mcu_frequency(self) -> int:
|
|
56
|
+
# """GET MCU frequency."""
|
|
57
|
+
|
|
58
|
+
# @abstractmethod
|
|
59
|
+
# async def get_gate_time(self) -> float:
|
|
60
|
+
# """Get gate time in ms"""
|
|
61
|
+
|
|
62
|
+
# @abstractmethod
|
|
63
|
+
# async def set_gate_time(self, gate_time_ms: float) -> float:
|
|
64
|
+
# """Set gate time in ms"""
|
|
65
|
+
|
|
66
|
+
# @abstractmethod
|
|
67
|
+
# async def get_averaging(self) -> int:
|
|
68
|
+
# """Get averaging window"""
|
|
69
|
+
|
|
70
|
+
# @abstractmethod
|
|
71
|
+
# async def set_averaging(self, averaging_window: int) -> int:
|
|
72
|
+
# """Set averaging window."""
|
|
73
|
+
|
|
74
|
+
# Voltage measurement methods
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
async def get_voltage(self) -> VoltageTuple:
|
|
78
|
+
"""Get all channels voltages."""
|
|
79
|
+
|
|
80
|
+
@abstractmethod
|
|
81
|
+
async def get_channel_voltage(self, channel: int) -> float | None:
|
|
82
|
+
"""Get voltage value for a specific channel."""
|
|
83
|
+
|
|
84
|
+
# Read ADC parameters in single call
|
|
85
|
+
|
|
86
|
+
@abstractmethod
|
|
87
|
+
async def read_parameters(self) -> ADCParameters:
|
|
88
|
+
"""Read ADC Parameters"""
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Data models for the ADC."""
|
|
2
|
+
|
|
3
|
+
# from enum import Enum
|
|
4
|
+
|
|
5
|
+
import msgspec
|
|
6
|
+
|
|
7
|
+
# class OutCTRLMode(Enum):
|
|
8
|
+
# """Modes of the control output."""
|
|
9
|
+
|
|
10
|
+
# HIGH = 1
|
|
11
|
+
# LOW = 2
|
|
12
|
+
# MANUAL = 3
|
|
13
|
+
# DISABLED = 4
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# class PwmCTRLMode(Enum):
|
|
17
|
+
# """Modes of the PWM output."""
|
|
18
|
+
|
|
19
|
+
# ABSOLUTE = 1
|
|
20
|
+
# RELATIVE = 2
|
|
21
|
+
# MANUAL = 3
|
|
22
|
+
# DISABLED = 4
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ADCError(msgspec.Struct, frozen=True):
|
|
26
|
+
"""Model of an ADC error with code and message."""
|
|
27
|
+
|
|
28
|
+
code: int
|
|
29
|
+
message: str = "Unknown error"
|
|
30
|
+
|
|
31
|
+
def __str__(self) -> str:
|
|
32
|
+
return f"ADCError(code={self.code}, message='{self.message}')"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
VoltageTuple = tuple[float | None, ...]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ADCParameters(msgspec.Struct, frozen=True):
|
|
39
|
+
"""ADC parameters schema."""
|
|
40
|
+
|
|
41
|
+
connected: bool = False # ADC connection status
|
|
42
|
+
channels_number: int | None = None # Number of ADC channels
|
|
43
|
+
voltage: VoltageTuple | None = None # Channel voltages
|
|
44
|
+
|
|
45
|
+
def __str__(self) -> str:
|
|
46
|
+
"""Human-readable representation."""
|
|
47
|
+
if self.voltage is None:
|
|
48
|
+
voltage_str = "None"
|
|
49
|
+
elif not self.voltage:
|
|
50
|
+
voltage_str = "[]"
|
|
51
|
+
else:
|
|
52
|
+
voltage_strs = [f"{v:.2f} V" if v is not None else "N/A" for v in self.voltage]
|
|
53
|
+
voltage_str = f"[{', '.join(voltage_strs)}]"
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
f"ADCParameters("
|
|
57
|
+
f"channels_number={self.channels_number}, "
|
|
58
|
+
f"voltage={voltage_str}, "
|
|
59
|
+
f"connected={self.connected})"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def __repr__(self) -> str:
|
|
63
|
+
"""Official string representation (used in debugging)."""
|
|
64
|
+
return (
|
|
65
|
+
f"ADCParameters("
|
|
66
|
+
f"connected={self.connected!r}, "
|
|
67
|
+
f"channels_number={self.channels_number!r}, "
|
|
68
|
+
f"voltage={self.voltage!r})"
|
|
69
|
+
)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Lock-in amplifier with RS485 communication interface."""
|
|
2
|
+
|
|
3
|
+
from logging import Logger
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from pymodbus.framer import FramerBase
|
|
7
|
+
from pymodbus.pdu import DecodePDU, ModbusPDU
|
|
8
|
+
from scietex.hal.serial import (
|
|
9
|
+
ModbusSerialConnectionConfig,
|
|
10
|
+
RS485Client,
|
|
11
|
+
SerialConnectionConfig,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from ...version import __version__
|
|
15
|
+
from .. import ADC
|
|
16
|
+
from ..data import ADCParameters, VoltageTuple
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RS485ADC(ADC, RS485Client):
|
|
20
|
+
"""ADC with RS485 communication interface."""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
channels_number: int,
|
|
25
|
+
con_params: SerialConnectionConfig | ModbusSerialConnectionConfig,
|
|
26
|
+
address: int = 1,
|
|
27
|
+
label: str = "RS485 ADC",
|
|
28
|
+
custom_framer: type[FramerBase] | None = None,
|
|
29
|
+
custom_decoder: type[DecodePDU] | None = None,
|
|
30
|
+
custom_response: list[type[ModbusPDU]] | None = None,
|
|
31
|
+
chunk_size: int | None = None,
|
|
32
|
+
write_chunk_size: int | None = None,
|
|
33
|
+
logger: Logger | None = None,
|
|
34
|
+
**kwargs,
|
|
35
|
+
):
|
|
36
|
+
RS485Client.__init__(
|
|
37
|
+
self,
|
|
38
|
+
con_params=con_params,
|
|
39
|
+
address=address,
|
|
40
|
+
custom_framer=custom_framer,
|
|
41
|
+
custom_decoder=custom_decoder,
|
|
42
|
+
custom_response=custom_response,
|
|
43
|
+
chunk_size=chunk_size,
|
|
44
|
+
write_chunk_size=write_chunk_size,
|
|
45
|
+
logger=logger,
|
|
46
|
+
)
|
|
47
|
+
self.channels_number = channels_number
|
|
48
|
+
|
|
49
|
+
# Error processing methods
|
|
50
|
+
|
|
51
|
+
async def get_error_code(self, comm: bool = False) -> int:
|
|
52
|
+
"""Read error code from the ADC."""
|
|
53
|
+
code = 0
|
|
54
|
+
if comm:
|
|
55
|
+
self.logger.debug("%s: Communication error code %d.", self.label, code)
|
|
56
|
+
else:
|
|
57
|
+
self.logger.debug("%s: Error code %d.", self.label, code)
|
|
58
|
+
return code
|
|
59
|
+
|
|
60
|
+
async def clear_error(self, comm: bool = False) -> int:
|
|
61
|
+
"""Clear error from the ADC."""
|
|
62
|
+
if comm:
|
|
63
|
+
self.logger.debug("%s: Clear communication error.", self.label)
|
|
64
|
+
else:
|
|
65
|
+
self.logger.debug("%s: Clear error.", self.label)
|
|
66
|
+
return await self.get_error_code()
|
|
67
|
+
|
|
68
|
+
# Device information methods
|
|
69
|
+
|
|
70
|
+
async def get_vendor(self) -> str:
|
|
71
|
+
"""Get ADC vendor name."""
|
|
72
|
+
vendor: str = "n/d"
|
|
73
|
+
self.logger.debug("%s vendor: %s", self.label, vendor)
|
|
74
|
+
return vendor
|
|
75
|
+
|
|
76
|
+
async def get_product_name(self) -> str:
|
|
77
|
+
"""Get ADC product name."""
|
|
78
|
+
self.logger.debug("%s prod. name: %s", self.label, self.label)
|
|
79
|
+
return self.label
|
|
80
|
+
|
|
81
|
+
async def get_serial_number(self) -> str:
|
|
82
|
+
"""Get ADC serial number."""
|
|
83
|
+
sn = "n/d"
|
|
84
|
+
self.logger.debug("%s SN: %s", self.label, sn)
|
|
85
|
+
return sn
|
|
86
|
+
|
|
87
|
+
async def get_version(self) -> str:
|
|
88
|
+
"""Get ADC firmware version."""
|
|
89
|
+
self.logger.debug("%s version: %s.", self.label, __version__)
|
|
90
|
+
return __version__
|
|
91
|
+
|
|
92
|
+
# Voltage measurement methods
|
|
93
|
+
|
|
94
|
+
async def get_voltage(self) -> VoltageTuple:
|
|
95
|
+
"""Get all channels voltages."""
|
|
96
|
+
self.logger.debug("%s: get_voltage call", self.label)
|
|
97
|
+
voltage: VoltageTuple = (None,) * self.channels_number
|
|
98
|
+
return voltage
|
|
99
|
+
|
|
100
|
+
async def get_channel_voltage(self, channel: int) -> float | None:
|
|
101
|
+
"""Get X channel voltage value."""
|
|
102
|
+
self.logger.debug("%s: get_channel_voltage[%d] call", self.label, channel)
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
# RS485 address and baudrate
|
|
106
|
+
|
|
107
|
+
async def get_address(self) -> int:
|
|
108
|
+
"""Get RS-485 address."""
|
|
109
|
+
self.logger.debug("%s: get_address call", self.label)
|
|
110
|
+
return 1
|
|
111
|
+
|
|
112
|
+
async def set_address(self, address: int) -> int:
|
|
113
|
+
"""Set RS-485 address."""
|
|
114
|
+
self.logger.debug("%s: set_address(%d) call", self.label, address)
|
|
115
|
+
return await self.get_address()
|
|
116
|
+
|
|
117
|
+
async def get_baudrate(self) -> int:
|
|
118
|
+
"""Get RS-485 baudrate value."""
|
|
119
|
+
self.logger.debug("%s: get_baudrate call", self.label)
|
|
120
|
+
return 9600
|
|
121
|
+
|
|
122
|
+
async def set_baudrate(self, baudrate: int) -> int:
|
|
123
|
+
"""Set RS-485 baudrate."""
|
|
124
|
+
self.logger.debug("%s: set_baudrate(%d) call", self.label, baudrate)
|
|
125
|
+
return await self.get_baudrate()
|
|
126
|
+
|
|
127
|
+
async def check_connection(self) -> bool:
|
|
128
|
+
"""Set RS-485 baudrate."""
|
|
129
|
+
self.logger.debug("%s: check_connection call", self.label)
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
# Read Lock-in state in a single request
|
|
133
|
+
|
|
134
|
+
async def read_parameters(self) -> ADCParameters:
|
|
135
|
+
"""Read ADC Parameters."""
|
|
136
|
+
self.logger.debug("%s: read_parameters call", self.label)
|
|
137
|
+
voltage: VoltageTuple = await self.get_voltage()
|
|
138
|
+
connected: bool = await self.check_connection()
|
|
139
|
+
parameters = ADCParameters(
|
|
140
|
+
channels_number=self.channels_number,
|
|
141
|
+
voltage=voltage,
|
|
142
|
+
connected=connected,
|
|
143
|
+
)
|
|
144
|
+
return parameters
|
|
145
|
+
|
|
146
|
+
async def read_data(self) -> dict[str, int | float | list[int | float]]:
|
|
147
|
+
"""Read Lockin data in a single request."""
|
|
148
|
+
parameters = await self.read_parameters()
|
|
149
|
+
return {f: getattr(parameters, f) for f in parameters.__struct_fields__}
|
|
150
|
+
|
|
151
|
+
async def process_message(self, message: dict[str, Any]) -> None:
|
|
152
|
+
await super().process_message(message)
|
scietex/hal/adc/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Scietex-related utilities."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def baudrate_check(baudrate: int) -> int:
|
|
5
|
+
"""Adjust baudrate to the supported values."""
|
|
6
|
+
if baudrate <= 9600:
|
|
7
|
+
return 9600
|
|
8
|
+
if baudrate <= 14400:
|
|
9
|
+
return 14400
|
|
10
|
+
if baudrate <= 19200:
|
|
11
|
+
return 19200
|
|
12
|
+
if baudrate <= 38400:
|
|
13
|
+
return 38400
|
|
14
|
+
if baudrate <= 57600:
|
|
15
|
+
return 57600
|
|
16
|
+
return 115200
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def address_check(address: int) -> int:
|
|
20
|
+
"""Adjust address to the supported values."""
|
|
21
|
+
return max(1, min(address, 247))
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""Scietex VdpADC."""
|
|
2
|
+
|
|
3
|
+
from logging import Logger
|
|
4
|
+
|
|
5
|
+
from scietex.hal.serial import ModbusSerialConnectionConfig
|
|
6
|
+
from scietex.hal.serial.utilities.numeric import ByteOrder, combine_32bit, float_from_int
|
|
7
|
+
|
|
8
|
+
from ..base.data import ADCParameters, VoltageTuple
|
|
9
|
+
from ..base.rs485 import RS485ADC
|
|
10
|
+
|
|
11
|
+
VOLTAGE_SCALE = 100
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class VdpADC(RS485ADC):
|
|
15
|
+
"""Scietex Van der Pauw ADC RS485 driver."""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
con_params: ModbusSerialConnectionConfig,
|
|
20
|
+
address: int = 1,
|
|
21
|
+
label: str = "Scietex Van der Pauw ADC",
|
|
22
|
+
logger: Logger | None = None,
|
|
23
|
+
chunk_size: int | None = 8,
|
|
24
|
+
write_chunk_size: int | None = 8,
|
|
25
|
+
**kwargs,
|
|
26
|
+
):
|
|
27
|
+
|
|
28
|
+
con_params.framer = "RTU"
|
|
29
|
+
super().__init__(
|
|
30
|
+
channels_number=4,
|
|
31
|
+
con_params=con_params,
|
|
32
|
+
address=address,
|
|
33
|
+
label=label,
|
|
34
|
+
logger=logger,
|
|
35
|
+
chunk_size=chunk_size,
|
|
36
|
+
write_chunk_size=write_chunk_size,
|
|
37
|
+
**kwargs,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
async def get_vendor(self) -> str:
|
|
41
|
+
response = await self.read_registers(0, 10, holding=False)
|
|
42
|
+
if response is not None:
|
|
43
|
+
return bytes(response).decode()
|
|
44
|
+
return ""
|
|
45
|
+
|
|
46
|
+
async def get_product_name(self) -> str:
|
|
47
|
+
response = await self.read_registers(10, 10, holding=False)
|
|
48
|
+
if response is not None:
|
|
49
|
+
return bytes(response).decode()
|
|
50
|
+
return ""
|
|
51
|
+
|
|
52
|
+
async def get_version(self) -> str:
|
|
53
|
+
response = await self.read_registers(20, 3, holding=False)
|
|
54
|
+
if response is not None:
|
|
55
|
+
return f"{response[0]:d}.{response[1]:d}.{response[2]:d}"
|
|
56
|
+
return ""
|
|
57
|
+
|
|
58
|
+
async def get_serial_number(self) -> str:
|
|
59
|
+
response = await self.read_two_registers_int(
|
|
60
|
+
10, holding=True, byteorder=ByteOrder.BIG_ENDIAN
|
|
61
|
+
)
|
|
62
|
+
if response is not None:
|
|
63
|
+
return f"{response:d}"
|
|
64
|
+
return ""
|
|
65
|
+
|
|
66
|
+
async def get_channel_voltage(self, channel: int) -> float | None:
|
|
67
|
+
ch_idx = max(0, min(channel, self.channels_number - 1))
|
|
68
|
+
start_register = 36 + ch_idx * 2
|
|
69
|
+
response = await self.read_two_registers_float(
|
|
70
|
+
start_register, holding=False, factor=VOLTAGE_SCALE, byteorder=ByteOrder.BIG_ENDIAN
|
|
71
|
+
)
|
|
72
|
+
if response is not None:
|
|
73
|
+
return float(response)
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
async def get_voltage(self) -> VoltageTuple:
|
|
77
|
+
response = await self.read_registers(36, self.channels_number * 2, holding=False)
|
|
78
|
+
if response is not None and len(response) == self.channels_number * 2:
|
|
79
|
+
voltage = tuple(
|
|
80
|
+
float_from_int(combine_32bit(a, b, byteorder=ByteOrder.BIG_ENDIAN), VOLTAGE_SCALE)
|
|
81
|
+
if a is not None and b is not None
|
|
82
|
+
else None
|
|
83
|
+
for a, b in zip(response[::2], response[1::2])
|
|
84
|
+
)
|
|
85
|
+
return voltage
|
|
86
|
+
return (None,) * self.channels_number
|
|
87
|
+
|
|
88
|
+
async def get_address(self) -> int:
|
|
89
|
+
response = await self.read_register(0, holding=True)
|
|
90
|
+
if response is not None:
|
|
91
|
+
return response
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
async def set_address(self, address: int) -> int:
|
|
95
|
+
new_address = max(1, min(address, 247))
|
|
96
|
+
await self.write_register(0, new_address)
|
|
97
|
+
self.address = new_address
|
|
98
|
+
response = await self.get_address()
|
|
99
|
+
if response is not None and response > 0:
|
|
100
|
+
self.address = response
|
|
101
|
+
return response
|
|
102
|
+
return 0
|
|
103
|
+
|
|
104
|
+
async def get_baudrate(self) -> int:
|
|
105
|
+
response = await self.read_register(1, holding=True)
|
|
106
|
+
if response is not None:
|
|
107
|
+
if response == 0:
|
|
108
|
+
return 9600
|
|
109
|
+
elif response == 1:
|
|
110
|
+
return 19200
|
|
111
|
+
elif response == 2:
|
|
112
|
+
return 115200
|
|
113
|
+
return 0
|
|
114
|
+
|
|
115
|
+
async def set_baudrate(self, baudrate: int) -> int:
|
|
116
|
+
if baudrate <= 9600:
|
|
117
|
+
new_baudrate = 9600
|
|
118
|
+
baudrate_code = 0
|
|
119
|
+
elif baudrate <= 19200:
|
|
120
|
+
new_baudrate = 19200
|
|
121
|
+
baudrate_code = 1
|
|
122
|
+
else:
|
|
123
|
+
new_baudrate = 115200
|
|
124
|
+
baudrate_code = 5
|
|
125
|
+
response = await self.write_register(1, baudrate_code)
|
|
126
|
+
new_con_params = self.con_params
|
|
127
|
+
new_con_params.baudrate = new_baudrate
|
|
128
|
+
self.con_params = new_con_params
|
|
129
|
+
if response is not None:
|
|
130
|
+
return response
|
|
131
|
+
response = await self.read_register(1, holding=True)
|
|
132
|
+
if response is not None:
|
|
133
|
+
return response
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
async def check_connection(self):
|
|
137
|
+
vendor = await self.get_vendor()
|
|
138
|
+
if vendor:
|
|
139
|
+
return True
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
async def read_parameters(self) -> ADCParameters:
|
|
143
|
+
voltage = await self.get_voltage()
|
|
144
|
+
parameters = ADCParameters(
|
|
145
|
+
connected=True,
|
|
146
|
+
channels_number=self.channels_number,
|
|
147
|
+
voltage=voltage,
|
|
148
|
+
)
|
|
149
|
+
return parameters
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: scietex.hal.adc
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Scietex ADC HAL package
|
|
5
|
+
Author-email: Anton Bondarenko <bond.anton@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Anton Bondarenko
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Project-URL: Homepage, https://github.com/bond-anton/scietex.hal.adc
|
|
28
|
+
Project-URL: Bug Tracker, https://github.com/bond-anton/scietex.hal.adc/issues
|
|
29
|
+
Classifier: Programming Language :: Python :: 3
|
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
31
|
+
Classifier: Operating System :: OS Independent
|
|
32
|
+
Requires-Python: >=3.10
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: msgspec[yaml]>=0.20.0
|
|
36
|
+
Requires-Dist: scietex.hal.serial<2.0.0,>=1.3.0
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: tox>=4.45.0; extra == "dev"
|
|
39
|
+
Provides-Extra: test
|
|
40
|
+
Requires-Dist: pytest; extra == "test"
|
|
41
|
+
Requires-Dist: pytest-asyncio; extra == "test"
|
|
42
|
+
Provides-Extra: lint
|
|
43
|
+
Requires-Dist: ruff; extra == "lint"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# scietex.hal.adc
|
|
47
|
+
|
|
48
|
+
The `scietex.hal.adc` package is a Python library for interfacing with ADC.
|
|
49
|
+
It provides an abstract class `ADC`, and a base class for ADCs with RS485 communication
|
|
50
|
+
interface, which in its turn inherits `scietex.hal.serial.RS485Client`.
|
|
51
|
+
The concrete implementation for the ADC manufactured by Scietex is provided.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
This project is licensed under the **MIT License** - see the LICENSE file for details.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
scietex/hal/adc/__init__.py,sha256=9GMNW7ZUEc6JsUc4j0ByDQs5QsPKxbCaCZznj3h_cr8,111
|
|
2
|
+
scietex/hal/adc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
scietex/hal/adc/version.py,sha256=piE4bIBU9mWny5k8pD8kbdn__ngmBDQS7k2Ja56GK8I,154
|
|
4
|
+
scietex/hal/adc/base/__init__.py,sha256=eys9eDRuyCojmDxfs2q2-9Ml4MAqhrRynewEypnEMbQ,117
|
|
5
|
+
scietex/hal/adc/base/adc.py,sha256=_xqSRkSp3Cyta81CvGFmb4WySgEvVDKrhcH6LHRSFIQ,2541
|
|
6
|
+
scietex/hal/adc/base/data.py,sha256=EQIb0dqcOTWNvC3Snq5j2z0tz-PXLFGDhBhzL5D2D_0,1771
|
|
7
|
+
scietex/hal/adc/base/rs485/__init__.py,sha256=IwKX84855Q9p1-s9WiT6TOeK7qRrhcahZSmxQmuVis4,72
|
|
8
|
+
scietex/hal/adc/base/rs485/adc.py,sha256=1qSCbqSJTF5CcpKtuF3_CuUD3VX7Nxu1QiIwJ4qHOOI,5161
|
|
9
|
+
scietex/hal/adc/scietex/__init__.py,sha256=-70CpKu-Wmx79fKESPtw33CvQZCjkCaILr7wH2Xi8ZA,74
|
|
10
|
+
scietex/hal/adc/scietex/utils.py,sha256=vc-oHUIV8Ut2MBanf536mDwvPwGjxbGCWIsLkNTHw8Q,508
|
|
11
|
+
scietex/hal/adc/scietex/vdp_adc.py,sha256=UXZ8RTT2Z1dWNIT1WqegmRECiSAPUFybRgE2_w4Yh4A,4915
|
|
12
|
+
scietex_hal_adc-0.0.1.dist-info/licenses/LICENSE,sha256=Kv8K8tNh4XWlpCNncypg7EhUWm4drfJp0zCGNsrp6So,1072
|
|
13
|
+
scietex_hal_adc-0.0.1.dist-info/METADATA,sha256=9ZiMVZFuxSj8Rt5wALqgflZ-Wubb6dqYHGPL9qvddqc,2537
|
|
14
|
+
scietex_hal_adc-0.0.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
15
|
+
scietex_hal_adc-0.0.1.dist-info/top_level.txt,sha256=AyNTe2f94XrlwxyUGMuitoEj6mqEacwNkt8nU47GjvI,8
|
|
16
|
+
scietex_hal_adc-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Anton Bondarenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
scietex
|