BDPotentiometer 0.0.1__tar.gz → 0.0.3__tar.gz

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.
Files changed (39) hide show
  1. BDPotentiometer-0.0.3/LICENSE +21 -0
  2. BDPotentiometer-0.0.3/PKG-INFO +79 -0
  3. BDPotentiometer-0.0.3/README.md +33 -0
  4. BDPotentiometer-0.0.3/pyproject.toml +42 -0
  5. BDPotentiometer-0.0.3/setup.cfg +4 -0
  6. BDPotentiometer-0.0.3/src/BDPotentiometer/__gpiozero_helpers.py +83 -0
  7. BDPotentiometer-0.0.3/src/BDPotentiometer/__helpers.py +160 -0
  8. BDPotentiometer-0.0.3/src/BDPotentiometer/__init__.py +16 -0
  9. BDPotentiometer-0.0.3/src/BDPotentiometer/digital_potentiometer.py +522 -0
  10. BDPotentiometer-0.0.3/src/BDPotentiometer/digital_wiper.py +291 -0
  11. BDPotentiometer-0.0.3/src/BDPotentiometer/mcp4xxx/__init__.py +24 -0
  12. BDPotentiometer-0.0.3/src/BDPotentiometer/mcp4xxx/mcp4xx1.py +74 -0
  13. BDPotentiometer-0.0.3/src/BDPotentiometer/mcp4xxx/mcp4xx2.py +74 -0
  14. BDPotentiometer-0.0.3/src/BDPotentiometer/mcp4xxx/mcp4xxx.py +214 -0
  15. BDPotentiometer-0.0.3/src/BDPotentiometer/potentiometer.py +260 -0
  16. BDPotentiometer-0.0.3/src/BDPotentiometer.egg-info/PKG-INFO +79 -0
  17. BDPotentiometer-0.0.3/src/BDPotentiometer.egg-info/SOURCES.txt +19 -0
  18. BDPotentiometer-0.0.3/src/BDPotentiometer.egg-info/requires.txt +13 -0
  19. BDPotentiometer-0.0.3/tests/test_version.py +51 -0
  20. BDPotentiometer-0.0.1/BDPotentiometer/DigitalPotentiometer.py +0 -283
  21. BDPotentiometer-0.0.1/BDPotentiometer/MCP4xx1.py +0 -126
  22. BDPotentiometer-0.0.1/BDPotentiometer/MCP4xx2.py +0 -44
  23. BDPotentiometer-0.0.1/BDPotentiometer/MCP4xxx.py +0 -123
  24. BDPotentiometer-0.0.1/BDPotentiometer/__gpiozero_helpers.py +0 -33
  25. BDPotentiometer-0.0.1/BDPotentiometer/__helpers.py +0 -80
  26. BDPotentiometer-0.0.1/BDPotentiometer/__init__.py +0 -6
  27. BDPotentiometer-0.0.1/BDPotentiometer/_version.py +0 -1
  28. BDPotentiometer-0.0.1/BDPotentiometer.egg-info/PKG-INFO +0 -47
  29. BDPotentiometer-0.0.1/BDPotentiometer.egg-info/SOURCES.txt +0 -19
  30. BDPotentiometer-0.0.1/LICENSE.txt +0 -202
  31. BDPotentiometer-0.0.1/MANIFEST.in +0 -15
  32. BDPotentiometer-0.0.1/NOTICE.txt +0 -2
  33. BDPotentiometer-0.0.1/PKG-INFO +0 -47
  34. BDPotentiometer-0.0.1/README.md +0 -25
  35. BDPotentiometer-0.0.1/pyproject.toml +0 -3
  36. BDPotentiometer-0.0.1/setup.cfg +0 -7
  37. BDPotentiometer-0.0.1/setup.py +0 -56
  38. {BDPotentiometer-0.0.1 → BDPotentiometer-0.0.3/src}/BDPotentiometer.egg-info/dependency_links.txt +0 -0
  39. {BDPotentiometer-0.0.1 → BDPotentiometer-0.0.3/src}/BDPotentiometer.egg-info/top_level.txt +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 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,79 @@
