feat(ism330dl): Add OLED spirit level example.#376
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new interactive ISM330DL + SSD1327 OLED example that visualizes board tilt as a “bubble” moving around a center crosshair, with a brighter background when the device is near level.
Changes:
- Added
lib/ism330dl/examples/spirit_level.pyimplementing spirit-level visualization on the SSD1327 OLED. - Included a custom
fill_circle()helper for drawing a filled circular bubble withframebuf.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # 1. Read acceleration in g-forces | ||
| ax, ay, az = imu.acceleration_g() | ||
|
|
There was a problem hiding this comment.
az is unpacked from imu.acceleration_g() but never used. With Ruff enabled for examples (no per-file ignore for F841), this should be renamed to _/_az or used to avoid an unused-variable lint failure.
There was a problem hiding this comment.
I've renamed the unused Z-axis variable to _az to satisfy Ruff's F841 rule and clearly indicate it's intentionally ignored.
| for x in range(-r, r + 1): | ||
| if x*x + y*y <= r*r: | ||
| fbuf.pixel(x0 + x, y0 + y, c) |
There was a problem hiding this comment.
The circle fill test uses operators without surrounding whitespace (x*x, r*r, etc.). Ruff explicitly enables E225, so this should be spaced (x * x, etc.) to pass linting.
There was a problem hiding this comment.
I added the required whitespace around the operators in the fill_circle helper (x * x, etc.) to comply with Ruff E225.
| # 3. Map Acceleration to Pixel Offset | ||
| # We cap the acceleration at 1.0g to avoid the bubble leaving the screen | ||
| # 3. Map Acceleration to Pixel Offset | ||
| clamped_ax = max(-1.0, min(1.0, ax)) | ||
| clamped_ay = max(-1.0, min(1.0, ay)) |
There was a problem hiding this comment.
Duplicate comment header: "Map Acceleration to Pixel Offset" is repeated consecutively. Consider removing one copy to keep the example clean.
There was a problem hiding this comment.
I've removed the duplicated header.
| """Spirit level example using ISM330DL accelerometer and SSD1327 OLED. | ||
|
|
||
| Displays a digital bubble level. The bubble moves according to the board's tilt. | ||
| When the board is perfectly flat, the bubble centers and the background lights up. | ||
| """ |
There was a problem hiding this comment.
PR description mentions adding this example to a README examples table, but lib/ism330dl/README.md currently lists only basic_read/static_orientation/motion_orientation and does not include spirit_level.py. Either update the docs or adjust the PR description so they match.
There was a problem hiding this comment.
My mistake, I missed staging the README.md file in my previous commit. It's now properly updated in the examples table and included in this push.
7939156 to
2566c26
Compare
ReviewTrès bon travail sur cet exemple. Le rendu est clair et intuitif, et l’effet “niveau à bulle” fonctionne très bien. L’utilisation de l’accéléromètre est pertinente, et le mapping vers l’écran est bien pensé. L’ajout du crosshair, de la zone centrale et du feedback visuel (changement de luminosité) rend l’exemple à la fois pédagogique et agréable à utiliser. Le code est globalement propre, lisible, avec de bonnes constantes et une structure simple à suivre. Quelques points à améliorer : 1. Duplication de commentaire# 3. Map Acceleration to Pixel Offset
# 3. Map Acceleration to Pixel OffsetPetit détail mais à nettoyer pour garder le code propre. 2. Position de la bulle non clampéebubble_x = SCREEN_CENTER_X + offset_x
bubble_y = SCREEN_CENTER_Y + offset_yMême avec le clamp à ±1g, la bulle peut sortir de l’écran ou être partiellement coupée. Suggestion : clamp final des coordonnées pour garantir qu’elle reste visible : bubble_x = max(BUBBLE_RADIUS, min(127 - BUBBLE_RADIUS, bubble_x))
bubble_y = max(BUBBLE_RADIUS, min(127 - BUBBLE_RADIUS, bubble_y))3. Inversion d’axe non expliquéeoffset_x = int(-clamped_ay * MAX_OFFSET)Le Suggestion : ajouter un commentaire rapide pour clarifier l’intention (ex : inversion pour simuler la montée de la bulle vers le point haut). ConclusionExemple très réussi et utile pour comprendre comment combiner capteur + affichage avec une interaction visuelle en temps réel. Avec ces petits ajustements, il sera encore plus propre et robuste. |
2566c26 to
66dcd0c
Compare
Summary
Closes #329
Adds an interactive
spirit_level.pyexample demonstrating a digital bubble level using the ISM330DL accelerometer and the SSD1327 OLED display. The bubble moves dynamically based on the board's physical tilt, providing real-time visual feedback.Changes
lib/ism330dl/examples/spirit_level.py.acceleration_g()) to a 2D pixel offset.fill_circle()helper function to draw a smooth bubble (bypassing the lack of native ellipse support inframebuf).< 0.05g).spirit_level.pyexample to theREADME.mdexamples table.Checklist
ruff checkpassespython -m pytest tests/ -k mock -vpasses (no mock test broken)<scope>: <Description.>format