Skip to content

ism330dl: Add ism330dl driver.#50

Merged
nedseb merged 11 commits intomainfrom
ism330dl
Mar 14, 2026
Merged

ism330dl: Add ism330dl driver.#50
nedseb merged 11 commits intomainfrom
ism330dl

Conversation

@Charly-sketch
Copy link
Copy Markdown
Contributor

@Charly-sketch Charly-sketch commented Mar 12, 2026

Closes #4, closes #33

Summary

Add a new MicroPython driver for the ISM330DL 6-axis IMU from STMicroelectronics.

The driver provides access to the 3-axis accelerometer, 3-axis gyroscope, and internal temperature sensor over I²C. It follows the same structure and conventions used in the other drivers of this repository.

Features

  • Full I²C driver for ISM330DL
  • Read accelerometer data (raw, g, m/s²)
  • Read gyroscope data (raw, degrees/s, radians/s)
  • Read temperature
  • Simple orientation detection using the accelerometer
  • Simple motion detection using the gyroscope
  • Device WHO_AM_I check on init
  • I2C errors wrapped in ISM330DLIOError
  • Device reset and power down support
  • Status register helper (temp_ready, gyro_ready, accel_ready)
  • Default I²C address 0x6B (STeaMi board, SA0=1)

Test plan

# Mock tests (no hardware needed)
python3 -m pytest tests/ -k "ism330dl and mock" -v

# Hardware tests (with board connected)
python3 -m pytest tests/ --port /dev/ttyACM0 -k "ism330dl and hardware" -s -v

Mock test results (19 tests)

tests/test_scenarios.py::test_scenario[ism330dl/Verify WHO_AM_I register/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Read WHO_AM_I via method/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Status returns all ready flags/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Acceleration raw returns tuple of 3 ints/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Acceleration g returns expected values/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Acceleration ms2 matches g times 9.80665/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Gyroscope raw returns tuple of 3 ints/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Gyroscope dps returns zeros when static/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Gyroscope rads consistent with dps/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Temperature returns 25.0 from mock data/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Temperature raw returns int/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Orientation detects SCREEN_DOWN/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Motion returns STABLE when static/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Configure accel changes scale/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Configure gyro changes scale/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Configure accel rejects invalid scale/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Configure gyro rejects invalid scale/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Power down writes zero to CTRL registers/mock] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Reset sets BDU and IF_INC in CTRL3_C/mock] PASSED
19 passed

Hardware test results

$ python3 -m pytest tests/ --port /dev/ttyACM0 -k "ism330dl and hardware" -s -v

======================================================= test session starts ========================================================
platform linux -- Python 3.13.7, pytest-8.3.5, pluggy-1.5.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/nedjar/sandbox/micropython-steami-lib
configfile: pytest.ini
plugins: typeguard-4.4.2
collected 194 items / 186 deselected / 8 selected                                                                                  

tests/test_scenarios.py::test_scenario[board_i2c_scan/ISM330DL WHO_AM_I (0x6B)/hardware] 0x6A
PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Verify WHO_AM_I register/hardware] 0x6A
PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Read WHO_AM_I via method/hardware] 0x6A
PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Status returns dictionary/hardware] {'accel_ready': True, 'temp_ready': True, 'gyro_ready': True}
PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Acceleration magnitude near 1g/hardware] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Gyroscope values plausible at rest/hardware] PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Temperature in plausible range/hardware] 25.45
PASSED
tests/test_scenarios.py::test_scenario[ism330dl/Sensor readings feel correct/hardware]   Acceleration (g): [-0.298961, 0.167872, -0.914146] 
  Gyroscope (dps): [0.60375, -2.5025, -0.1925] 
  Temperature: 25.50 °C
  Orientation: SCREEN_UP 
  [MANUAL] Les valeurs d'accélération, rotation, température et orientation sont-elles cohérentes ? [Entree=oui / Echap=non] 
PASSED

================================================ 8 passed, 186 deselected in 32.23s ================================================
➜  micropython-steami-lib git:(ism330dl) ✗ 

