elektronische Wasserwaage


(spirit level)

- auf dem runden 1.28-Zoll-IPS-LCD-Display 240 x 240 Pixel
- nutzt den ACC Beschleunigungssensor in CircuitPython



Die erste Version der Wasserwaage war noch in Micropython geschrieben, die Sie hier über diesen Link erreichen. Jetzt nutzt sie den ACC-Sensor unter CircuitPython und stellt die Position mit 4 Progressbars dar.

Hardware

- Rundes 1,28-Zoll-IPS-LCD-Display
- RP Pico 2040 (inclusive)
- USB-A zu USB-C Kabel


Wenn Sie z.B. ihr Wohnmobil auf dem Campingplatz abstellen, soll es in der 'Waage' stehen. Um diese waagerechte Ausrichtung zu bestimmen, nutzen Sie eine Wasserwaage. Eine kleine Wasserblase bewegt sich dabei in einem Glasröhrchen, einer s.g. Libelle. Bei unserem Display werden wir das mit Hilfe der Progressbars umsetzen. Der ACC-Sensor misst die Abweichung von 'Null' in x- und y-Richtung und stellt diese optisch dar.

Los gehts

Nachdem Sie die Firmware CircuitPython auf dem Pico-Display installiert haben, müssen Sie einige Bibliotheken im 'lib-Ordner' speichern. Es sind dies der Displaytreiber gc9a01.py, der Sensortreiber my_qmi8658.py und die Bibliothek adafruit_progressbar. Außerdem benötigt der Programmablauf auch adafruit_display_shapes und adafruit_display_text. Die Adafruit-Bibliotheken können Sie aus deren Bundle in den 'lib-Ordner' kopieren. Oder Sie laden sich die zip-Datei mit allen benötigten Treibern hier von meiner Seite herunter, entpacken sie und kopieren sie in den 'lib-Ordner'. Los geht es dann wieder mit dem Import der Module ind den Zeilen bis 23. Es folgen die Initialisierung des Sensors und des Displays.

  
  

1  # SPDX-FileCopyrightText : 2023 Detlef Gebhardt, written for CircuitPython
2  # SPDX-FileCopyrightText : Copyright (c) 2023 Detlef Gebhardt
3  # SPDX-Filename          : ACC-Spirit-Level
4  # SPDX-License-Identifier: GEBMEDIA
5  import time
6  import gc
7  import displayio
8  import terminalio
9  import board
10 import busio
11 import gc9a01
12 import my_qmi8658
13 from adafruit_display_text import label
14 from adafruit_display_shapes.rect import Rect
15 from adafruit_display_shapes.circle import Circle
16 from adafruit_progressbar.horizontalprogressbar import (
17     HorizontalProgressBar,
18     HorizontalFillDirection,
19 )
20 from adafruit_progressbar.verticalprogressbar import (
21     VerticalProgressBar,
22     VerticalFillDirection,
23 )
24
25 # ACC-Sensor initialisieren
26 sensor=my_qmi8658.QMI8658()
27 #
28 # Display initialisieren
29 #
30 # Release any resources currently in use for the displays
31 displayio.release_displays()
32 # Make the displayio SPI bus and the GC9A01 display
33 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN)
34 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST)
35 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL)
36
37 main = displayio.Group()
38 display.show(main)
39
  

Es folgen die Programmzeilen 40 bis 65. Dort wird der Hintergrund gestaltet.

  
  

40 # Make the background bitmap
41 color_bitmap = displayio.Bitmap(240, 240, 1)
42 color_palette = displayio.Palette(1)
43 #color_palette[0] = 0x03C2FC
44 color_palette[0] = 0x006600
45 bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
46 main.append(bg_sprite)
47 circle = Circle(120,120,115,fill=0x660033,outline=None)
48 main.append(circle)
49 circle = Circle(120,120,65,fill=0xffffff,outline=None)
50 main.append(circle)
51 circle = Circle(120,120,64,fill=0x660033,outline=None)
52 main.append(circle)
53 circle = Circle(120,120,40,fill=0xffffff,outline=None)
54 main.append(circle)
55 circle = Circle(120,120,39,fill=0x660033,outline=None)
56 main.append(circle)
57 # create the label
58 text_group_step = displayio.Group(scale=2, x=50, y=25)
59 text_area1 = label.Label(terminalio.FONT, text="    Pico\n\n\n\n\n\nspirit-level", color=0xffff00)
60 text_group_step.append(text_area1)
61 main.append(text_group_step)
62
63 rect = Rect(105,105, 30,30,fill=0x00cc00, outline=None)
64 main.append(rect)
65

Danach werden die Progressbars angelegt. In der Reihenfolge sind das
- eine linke Horizontalbar,
- eine rechte Horizontalbar,
- eine obere Verticalbar und
- eine untere Verticalbar.
Die Koordinaten sind so gewählt, dass ein Kreuz entsteht. Die freie Fläche in der Mitte wird mit einem farbigen Quadrat (rect) gefüllt.

  
  

