adafruit-circuitpython-qmc5883p 1.0.0__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.
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.4
2
+ Name: adafruit-circuitpython-qmc5883p
3
+ Version: 1.0.0
4
+ Summary: CircuitPython driver for the Adafruit QMC5883P - Triple Axis Magnetometer - STEMMA QT
5
+ Author-email: Adafruit Industries <circuitpython@adafruit.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/adafruit/Adafruit_CircuitPython_QMC5883P
8
+ Keywords: adafruit,blinka,circuitpython,micropython,qmc5883p,magnetometer,,sensor
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries
11
+ Classifier: Topic :: Software Development :: Embedded Systems
12
+ Classifier: Topic :: System :: Hardware
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Description-Content-Type: text/x-rst
16
+ License-File: LICENSE
17
+ Requires-Dist: Adafruit-Blinka
18
+ Requires-Dist: adafruit-circuitpython-busdevice
19
+ Requires-Dist: adafruit-circuitpython-register
20
+ Provides-Extra: optional
21
+ Dynamic: license-file
22
+
23
+ Introduction
24
+ ============
25
+
26
+
27
+ .. image:: https://readthedocs.org/projects/adafruit-circuitpython-qmc5883p/badge/?version=latest
28
+ :target: https://docs.circuitpython.org/projects/qmc5883p/en/latest/
29
+ :alt: Documentation Status
30
+
31
+
32
+ .. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg
33
+ :target: https://adafru.it/discord
34
+ :alt: Discord
35
+
36
+
37
+ .. image:: https://github.com/adafruit/Adafruit_CircuitPython_QMC5883P/workflows/Build%20CI/badge.svg
38
+ :target: https://github.com/adafruit/Adafruit_CircuitPython_QMC5883P/actions
39
+ :alt: Build Status
40
+
41
+
42
+ .. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
43
+ :target: https://github.com/astral-sh/ruff
44
+ :alt: Code Style: Ruff
45
+
46
+ CircuitPython driver for the Adafruit QMC5883P - Triple Axis Magnetometer - STEMMA QT
47
+
48
+
49
+ Dependencies
50
+ =============
51
+ This driver depends on:
52
+
53
+ * `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
54
+ * `Bus Device <https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_
55
+ * `Register <https://github.com/adafruit/Adafruit_CircuitPython_Register>`_
56
+
57
+ Please ensure all dependencies are available on the CircuitPython filesystem.
58
+ This is easily achieved by downloading
59
+ `the Adafruit library and driver bundle <https://circuitpython.org/libraries>`_
60
+ or individual libraries can be installed using
61
+ `circup <https://github.com/adafruit/circup>`_.
62
+
63
+ `Purchase one from the Adafruit shop <http://www.adafruit.com/products/6388>`_
64
+
65
+ Installing from PyPI
66
+ =====================
67
+
68
+ On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
69
+ PyPI <https://pypi.org/project/adafruit-circuitpython-qmc5883p/>`_.
70
+ To install for current user:
71
+
72
+ .. code-block:: shell
73
+
74
+ pip3 install adafruit-circuitpython-qmc5883p
75
+
76
+ To install system-wide (this may be required in some cases):
77
+
78
+ .. code-block:: shell
79
+
80
+ sudo pip3 install adafruit-circuitpython-qmc5883p
81
+
82
+ To install in a virtual environment in your current project:
83
+
84
+ .. code-block:: shell
85
+
86
+ mkdir project-name && cd project-name
87
+ python3 -m venv .venv
88
+ source .env/bin/activate
89
+ pip3 install adafruit-circuitpython-qmc5883p
90
+
91
+ Installing to a Connected CircuitPython Device with Circup
92
+ ==========================================================
93
+
94
+ Make sure that you have ``circup`` installed in your Python environment.
95
+ Install it with the following command if necessary:
96
+
97
+ .. code-block:: shell
98
+
99
+ pip3 install circup
100
+
101
+ With ``circup`` installed and your CircuitPython device connected use the
102
+ following command to install:
103
+
104
+ .. code-block:: shell
105
+
106
+ circup install adafruit_qmc5883p
107
+
108
+ Or the following command to update an existing version:
109
+
110
+ .. code-block:: shell
111
+
112
+ circup update
113
+
114
+ Usage Example
115
+ =============
116
+
117
+ .. code-block:: python
118
+
119
+ import time
120
+ import board
121
+ import adafruit_qmc5883p
122
+
123
+ i2c = board.I2C()
124
+
125
+ sensor = adafruit_qmc5883p.QMC5883P(i2c)
126
+
127
+ while True:
128
+ mag_x, mag_y, mag_z = sensor.magnetic
129
+
130
+ print(f"X:{mag_x:2.3f}, Y:{mag_y:2.3f}, Z:{mag_z:2.3f} G")
131
+ print("")
132
+
133
+ time.sleep(1)
134
+
135
+ Documentation
136
+ =============
137
+ API documentation for this library can be found on `Read the Docs <https://docs.circuitpython.org/projects/qmc5883p/en/latest/>`_.
138
+
139
+ For information on building library documentation, please check out
140
+ `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
141
+
142
+ Contributing
143
+ ============
144
+
145
+ Contributions are welcome! Please read our `Code of Conduct
146
+ <https://github.com/adafruit/Adafruit_CircuitPython_QMC5883P/blob/HEAD/CODE_OF_CONDUCT.md>`_
147
+ before contributing to help this project stay welcoming.
@@ -0,0 +1,6 @@
1
+ adafruit_qmc5883p.py,sha256=ZdenYn0bvGe0vFlGU2hnrqcT-0JkbW0xxnxCXCWTD_Y,8960
2
+ adafruit_circuitpython_qmc5883p-1.0.0.dist-info/licenses/LICENSE,sha256=wVvRttvrBkNBywZ9UleFPOXyBN2G0jmzBWx2sMlPn84,1100
3
+ adafruit_circuitpython_qmc5883p-1.0.0.dist-info/METADATA,sha256=nHm6IPBBN-0CDBltLq_IO0TEDm7L7T5gaR3j8xam6-s,4693
4
+ adafruit_circuitpython_qmc5883p-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ adafruit_circuitpython_qmc5883p-1.0.0.dist-info/top_level.txt,sha256=pRG0X7-QH4J554Rk-AIdHQ6E4jAZymZEuGF5fyJaprA,18
6
+ adafruit_circuitpython_qmc5883p-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Liz Clark for Adafruit Industries
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
+ adafruit_qmc5883p
adafruit_qmc5883p.py ADDED
@@ -0,0 +1,316 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 Liz Clark for Adafruit Industries
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """
5
+ `adafruit_qmc5883p`
6
+ ================================================================================
7
+
8
+ CircuitPython driver for the Adafruit QMC5883P - Triple Axis Magnetometer - STEMMA QT
9
+
10
+
11
+ * Author(s): Liz Clark
12
+
13
+ Implementation Notes
14
+ --------------------
15
+
16
+ **Hardware:**
17
+
18
+ * `Adafruit QMC5883P - Triple Axis Magnetometer <https://www.adafruit.com/product/6388>`_"
19
+
20
+ **Software and Dependencies:**
21
+
22
+ * Adafruit CircuitPython firmware for the supported boards:
23
+ https://circuitpython.org/downloads
24
+
25
+ * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
26
+ * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
27
+ """
28
+
29
+ import struct
30
+ import time
31
+
32
+ from adafruit_bus_device.i2c_device import I2CDevice
33
+ from adafruit_register.i2c_bit import ROBit, RWBit
34
+ from adafruit_register.i2c_bits import RWBits
35
+ from adafruit_register.i2c_struct import ROUnaryStruct
36
+ from micropython import const
37
+
38
+ try:
39
+ from typing import Tuple
40
+
41
+ import busio
42
+ except ImportError:
43
+ pass
44
+
45
+ __version__ = "1.0.0"
46
+ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_QMC5883P.git"
47
+
48
+ # I2C Address
49
+ _DEFAULT_ADDR = const(0x2C)
50
+
51
+ # Registers
52
+ _CHIPID = const(0x00)
53
+ _XOUT_LSB = const(0x01)
54
+ _XOUT_MSB = const(0x02)
55
+ _YOUT_LSB = const(0x03)
56
+ _YOUT_MSB = const(0x04)
57
+ _ZOUT_LSB = const(0x05)
58
+ _ZOUT_MSB = const(0x06)
59
+ _STATUS = const(0x09)
60
+ _CONTROL1 = const(0x0A)
61
+ _CONTROL2 = const(0x0B)
62
+
63
+ # Operating modes
64
+ MODE_SUSPEND = const(0x00)
65
+ MODE_NORMAL = const(0x01)
66
+ MODE_SINGLE = const(0x02)
67
+ MODE_CONTINUOUS = const(0x03)
68
+
69
+ # Output data rates
70
+ ODR_10HZ = const(0x00)
71
+ ODR_50HZ = const(0x01)
72
+ ODR_100HZ = const(0x02)
73
+ ODR_200HZ = const(0x03)
74
+
75
+ # Over sample ratios
76
+ OSR_8 = const(0x00)
77
+ OSR_4 = const(0x01)
78
+ OSR_2 = const(0x02)
79
+ OSR_1 = const(0x03)
80
+
81
+ # Downsample ratios
82
+ DSR_1 = const(0x00)
83
+ DSR_2 = const(0x01)
84
+ DSR_4 = const(0x02)
85
+ DSR_8 = const(0x03)
86
+
87
+ # Field ranges
88
+ RANGE_30G = const(0x00)
89
+ RANGE_12G = const(0x01)
90
+ RANGE_8G = const(0x02)
91
+ RANGE_2G = const(0x03)
92
+
93
+ # Set/Reset modes
94
+ SETRESET_ON = const(0x00)
95
+ SETRESET_SETONLY = const(0x01)
96
+ SETRESET_OFF = const(0x02)
97
+
98
+ # LSB per Gauss for each range
99
+ _LSB_PER_GAUSS = {RANGE_30G: 1000.0, RANGE_12G: 2500.0, RANGE_8G: 3750.0, RANGE_2G: 15000.0}
100
+
101
+
102
+ class QMC5883P:
103
+ """Driver for the QMC5883P 3-axis magnetometer.
104
+
105
+ :param ~busio.I2C i2c_bus: The I2C bus the QMC5883P is connected to.
106
+ :param int address: The I2C address of the device. Defaults to :const:`0x3C`
107
+ """
108
+
109
+ # Register definitions using adafruit_register
110
+ _chip_id = ROUnaryStruct(_CHIPID, "<B")
111
+
112
+ # Status register bits
113
+ data_ready = ROBit(_STATUS, 0)
114
+ """Check if new magnetic data is ready."""
115
+ overflow = ROBit(_STATUS, 1)
116
+ """Check if data overflow has occurred."""
117
+
118
+ # Control register 1 bits
119
+ _mode = RWBits(2, _CONTROL1, 0)
120
+ _odr = RWBits(2, _CONTROL1, 2)
121
+ _osr = RWBits(2, _CONTROL1, 4)
122
+ _dsr = RWBits(2, _CONTROL1, 6)
123
+
124
+ # Control register 2 bits
125
+ _setreset = RWBits(2, _CONTROL2, 0)
126
+ _range = RWBits(2, _CONTROL2, 2)
127
+ _selftest = RWBit(_CONTROL2, 6)
128
+ _reset = RWBit(_CONTROL2, 7)
129
+
130
+ def __init__(self, i2c_bus: busio.I2C, address: int = _DEFAULT_ADDR) -> None:
131
+ self.i2c_device = I2CDevice(i2c_bus, address)
132
+
133
+ # Check chip ID
134
+ if self._chip_id != 0x80:
135
+ raise RuntimeError("Failed to find QMC5883P chip")
136
+
137
+ # Initialize with default settings
138
+ self.mode = MODE_NORMAL
139
+ self.data_rate = ODR_50HZ
140
+ self.oversample_ratio = OSR_4
141
+ self.downsample_ratio = DSR_2
142
+ self.range = RANGE_8G
143
+ self.setreset_mode = SETRESET_ON
144
+
145
+ @property
146
+ def magnetic(self) -> Tuple[float, float, float]:
147
+ """The magnetic field measured in microteslas (uT).
148
+
149
+ :return: A 3-tuple of X, Y, Z axis values in microteslas
150
+ """
151
+ # Wait for data ready
152
+ while not self.data_ready:
153
+ time.sleep(0.001)
154
+
155
+ # Read all 6 bytes at once
156
+ buf = bytearray(6)
157
+ with self.i2c_device as i2c:
158
+ i2c.write_then_readinto(bytes([_XOUT_LSB]), buf)
159
+
160
+ # Unpack as signed 16-bit integers
161
+ raw_x, raw_y, raw_z = struct.unpack("<hhh", buf)
162
+
163
+ # Get conversion factor based on current range
164
+ lsb_per_gauss = _LSB_PER_GAUSS[self._range]
165
+
166
+ # Convert to Gauss then to microteslas (1 Gauss = 100 uT)
167
+ x = raw_x / lsb_per_gauss
168
+ y = raw_y / lsb_per_gauss
169
+ z = raw_z / lsb_per_gauss
170
+
171
+ return (x, y, z)
172
+
173
+ @property
174
+ def magnetic_raw(self) -> Tuple[int, int, int]:
175
+ """The raw magnetic field sensor values as signed 16-bit integers.
176
+
177
+ :return: A 3-tuple of X, Y, Z axis raw values
178
+ """
179
+ # Wait for data ready
180
+ while not self._data_ready:
181
+ time.sleep(0.001)
182
+
183
+ # Read all 6 bytes at once
184
+ buf = bytearray(6)
185
+ with self.i2c_device as i2c:
186
+ i2c.write_then_readinto(bytes([_XOUT_LSB]), buf)
187
+
188
+ # Unpack as signed 16-bit integers
189
+ return struct.unpack("<hhh", buf)
190
+
191
+ @property
192
+ def mode(self) -> int:
193
+ """The operating mode of the sensor.
194
+
195
+ Options are:
196
+ - MODE_SUSPEND (0x00): Suspend mode
197
+ - MODE_NORMAL (0x01): Normal mode
198
+ - MODE_SINGLE (0x02): Single measurement mode
199
+ - MODE_CONTINUOUS (0x03): Continuous mode
200
+ """
201
+ return self._mode
202
+
203
+ @mode.setter
204
+ def mode(self, value: int) -> None:
205
+ if value not in {MODE_SUSPEND, MODE_NORMAL, MODE_SINGLE, MODE_CONTINUOUS}:
206
+ raise ValueError("Invalid mode")
207
+ self._mode = value
208
+
209
+ @property
210
+ def data_rate(self) -> int:
211
+ """The output data rate in Hz.
212
+
213
+ Options are:
214
+ - ODR_10HZ (0x00): 10 Hz
215
+ - ODR_50HZ (0x01): 50 Hz
216
+ - ODR_100HZ (0x02): 100 Hz
217
+ - ODR_200HZ (0x03): 200 Hz
218
+ """
219
+ return self._odr
220
+
221
+ @data_rate.setter
222
+ def data_rate(self, value: int) -> None:
223
+ if value not in {ODR_10HZ, ODR_50HZ, ODR_100HZ, ODR_200HZ}:
224
+ raise ValueError("Invalid output data rate")
225
+ self._odr = value
226
+
227
+ @property
228
+ def oversample_ratio(self) -> int:
229
+ """The over sample ratio.
230
+
231
+ Options are:
232
+ - OSR_8 (0x00): Over sample ratio = 8
233
+ - OSR_4 (0x01): Over sample ratio = 4
234
+ - OSR_2 (0x02): Over sample ratio = 2
235
+ - OSR_1 (0x03): Over sample ratio = 1
236
+ """
237
+ return self._osr
238
+
239
+ @oversample_ratio.setter
240
+ def oversample_ratio(self, value: int) -> None:
241
+ if value not in {OSR_8, OSR_4, OSR_2, OSR_1}:
242
+ raise ValueError("Invalid oversample ratio")
243
+ self._osr = value
244
+
245
+ @property
246
+ def downsample_ratio(self) -> int:
247
+ """The downsample ratio.
248
+
249
+ Options are:
250
+ - DSR_1 (0x00): Downsample ratio = 1
251
+ - DSR_2 (0x01): Downsample ratio = 2
252
+ - DSR_4 (0x02): Downsample ratio = 4
253
+ - DSR_8 (0x03): Downsample ratio = 8
254
+ """
255
+ return self._dsr
256
+
257
+ @downsample_ratio.setter
258
+ def downsample_ratio(self, value: int) -> None:
259
+ if value not in {DSR_1, DSR_2, DSR_4, DSR_8}:
260
+ raise ValueError("Invalid downsample ratio")
261
+ self._dsr = value
262
+
263
+ @property
264
+ def range(self) -> int:
265
+ """The magnetic field range.
266
+
267
+ Options are:
268
+ - RANGE_30G (0x00): ±30 Gauss range
269
+ - RANGE_12G (0x01): ±12 Gauss range
270
+ - RANGE_8G (0x02): ±8 Gauss range
271
+ - RANGE_2G (0x03): ±2 Gauss range
272
+ """
273
+ return self._range
274
+
275
+ @range.setter
276
+ def range(self, value: int) -> None:
277
+ if value not in {RANGE_30G, RANGE_12G, RANGE_8G, RANGE_2G}:
278
+ raise ValueError("Invalid range")
279
+ self._range = value
280
+
281
+ @property
282
+ def setreset_mode(self) -> int:
283
+ """The set/reset mode.
284
+
285
+ Options are:
286
+ - SETRESET_ON (0x00): Set and reset on
287
+ - SETRESET_SETONLY (0x01): Set only on
288
+ - SETRESET_OFF (0x02): Set and reset off
289
+ """
290
+ return self._setreset
291
+
292
+ @setreset_mode.setter
293
+ def setreset_mode(self, value: int) -> None:
294
+ if value not in {SETRESET_ON, SETRESET_SETONLY, SETRESET_OFF}:
295
+ raise ValueError("Invalid set/reset mode")
296
+ self._setreset = value
297
+
298
+ def soft_reset(self) -> None:
299
+ """Perform a soft reset of the chip."""
300
+ self._reset = True
301
+ time.sleep(0.05) # Wait 50ms for reset to complete
302
+
303
+ # Verify chip ID after reset
304
+ if self._chip_id != 0x80:
305
+ raise RuntimeError("Chip ID invalid after reset")
306
+
307
+ def self_test(self) -> bool:
308
+ """Perform self-test of the chip.
309
+
310
+ :return: True if self-test passed, False otherwise
311
+ """
312
+ self._selftest = True
313
+ time.sleep(0.005) # Wait 5ms for self-test to complete
314
+
315
+ # Check if self-test bit auto-cleared (indicates completion)
316
+ return not self._selftest