Conventions checklist

  • const.py: constants wrapped with micropython.const()
  • device.py: class ISM330DL(object):
  • device.py: pre-allocated buffer for _read_u8 / _write_u8
  • device.py: address=ISM330DL_I2C_DEFAULT_ADDR (0x6B, SA0=1)
  • device.py: check_device() called in __init__
  • device.py: I2C errors wrapped in ISM330DLIOError
  • device.py: no French comments, no superfluous blank lines
  • examples/: sleep_ms() instead of sleep()
  • examples/: unused Pin import removed
  • examples/test.py: removed (not an example)
  • README.md: LLM artifact removed
  • README.md: gyro_motion() corrected to motion(), basic_reader.py corrected to basic_read.py
  • Tests: 19 mock tests covering all public methods
  • ruff check passes

@nedseb nedseb changed the title ism330dl: Add ism330dl driver. [WIP] ism330dl: Add ism330dl driver. Mar 12, 2026
@nedseb nedseb added the enhancement New feature or request label Mar 13, 2026
@nedseb nedseb linked an issue Mar 13, 2026 that may be closed by this pull request
@nedseb nedseb self-requested a review March 13, 2026 05:55
@Charly-sketch Charly-sketch changed the title [WIP] ism330dl: Add ism330dl driver. ism330dl: Add ism330dl driver. Mar 13, 2026
@Charly-sketch Charly-sketch linked an issue Mar 13, 2026 that may be closed by this pull request
1 task
@Charly-sketch Charly-sketch marked this pull request as ready for review March 13, 2026 12:36
Copy link
Copy Markdown
Contributor

@nedseb nedseb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revue complète — ISM330DL Driver

Bon travail sur ce driver, l'API est bien pensée (raw/g/ms², dps/rads, orientation/motion). Quelques points à corriger pour respecter les conventions du projet documentées dans le README (section Contributing).


Conventions du projet (README)

1. const.py — pas de micropython.const()

"Constants: use from micropython import const wrapper in const.py files." (README L462)

Les constantes de registre et de configuration ne sont pas wrappées avec const(). Ajouter from micropython import const et wrapper les constantes scalaires. Les dicts (ACCEL_FS_BITS, ACCEL_SENSITIVITY_MG, etc.) restent tels quels.

2. device.pyclass ISM330DL:class ISM330DL(object):

"Class inheritance: class Foo(object): is the existing convention." (README L464)

3. examples/sleep()sleep_ms()

"Time: use from time import sleep_ms (not utime, not sleep() with float seconds)." (README L465)

basic_read.py, static_orientation.py, motion_orientation.py utilisent from time import sleep + sleep(0.5). Remplacer par from time import sleep_ms + sleep_ms(500).


Qualité du code

4. device.py L14 — commentaire en français dans le code de production

if address is None: # Auto-detect address. Je ne sais pas si c'est nécessaire pour la STeaMi...

À supprimer ou remplacer par un commentaire en anglais.

5. device.py L43 — allocation à chaque écriture I2C

self.i2c.writeto_mem(self.address, reg, bytes([value]))

bytes([value]) alloue un nouvel objet à chaque appel. Les autres drivers utilisent un self.writebuffer = bytearray(1) pré-alloué dans __init__. Idem pour _read_u8 (L40) : readfrom_mem() alloue vs readfrom_mem_into() avec buffer pré-alloué.

6. device.py — lignes vides superflues en début de méthode
configure_accel, acceleration_g, gyroscope_dps, temperature_c, status, power_down, etc. ont une ligne vide entre la signature et le corps. Le style du repo n'en met pas.


README du driver

7. README.md L1 — artefact de génération

Voici un **README propre et complet** pour ton driver **ISM330DL**...

Cette phrase est un artefact LLM, à supprimer.

8. README.md L167 — méthode inexistante

imu.gyro_motion()

La méthode s'appelle motion(), pas gyro_motion().


Fichiers

9. examples/test.py (387 lignes) — script de test standalone
Ce fichier duplique le rôle du framework tests/scenarios/. Il n'a pas sa place dans examples/ (qui est destiné aux exemples d'utilisation). Soit le supprimer, soit le déplacer hors de examples/.