66  # Accelerometer Properties. Normally accelerometer well calibrated
67  # Will give a maximum output of 10 m/s**2
68  VALUES_X = (-10, 10)
69  VALUES_Y = (-10, 10)
70
71  #
72  # We create our bar displays
73  #
74  left_horizontal_bar = HorizontalProgressBar(
75      (45, 105),(60, 30), min_value=0, max_value=-VALUES_X[0],
76      direction=HorizontalFillDirection.RIGHT_TO_LEFT,
77      bar_color=0x00cc00, outline_color=0xffffff, fill_color=0x606060)
78  main.append(left_horizontal_bar)
79
80  right_horizontal_bar = HorizontalProgressBar(
81      (135, 105), (60, 30), min_value=0, max_value=VALUES_X[1],
82      direction=HorizontalFillDirection.LEFT_TO_RIGHT,
83      bar_color=0x00cc00, outline_color=0xffffff, fill_color=0x606060)
84  main.append(right_horizontal_bar)
85
86  top_vertical_bar = VerticalProgressBar(
87      (105, 45), (30, 60), min_value=0, max_value=VALUES_Y[1],
88      direction=VerticalFillDirection.BOTTOM_TO_TOP,
89      bar_color=0x00cc00, outline_color=0xffffff, fill_color=0x606060)
90  main.append(top_vertical_bar)
91
92  bottom_vertical_bar = VerticalProgressBar(
93      (105, 135), (30, 60), min_value=0, max_value=-VALUES_Y[0],
94      direction=VerticalFillDirection.TOP_TO_BOTTOM,
95      bar_color=0x00cc00, outline_color=0xffffff, fill_color=0x606060)
96  main.append(bottom_vertical_bar)
97
  



Das Bild oben zeigt, was jetzt in der 'while'- Schleife passiert. Zunächst wird der Sensor für die x- und y_Richtung gelesen. Damit der Ausschlag in der jeweiligen Progressbar entsprechend groß ist, habe ich die Werte vervielfacht. Da der Sensor in y-Richtung deutlich stärker ansprach nur mit 50, während in x-Richtung der Faktor 100 gute Anzeigewerte ergab. Danach werden die Werte angezeigt. Z.B. in den Zeilen 106 bis 114 für den Ausschlag nach rechts. Ist der 'wert_x' dort zwischen -10 und 0, dann erscheint der Progresswert in dem Grünton. Ist der Ausschlag dagegen am Anschlag, dann wird der Balken rot. Analog für die anderen Richtungen.

  
  

98  while True:
99      #read QMI8658
100     val=sensor.Read_XYZ()
101     # Display wird rel. zur x-Achse bewegt
102     wert_x = (100)*val[0]
103     # Display wird rel. zur y-Achse bewegt
104     wert_y = (50)*val[1]
105     # x-Werte
106     ## Ausschlag nach rechts
107     if wert_x < 0 and wert_x >= -10:
108         right_horizontal_bar.value = -wert_x
109         left_horizontal_bar.value = 0
110         right_horizontal_bar.bar_color=0x00cc00
111     if wert_x < -10:
112         right_horizontal_bar.value = 10
113         left_horizontal_bar.value = 0
114         right_horizontal_bar.bar_color=0xff0000
115     # Ausschlag nach links
116     if wert_x >= 0 and wert_x < 10:
117         left_horizontal_bar.value = wert_x
118         right_horizontal_bar.value = 0
119         left_horizontal_bar.bar_color=0x00cc00
120     if wert_x >= 10:
121        left_horizontal_bar.value = 10
122         right_horizontal_bar.value = 0
123         left_horizontal_bar.bar_color=0xff0000
124     # y-Werte
125     ## Ausschlag nach oben
126     if wert_y >= 0 and wert_y < 10:
127         top_vertical_bar.value = wert_y
128         bottom_vertical_bar.value = 0
129         top_vertical_bar.bar_color=0x00cc00
130     if wert_y >= 10:
131         top_vertical_bar.value = 10
132         bottom_vertical_bar.value = 0
133         top_vertical_bar.bar_color=0xff0000
134     # Ausschlag nach unten
135     if wert_y < 0 and wert_y >= -10:
136         bottom_vertical_bar.value = -wert_y
137         top_vertical_bar.value = 0
138         bottom_vertical_bar.bar_color=0x00cc00
139     if wert_y < -10:
140         bottom_vertical_bar.value = 10
141         top_vertical_bar.value = 0
142         bottom_vertical_bar.bar_color=0xff0000
143     display.refresh()
144     time.sleep(0.2)
145     gc.collect()
146     #print(gc.mem_free())
  






Viel Spass und Erfolg beim Ausprobieren.