Bemerkung
Hallo, willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauchen Sie mit anderen Enthusiasten tiefer in Raspberry Pi, Arduino und ESP32 ein.
Warum beitreten?
Expertenunterstützung: Lösen Sie Probleme nach dem Kauf und technische Herausforderungen mit Hilfe unserer Community und unseres Teams.
Lernen & Teilen: Tauschen Sie Tipps und Tutorials aus, um Ihre Fähigkeiten zu verbessern.
Exklusive Vorschauen: Erhalten Sie frühzeitigen Zugang zu neuen Produktankündigungen und Sneak Peeks.
Sonderrabatte: Genießen Sie exklusive Rabatte auf unsere neuesten Produkte.
Festliche Aktionen und Gewinnspiele: Nehmen Sie an Gewinnspielen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu gestalten? Klicken Sie auf [here] und treten Sie noch heute bei!
4.10 Farbregler (Hue Knob)
Einführung
In dieser Lektion bauen Sie einen Hue Knob – einen interaktiven Farbregler, der einen Drehencoder verwendet, um den Farbton eines kreisförmigen WS2812-LED-Moduls anzupassen. Dieses WS2812-LED-Modul enthält 12 einzeln adressierbare WS2812-RGB-LEDs, die über die SPI-basierte NeoPixel-Schnittstelle des Fusion HAT+ gesteuert werden. Der externe Drehencoder liefert Echtzeit-Benutzereingaben über standardmäßige GPIO-Pins.
Beim Drehen des Encoders durchlaufen die 12 LEDs fließend das gesamte RGB-Farbspektrum. Durch Drücken der integrierten Taste des Encoders wird der Farbton wieder auf den Ausgangswert zurückgesetzt.
Was Sie benötigen
Für dieses Projekt werden die folgenden Komponenten benötigt:
KOMPONENTENBESCHREIBUNG |
KAUFLINK |
|---|---|
- |
|
- |
|
Raspberry Pi |
- |
Verdrahtungsdiagramm
Verwenden Sie das folgende Verdrahtungsdiagramm, um die Komponenten korrekt zu verbinden:
Einrichtungsschritte
Bevor Sie den Code ausführen, müssen Sie die erforderliche Bibliothek installieren:
Diese Bibliothek stellt die notwendigen Funktionen bereit, um NeoPixel-LEDs über SPI-Kommunikation zu steuern.
sudo pip3 install adafruit-circuitpython-neopixel-spi --break
Der gesamte in diesem Tutorial verwendete Beispielcode befindet sich im Verzeichnis
ai-lab-kit. Führen Sie die folgenden Schritte aus, um das Beispiel auszuführen:cd ~/ai-lab-kit/python/ sudo python3 4.10_Hue_Knob.py
Wenn das Skript ausgeführt wird, reagiert der WS2812-LED-Ring auf den Drehencoder:
Die LEDs starten in Rot (Hue 0°).
Drehen Sie den Encoder, um fließend durch das gesamte RGB-Farbrad zu wechseln. Die Farben ändern sich kontinuierlich (Rot → Gelb → Grün → Blau → Violett → Rot). Im Terminal werden der aktuelle Hue-Wert sowie die RGB-Werte ausgegeben.*
Drücken Sie die Encodertaste, um den Farbton auf 0° (Rot) zurückzusetzen.
Drücken Sie Ctrl+C, um das Programm zu beenden. Alle LEDs werden ausgeschaltet, bevor das Programm beendet wird.
Code
Hier ist das Python-Skript für dieses Projekt:
#!/usr/bin/env python3
from fusion_hat.motor import Motor
from fusion_hat.pin import Pin, Mode, Pull
from fusion_hat.adc import ADC
from time import sleep, time
import math
BtnPin = Pin(22, mode=Mode.IN, pull=Pull.DOWN)
motor = Motor("M0")
thermistor = ADC("A3")
level = 0
currentTemp = None
markTemp = None
PRINT_INTERVAL = 1.0
_last_print = 0.0
button_event = False # flag: button was pressed
def temperature(samples=5, delay=0.01):
"""Read thermistor multiple times and return averaged Celsius (float) or None."""
vals = []
for _ in range(samples):
analogVal = thermistor.read()
Vr = 3.3 * float(analogVal) / 4095.0
if (3.3 - Vr) <= 0.1:
return None
Rt = 10000.0 * Vr / (3.3 - Vr)
tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
vals.append(tempK - 273.15)
sleep(delay)
return sum(vals) / len(vals)
def motor_run(lv):
lv = max(0, min(4, lv))
motor.power(0 if lv == 0 else lv * 25)
return lv
def changeLevel():
"""Button press: cycle level 0~4 and set a flag for main loop to print."""
global level, button_event
level = (level + 1) % 5
button_event = True
BtnPin.when_activated = changeLevel
def main():
global level, currentTemp, markTemp, _last_print, button_event
markTemp = temperature()
while True:
currentTemp = temperature()
if currentTemp is None:
print("Sensor read failed. Please check the sensor.")
sleep(0.5)
continue
# Handle button event in main loop (stable timing)
if button_event:
button_event = False
markTemp = currentTemp
print(f"[Button] Level -> {level} | Temp: {currentTemp:.2f} °C | Mark: {markTemp:.2f} °C")
# Periodic temperature print
now = time()
if now - _last_print >= PRINT_INTERVAL:
if markTemp is None:
markTemp = currentTemp
print(f"Temp: {currentTemp:.2f} °C | Mark: {markTemp:.2f} °C | Level: {level}")
_last_print = now
# Auto adjust level based on ±5°C
if markTemp is None:
markTemp = currentTemp
if level != 0:
diff = currentTemp - markTemp
if diff <= -5:
level = max(0, level - 1)
markTemp = currentTemp
print(f"[Auto] Temp down -> Level {level} (Temp: {currentTemp:.2f} °C)")
elif diff >= 5:
level = min(4, level + 1)
markTemp = currentTemp
print(f"[Auto] Temp up -> Level {level} (Temp: {currentTemp:.2f} °C)")
level = motor_run(level)
sleep(0.5)
try:
main()
except KeyboardInterrupt:
print("\nExiting...")
finally:
motor.stop()
sleep(0.1)
Code verstehen
NeoPixel-Initialisierung
Das Skript verwendet SPI, um einen NeoPixel-LED-Ring oder -Streifen zu steuern (
LED_COUNT = 12).auto_write=Falseist aktiviert, sodass die LEDs erst aktualisiert werden, wennstrip.show()aufgerufen wird. Dadurch werden Flackern reduziert und die Leistung verbessert.Beim Start werden die LEDs mit
strip.fill(0)undstrip.show()ausgeschaltet.
Hardware-Setup des Drehencoders
Es werden drei GPIO-Pins verwendet: -
CLK_PINundDT_PINliefern die Quadratur-Signale für Drehrichtung und Schritte. -SW_PINist der Tastereingang des Encoders.Alle Pins verwenden interne Pull-ups (
Pull.UP), und der Taster ist aktiv LOW (gedrückt =0).
Wichtige Parameter (Verhaltensabstimmung)
DETENTS_PER_CYCLEdefiniert, wie viele physische „Klicks“ erforderlich sind, um eine vollständige Farbtonrotation (0–360°) abzuschließen. - Ein größerer Wert ermöglicht eine feinere Farbsteuerung.TRANSITIONS_PER_DETENTwandelt rohe Quadratur-Übergänge in „ein Raster = ein Schritt“ um. - Viele Encoder erzeugen 2 Übergänge pro Raster, einige jedoch 4. Durch Anpassen dieses Wertes wird die Genauigkeit verbessert.
hue_to_rgb()Wandelt einen Hue-Wert im Bereich
0.0 ~ 1.0in ein RGB-Tupel(R, G, B)mit Werten von0 ~ 255um.Dadurch lassen sich mit dem HSV-Farbmodell leicht sanfte Farbverläufe erzeugen.
apply_color_from_detent()Ordnet die Rasterzählung des Encoders mithilfe von Modulo einem Farbtonindex zu: -
hue_idx = detent % DETENTS_PER_CYCLEWandelt den Farbton in eine RGB-Farbe um und aktualisiert alle LEDs mit
strip.fill(color)gefolgt vonstrip.show().Verwendet
last_hue_idx, um unnötige Aktualisierungen zu vermeiden, wenn sich der berechnete Farbton nicht geändert hat.Gibt den aktuellen Hue-Winkel, den Rasterwert und die RGB-Farbe zur Kontrolle bzw. Fehlersuche im Terminal aus.
reset_all()Setzt den internen Zählerzustand zurück: -
raw(rohe Übergangszählung) -last_detent(zuletzt angezeigtes Raster) -last_hue_idx(zuletzt angezeigter Farbtonindex)Ruft
apply_color_from_detent(0)auf, um die LEDs sofort auf die Ausgangsfarbe (Hue = 0°) zurückzusetzen.
Hauptschleife (Polling + Richtungsbestimmung)
Das Programm überwacht kontinuierlich
CLKund prüft auf Änderungen: - Wenn sichCLKändert, hat sich der Encoder um einen Schritt in der Quadratur-Sequenz bewegt.Die Drehrichtung wird durch Vergleich von DT und CLK bestimmt: -
dt.value() != cbedeutet eine Drehrichtung (Erhöhen) - andernfalls wird verringertDie rohe Übergangszählung wird in Rasterwerte umgerechnet: -
detent = raw // TRANSITIONS_PER_DETENTDie LED-Farbe wird nur aktualisiert, wenn sich der Rasterwert geändert hat.
Taster-Reset und Entprellung
Wenn der Taster gedrückt wird (
sw.value() == 0), ruft das Programmreset_all()auf.Eine kurze Entprellverzögerung wird angewendet, und das Skript wartet, bis der Taster wieder losgelassen wird, um mehrere Resets durch einen einzelnen Tastendruck zu verhindern.
Sauberes Beenden
Durch Drücken von
Ctrl + Cwird das Programm beendet.Im
finally-Block werden alle LEDs ausgeschaltet (strip.fill(0)undstrip.show()), sodass die Hardware in einem sicheren Zustand verbleibt.
Fehlerbehebung
LEDs leuchten nicht
Überprüfen Sie die Verdrahtung des WS2812-LED-Moduls.
Stellen Sie sicher, dass die SPI-NeoPixel-Schnittstelle des Fusion HAT+ aktiviert ist.
Vergewissern Sie sich, dass ein unterstütztes WS2812/WS2812B-LED-Modul verwendet wird.
Farben ändern sich zu schnell oder zu langsam
Passen Sie
STEPS_PER_CYCLEan, um die Empfindlichkeit zu erhöhen oder zu verringern.
Tastendruck setzt den Farbton nicht zurück
Überprüfen Sie, ob SW mit GPIO27 verbunden ist.
Stellen Sie sicher, dass der Pin mit
pull=Pin.PULL_UPkonfiguriert ist.
Skript beendet sich sofort
Stellen Sie sicher, dass
pause()aus dem Modulsignalimportiert wurde.Prüfen Sie, ob kein anderer Prozess SPI verwendet.
Probieren Sie es selbst aus
Möchten Sie dieses Projekt erweitern? Probieren Sie folgende Ideen:
Helligkeitssteuerung hinzufügen
Verwenden Sie eine weitere Variable (z. B. Encoder drücken + drehen), um die LED-Helligkeit von 0–255 einzustellen.
Mehrere Anzeigemodi hinzufügen
Drücken Sie den Encoder, um zwischen verschiedenen Modi zu wechseln:
Einfarbig (Standard)
Regenbogenanimation
„Breathing“-Effekt
Color-Wipe-Effekt
Ein-/Ausschalter hinzufügen
Halten Sie die Encodertaste länger gedrückt, um den LED-Ring ein- oder auszuschalten.
Sanftere Farbänderung
Erhöhen Sie
STEPS_PER_CYCLEoder fügen Sie Interpolation hinzu, um besonders flüssige Übergänge zu erzielen.Richtungsanzeige
Lassen Sie eine LED grün leuchten, wenn im Uhrzeigersinn gedreht wird, und rot bei Drehung gegen den Uhrzeigersinn.
Diese kleinen Erweiterungen verwandeln den einfachen „Hue Knob“ in eine vielseitige RGB-Steueroberfläche.