10. examples/static_orientation.py L1 — import inutile

from machine import I2C, Pin

Pin n'est pas utilisé.

11. exceptions.pyISM330DLIOError jamais utilisée
Définie mais jamais levée dans le driver. Soit l'utiliser, soit la retirer.


Tests (scénario YAML)

12. Tests hardware trop faibles

  • acceleration_g et gyroscope_dps testent seulement expect_not_none. Pour l'accéléromètre au repos, vérifier que la magnitude est ≈ 1g serait plus utile.
  • Pas de test hardware automatique pour orientation (la carte posée à plat devrait retourner SCREEN_UP ou SCREEN_DOWN).
  • Pas de test temperature_c en hardware avec une plage raisonnable (la plage actuelle [-20, 80] est très large).

Points positifs ✓

  • API complète : raw / g / ms² pour l'accéléromètre, raw / dps / rads pour le gyro
  • Auto-détection d'adresse I2C
  • orientation() et motion() bien implémentés comme fonctions de haut niveau
  • reset() correct avec SW_RESET + attente + BDU/IF_INC
  • Mock tests avec des valeurs réalistes (z=0x4000 → ~1g)
  • Scénario YAML bien structuré avec mock + hardware + manual

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new MicroPython driver package for the ST ISM330DL 6‑axis IMU (accelerometer, gyroscope, temperature) along with examples, documentation, and a YAML scenario suite integrated into the existing test runner.

Changes:

  • Introduces lib/ism330dl driver implementation (I²C access, scaling/conversions, orientation/motion helpers, reset/power-down, custom exceptions).
  • Adds usage examples and a driver-local README.
  • Adds a new scenario file tests/scenarios/ism330dl.yaml covering mock + hardware + manual checks.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/scenarios/ism330dl.yaml Adds scenario-based mock/hardware/manual tests for the new driver.
lib/ism330dl/manifest.py Declares the new MicroPython package metadata and package name.
lib/ism330dl/ism330dl/device.py Implements the ISM330DL driver (I²C helpers, configuration, readings, helpers).
lib/ism330dl/ism330dl/const.py Defines registers, bit masks, ranges, sensitivities, and constants.
lib/ism330dl/ism330dl/exceptions.py Adds driver-specific exception types.
lib/ism330dl/ism330dl/__init__.py Exposes the driver class and exceptions at package level.
lib/ism330dl/examples/basic_read.py Example: print accel/gyro/temp periodically.
lib/ism330dl/examples/motion_orientation.py Example: simple motion detection from gyro.
lib/ism330dl/examples/static_orientation.py Example: simple orientation detection from accel.
lib/ism330dl/README.md Driver-local documentation and API description.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/scenarios/ism330dl.yaml Outdated
Comment thread tests/scenarios/ism330dl.yaml
Comment thread lib/ism330dl/manifest.py
Comment thread lib/ism330dl/ism330dl/device.py
@nedseb
Copy link
Copy Markdown
Contributor

nedseb commented Mar 14, 2026

Copilot review — changes made in 408be94

# Comment Action
1 Config tests read private _accel_scale / _gyro_scale Replaced with i2c.get_write_log() to verify the actual I2C register writes
2 Power/reset tests use private _read_u8() Replaced with i2c.get_write_log() to verify writes without calling private methods
3 Naming mismatch ism330dl vs ism330dlc in root README Out of scope — the chip is ISM330DL, root README will be fixed separately (see #119)
4 configure_accel() / configure_gyro() don't validate odr Added ACCEL_ODR_VALUES / GYRO_ODR_VALUES tuples and validation with ISM330DLConfigError. Two new rejection tests added

Test count went from 19 to 21 mock tests, all passing.

@nedseb nedseb merged commit a6293f9 into main Mar 14, 2026
3 checks passed
@nedseb nedseb deleted the ism330dl branch March 14, 2026 15:19
@semantic-release-updater
Copy link
Copy Markdown

🎉 This PR is included in version 0.0.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tests: Add test scenario for ISM330DL accelerometer and gyroscope. ism330dl: Add ISM330DLCTR accelerometer and gyroscope driver

3 participants