1
+ Metadata-Version: 2.1
2
+ Name: BDPotentiometer
3
+ Version: 0.0.3
4
+ Summary: BD Digital Potentiometer
5
+ Author-email: Anton Bondarenko <bond.anton@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2023 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/BDPotentiometer
28
+ Project-URL: Bug Tracker, https://github.com/bond-anton/BDPotentiometer/issues
29
+ Project-URL: Documentation, https://bdpotentiometer.readthedocs.io
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Operating System :: OS Independent
33
+ Requires-Python: >=3.9
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ Requires-Dist: gpiozero>=1.6.2
37
+ Provides-Extra: dev
38
+ Requires-Dist: gpiozero>=1.6.2; extra == "dev"
39
+ Requires-Dist: numpy; extra == "dev"
40
+ Provides-Extra: test
41
+ Requires-Dist: flake8; extra == "test"
42
+ Requires-Dist: pytest; extra == "test"
43
+ Requires-Dist: numpy; extra == "test"
44
+ Provides-Extra: lint
45
+ Requires-Dist: pylint; extra == "lint"
46
+
47
+ # BDPotentiometer
48
+
49
+ ![Build](https://github.com/bond-anton/BDPotentiometer/actions/workflows/python-package.yml/badge.svg)
50
+ [![Documentation Status](https://readthedocs.org/projects/bdpotentiometer/badge/?version=latest)](https://bdpotentiometer.readthedocs.io/en/latest/?badge=latest)
51
+
52
+ Module to operate Digital Potentiometer over SPI bus. Extends gpiozero SPIDev class.
53
+
54
+ ## Installation
55
+
56
+ To install BDPotentiometer use pip
57
+ ```shell
58
+ $ pip install BDPotentiometer
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ Just import the correct potentiometer class, for example MCP4231, and start operating your pot.
64
+
65
+ ```python
66
+ from BDPotentiometer.mcp4xxx import MCP4231
67
+
68
+
69
+ my_pot = MCP4231(r_ab=10e3, device=0)
70
+ my_pot.channels[0].value = 43
71
+ ```
72
+
73
+ Please see the [examples](examples) directory for more usage examples.
74
+
75
+ Detailed documentation is available at https://bdpotentiometer.readthedocs.io
76
+
77
+ ## License
78
+
79
+ BDPotentiometer is free open source software licensed under MIT License
@@ -0,0 +1,33 @@
1
+ # BDPotentiometer
2
+
3
+ ![Build](https://github.com/bond-anton/BDPotentiometer/actions/workflows/python-package.yml/badge.svg)
4
+ [![Documentation Status](https://readthedocs.org/projects/bdpotentiometer/badge/?version=latest)](https://bdpotentiometer.readthedocs.io/en/latest/?badge=latest)
5
+
6
+ Module to operate Digital Potentiometer over SPI bus. Extends gpiozero SPIDev class.
7
+
8
+ ## Installation
9
+
10
+ To install BDPotentiometer use pip
11
+ ```shell
12
+ $ pip install BDPotentiometer
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Just import the correct potentiometer class, for example MCP4231, and start operating your pot.
18
+
19
+ ```python
20
+ from BDPotentiometer.mcp4xxx import MCP4231
21
+
22
+
23
+ my_pot = MCP4231(r_ab=10e3, device=0)
24
+ my_pot.channels[0].value = 43
25
+ ```
26
+
27
+ Please see the [examples](examples) directory for more usage examples.
28
+
29
+ Detailed documentation is available at https://bdpotentiometer.readthedocs.io
30
+
31
+ ## License
32
+
33
+ BDPotentiometer is free open source software licensed under MIT License
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "BDPotentiometer"
7
+ dynamic = ["version"]
8
+ description = "BD Digital Potentiometer"
9
+ authors = [
10
+ { name = "Anton Bondarenko", email = "bond.anton@gmail.com" },
11
+ ]
12
+ license = { file = "LICENSE" }
13
+ readme = "README.md"
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+ requires-python = ">=3.9"
20
+ dependencies = [
21
+ "gpiozero>=1.6.2",
22
+ ]
23
+
24
+ [project.urls]
25
+ "Homepage" = "https://github.com/bond-anton/BDPotentiometer"
26
+ "Bug Tracker" = "https://github.com/bond-anton/BDPotentiometer/issues"
27
+ "Documentation" = "https://bdpotentiometer.readthedocs.io"
28
+
29
+ [project.optional-dependencies]
30
+ dev = ["gpiozero>=1.6.2", "numpy"]
31
+ test = ["flake8", "pytest", "numpy"]
32
+ lint = ["pylint"]
33
+
34
+ [tool.setuptools.dynamic]
35
+ version = {attr = "BDPotentiometer.__version__"}
36
+
37
+ [tool.mypy]
38
+ python_version = "3.9"
39
+
40
+ [[tool.mypy.overrides]]
41
+ module = ["gpiozero.*"]
42
+ ignore_missing_imports = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,83 @@
1
+ """Some helpers for gpiozero."""
2
+
3
+ try:
4
+ from gpiozero import Device
5
+ from gpiozero.pins.local import LocalPiHardwareSPI, LocalPiHardwareSPIShared
6
+ from gpiozero.pins.rpigpio import RPiGPIOFactory
7
+ except ModuleNotFoundError:
8
+ pass
9
+
10
+
11
+ def fix_gpiozero_dual_cs_spi() -> None:
12
+ """
13
+ A workaround written by slghb GitHub user to use two spi devices with hardware spi.
14
+ Taken from https://github.com/gpiozero/gpiozero/issues/1015
15
+
16
+ :return: None.
17
+ """
18
+
19
+ class LocalPiHardwareSPIFixed(LocalPiHardwareSPI):
20
+ """Custom conflict checker"""
21
+
22
+ # pylint: disable=too-few-public-methods
23
+ def _conflicts_with(self, other):
24
+ # pylint: disable=protected-access
25
+ return not (
26
+ isinstance(other, LocalPiHardwareSPI)
27
+ and (self._port, self._device) != (other._port, other._device)
28
+ )
29
+
30
+ @property
31
+ def value(self):
32
+ """
33
+ Returns a value representing the device's state. Frequently, this is a
34
+ boolean value, or a number between 0 and 1 but some devices use larger
35
+ ranges (e.g. -1 to +1) and composite devices usually use tuples to
36
+ return the states of all their subordinate components.
37
+ """
38
+ raise NotImplementedError
39
+
40
+ class LocalPiHardwareSPISharedFixed(LocalPiHardwareSPIShared):
41
+ """Custom Shared SPI hardware class inheriting from fixed Hardware SPI class above"""
42
+
43
+ def _conflicts_with(self, other):
44
+ # pylint: disable=protected-access
45
+ return not (
46
+ isinstance(other, LocalPiHardwareSPI)
47
+ and (self._port, self._device) != (other._port, other._device)
48
+ )
49
+
50
+ @property
51
+ def value(self):
52
+ """
53
+ Returns a value representing the device's state. Frequently, this is a
54
+ boolean value, or a number between 0 and 1 but some devices use larger
55
+ ranges (e.g. -1 to +1) and composite devices usually use tuples to
56
+ return the states of all their subordinate components.
57
+ """
58
+ raise NotImplementedError
59
+
60
+ class FixedRPiGPIOFactory(RPiGPIOFactory):
61
+ """Fixed RPiGPIOFactory"""
62
+
63
+ def _get_spi_class(self, shared, hardware):
64
+ """
65
+ Return a Fixed SPI class if shared hardware SPI port between two devices
66
+
67
+ :param shared: Flag for shared usage of SPI port.
68
+ :param hardware: Flag for hardware SPI usage.
69
+ :return:
70
+ """
71
+ if hardware:
72
+ if shared:
73
+ return LocalPiHardwareSPISharedFixed
74
+ return LocalPiHardwareSPIFixed
75
+ return super()._get_spi_class(shared, hardware)
76
+
77
+ Device.pin_factory = FixedRPiGPIOFactory()
78
+
79
+
80
+ def fix_gpiozero_dual_cs_spi_dummy() -> None:
81
+ """
82
+ A stub function if there will be problems importing above function
83
+ """
@@ -0,0 +1,160 @@
1
+ """This module contains internal helper functions and not supposed to be used outside."""
2
+
3
+ from numbers import Real, Integral
4
+ from math import isnan
5
+ from typing import Union, Callable
6
+
7
+
8
+ def check_number(num: Union[float, int, Real]) -> Union[float, int]:
9
+ """
10
+ Checks if argument is a real number.
11
+ check_number does not allow argument to be `+inf` or `-inf`, or `NaN`.
12
+ Special float numbers `+0.0` and `-0.0` will be converted to just 0.0
13
+
14
+ :param num: variable to check.
15
+ :return: Unchanged `num` as float or int or raises ValueError if num is not a real number.
16
+ """
17
+ if not isinstance(num, Real):
18
+ raise TypeError(f"Expected integer or float number, got {type(num)}")
19
+ if isinstance(num, Integral):
20
+ return int(num)
21
+ if num in [float("inf"), float("-inf")]:
22
+ raise ValueError(f"Expected integer or float number, got {num}")
23
+ if isnan(num):
24
+ raise ValueError("Expected integer or float number, not NaN")
25
+ if num == 0:
26
+ return 0.0
27
+ return float(num)
28
+
29
+
30
+ def check_integer(num: Union[float, int, Real]) -> int:
31
+ """
32
+ Checks if `num` is an integer and converts it to int, otherwise raises ValueError.
33
+
34
+ :param num: Number (either int or float) to be checked.
35
+ :return: int representation of `num` or rises ValueError.
36
+ """
37
+ num = check_number(num)
38
+ if isinstance(num, float):
39
+ if not num.is_integer():
40
+ raise ValueError("Argument should be integer number")
41
+ return int(num)
42
+
43
+
44
+ def check_not_negative(num: Union[float, int]) -> Union[float, int]:
45
+ """
46
+ Checks if `num` is a not negative number, otherwise rises ValueError.
47
+
48
+ :param num: Either float or int number.
49
+ :return: `num` if it is not negative or rises ValueError.
50
+ """
51
+ num = check_number(num)
52
+ if num < 0:
53
+ raise ValueError("Argument should be not negative number")
54
+ return num
55
+
56
+
57
+ def check_positive(num: Union[float, int]) -> Union[float, int]:
58
+ """
59
+ Checks if `num` is a positive number, otherwise rises ValueError.
60
+
61
+ :param num: Either float or int number.
62
+ :return: `num` if it is positive or rises ValueError.
63
+ """
64
+ num = check_number(num)
65
+ if num <= 0:
66
+ raise ValueError("Argument should be a positive number")
67
+ return num
68
+
69
+
70
+ def clamp(
71
+ value: Union[float, int], min_value: Union[float, int], max_value: Union[float, int]
72
+ ) -> Union[float, int]:
73
+ """
74
+ Clamp `value` to given range between `min_value` and `max_value`.
75
+
76
+ :param value: Either float or int number to be coerced.
77
+ :param min_value: Lower coerce range boundary.
78
+ :param max_value: Upper coerce range boundary.
79
+ :return: Value coerced to given range.
80
+ """
81
+ value = check_number(value)
82
+ min_value = check_number(min_value)
83
+ max_value = check_number(max_value)
84
+ if min_value > max_value:
85
+ min_value, max_value = max_value, min_value
86
+ if value < min_value:
87
+ if isinstance(value, float):
88
+ return float(min_value)
89
+ return min_value
90
+ if value > max_value:
91
+ if isinstance(value, float):
92
+ return float(max_value)
93
+ return max_value
94
+ return value
95
+
96
+
97
+ def build_tuple(
98
+ value: Union[float, int, tuple[float, ...], list[float, ...]],
99
+ num: Union[int, float],
100
+ func: Union[Callable, None] = None,
101
+ ) -> tuple[float, ...]:
102
+ """
103
+ Builds tuple of floats of given length by applying a callable `func` to value.
104
+ If `value` is an iterable (either list or tuple) its length must be equal to `num`.
105
+ The `func` will be applied to each element of the iterable.
106
+ If `value` is a number the resulting tuple of length `num` will be built of same `func(value)`
107
+ elements converted to float.
108
+ If `func` is None the `value` will enter resulting tuple unchanged.
109
+
110
+ :param value: Iterable (either list or tuple) or a number.
111
+ :param num: A number of elements in a tuple.
112
+ :param func: Callable to be applied to `value` or None for identity function.
113
+ :return: A tuple of floats of length `num` produced by application of `func` to `value`.
114
+ """
115
+
116
+ def identity(val: float) -> float:
117
+ return val
118
+
119
+ if not isinstance(value, (float, int, tuple, list)):
120
+ raise TypeError("Argument should be a number or list or tuple of numbers")
121
+ num = check_integer(check_positive(num))
122
+ if func is not None:
123
+ if not callable(func):
124
+ raise TypeError("function must be callable or None")
125
+ else:
126
+ func = identity
127
+
128
+ if isinstance(value, (list, tuple)):
129
+ if len(value) != num:
130
+ raise ValueError(f"A tuple or list of length {num} expected")
131
+ return tuple(float(func(check_number(value_i))) for value_i in value)
132
+ value = check_number(value)
133
+ return tuple(float(func(value)) for _ in range(num))
134
+
135
+
136
+ def adjust_tuple(
137
+ value: Union[tuple[float, ...], list[float, ...]], num: int, default_value: float
138
+ ) -> tuple[float, ...]:
139
+ """
140
+ Adjusts tuple or list of floats to a given length `num` and returns a tuple.
141
+ if `num` is less than initial length of the tuple it will be truncated to first `num` elements,
142
+ otherwise it will be appended using `default_value` parameter.
143
+
144
+ :param value: Initial iterable (either tuple or list) of float values.
145
+ :param num: Final length of the tuple.
146
+ :param default_value: Default value to populate the tuple if it needs to be grown.
147
+ :return: A tuple of floats of length `num`.
148
+ """
149
+ if not isinstance(value, (tuple, list)):
150
+ raise TypeError("Argument should be a list or a tuple of numbers")
151
+ num = check_integer(check_positive(num))
152
+ default_value = float(check_number(default_value))
153
+ if len(value) < num:
154
+ return tuple(
155
+ [float(check_number(value_i)) for value_i in value]
156
+ + [default_value] * (num - len(value))
157
+ )
158
+ if len(value) > num:
159
+ return tuple(float(check_number(value[i])) for i in range(num))
160
+ return tuple(float(check_number(value_i)) for value_i in value)
@@ -0,0 +1,16 @@
1
+ """ Module to operate SPI digital potentiometer devices """
2
+
3
+ # pylint: disable=invalid-name
4
+
5
+ __version__ = "0.0.3"
6
+
7
+ from .potentiometer import Potentiometer
8
+ from .digital_wiper import DigitalWiper, SpiDigitalWiper
9
+ from .digital_potentiometer import DigitalPotentiometerDevice
10
+
11
+ try:
12
+ from .__gpiozero_helpers import fix_gpiozero_dual_cs_spi
13
+ except ModuleNotFoundError:
14
+ from .__gpiozero_helpers import (
15
+ fix_gpiozero_dual_cs_spi_dummy as fix_gpiozero_dual_cs_spi,
16
+ )