Raspberry Pi Pico: Schütteln erkennen mit dem MPU-6050

Mithilfe eines Raspberry Pi Pico und MPU-6050 soll die Bewegung „Schütteln“ erkannt werden. Hierfür wird der MPU-6050-Sensor eingesetzt, der mit seinem Gyroskop und Beschleunigungssensor präzise Daten liefert, die wir als Bewegung interpretieren können.
Der Raspberry Pi Pico wertet diese Daten aus. Wenn ein Schütteln erkannt wird, leuchtet die Onboard-LED kurz auf, um die Bewegung visuell anzuzeigen.

Weil „Schütteln“ keine kontinuierliche Bewegung ist, arbeiten wir hier nicht mit nur einem Schwellwert bei der Auswertung, sondern mit einer oberen Schwelle zur Schüttelerkennung und einer unteren Schwelle, die den Ruhezustand repräsentiert. Das hilft, Aussetzern vorzubeugen und „anhaltendes Schütteln“ besser zu erkennen.

Zur Erkennung von „Schütteln“ verwenden wir drei Lösungen, die unterschiedlich leistungsfähig sind. Im einen werden die Sensordaten des Gyroskops verwendet, in einem weiteren die des Beschleunigungssensors. Im dritten werden die Sensordaten miteinander kombiniert.

Aufbau und Bauteile

Raspberry Pi Pico: MPU-6050 programmieren

Raspberry Pi Pico MPU-6050
Pin 38 GND GND
Pin 36 VCC +3,3V VCC
Pin 27 GPIO 21 SCL
Pin 26 GPIO 20 SDA

I2C verbinden und programmieren

Schnell und einfach alle Bauteile zusammen bestellen

Programmcode: Lösung mit Gyroskop

Der Programmcode enthält die softwareseitige Ansteuerung des MPU-6050 zum Lesen der Sensordaten des Gyroskops. Wenn der Aufbau zum Zeitpunkt der Messung bewegt wird, leuchtet die Onboard-LED.

# Bibliotheken laden
import machine
import time
import math

# Schwellwerte (Hysterese)
UPPER_THRESHOLD = 100
LOWER_THRESHOLD = 30
shaking = False # Status merken

# Onboard-LED initialisieren
led = machine.Pin('LED', machine.Pin.OUT, value=0)

# MPU-6050 über I2C initialisieren
mpu = machine.I2C(0, scl=machine.Pin(21), sda=machine.Pin(20), freq=100000)
mpu.writeto_mem(0x68, 0x6B, b'\x00') # Wake up MPU-6050

# Funktion: Daten von MPU-6050 lesen
def read_gyro():
    data = mpu.readfrom_mem(0x68, 0x43, 6)
    gx = int.from_bytes(data[0:2], 'big') if data[0] < 0x80 else int.from_bytes(data[0:2], 'big') - 65536
    gy = int.from_bytes(data[2:4], 'big') if data[2] < 0x80 else int.from_bytes(data[2:4], 'big') - 65536
    gz = int.from_bytes(data[4:6], 'big') if data[4] < 0x80 else int.from_bytes(data[4:6], 'big') - 65536
    return gx / 131, gy / 131, gz / 131  # in °/s

# Hauptprogramm: Endlos-Schleife
while True:
    # Sensor-Werte lesen
    gx, gy, gz = read_gyro()
    total = abs(gx) + abs(gy) + abs(gz)
    # Schwellwerte vergleichen
    if not shaking and total > UPPER_THRESHOLD:
        shaking = True
        print(f"{total:.3f}", 'SHAKE', end="\r")
        led.on()
        time.sleep(.5)
    elif shaking and total < LOWER_THRESHOLD:
        shaking = False
        print(f"{total:.3f}", str(shaking), end="        \r")
        led.off()
        #time.sleep(1)
    else:
        print(f"{total:.3f}", str(shaking), end="        \r")
    time.sleep(.1)

Programmcode: Lösung mit Accelerometer

Der Programmcode enthält die softwareseitige Ansteuerung des MPU-6050 zum Lesen der Sensordaten des Beschleunigungssensors. Wenn der Aufbau zum Zeitpunkt der Messung bewegt wird, leuchtet die Onboard-LED.

# Bibliotheken laden
import machine
import time

# Schwellwerte (Hysterese)
UPPER_THRESHOLD = 2.0
LOWER_THRESHOLD = 1.5
shaking = False # Status merken

# Onboard-LED initialisieren
led = machine.Pin('LED', machine.Pin.OUT, value=0)

# MPU-6050 über I2C initialisieren
mpu = machine.I2C(0, scl=machine.Pin(21), sda=machine.Pin(20), freq=100000)
mpu.writeto_mem(0x68, 0x6B, b'\x00') # Wake up MPU-6050

# Funktion: Daten von MPU-6050 lesen
def read_accel():
    data = mpu.readfrom_mem(0x68, 0x3B, 6)
    ax = int.from_bytes(data[0:2], 'big') if data[0] < 0x80 else int.from_bytes(data[0:2], 'big') - 65536
    ay = int.from_bytes(data[2:4], 'big') if data[2] < 0x80 else int.from_bytes(data[2:4], 'big') - 65536
    az = int.from_bytes(data[4:6], 'big') if data[4] < 0x80 else int.from_bytes(data[4:6], 'big') - 65536
    return ax / 16384, ay / 16384, az / 16384  # in g

# Hauptprogramm: Endlos-Schleife
while True:
    # Sensor-Werte lesen
    ax, ay, az = read_accel()
    total = abs(ax) + abs(ay) + abs(az)
    # Schwellwerte vergleichen
    if not shaking and total > UPPER_THRESHOLD:
        shaking = True
        print(f"{total:.3f}", 'SHAKE', end="\r")
        led.on()
        time.sleep(.5)
    elif shaking and total < LOWER_THRESHOLD:
        shaking = False
        print(f"{total:.3f}", '', end="        \r")
        led.off()
        #time.sleep(1) # Unterer Schwellwert herausfinden
    else:
        print(f"{total:.3f}", '', end="        \r")
    time.sleep(.1)

Problem

Wenn der MPU-6050 am Umkehrpunkt einer Schüttelbewegung misst (z. B. ganz links oder rechts am Ende der Schwingung), dann ist die Geschwindigkeit dort Null oder nahezu Null, und die Beschleunigung kann – je nach Timing - auch klein oder scheinbar „normal“ sein. Dann sehen die Messwerte so aus, als ob gerade kein Schütteln stattfindet – obwohl du es deutlich in der Hand spürst.

Programmcode: Lösung mit Kombination aus Accelerometer und Gyroskop

Statt auf die absolute Beschleunigung oder Geschwindigkeit zu schauen, wird in diesem Programmcode, die schnelle Änderung der Bewegung betrachtet. Zusätzlich wird die Schüttelerkennung noch mit dem Gyroskop abgesichert.

# Bibliotheken laden
import machine
import time

# Schwellwerte (Hysterese)
UPPER_THRESHOLD = 0.4
LOWER_THRESHOLD = 0.02
GYRO_THRESHOLD = 300

# Anfangswerte
last_acc_total = 0
shaking = False

# Onboard-LED initialisieren
led = machine.Pin('LED', machine.Pin.OUT, value=0)

# MPU-6050 über I2C initialisieren
mpu = machine.I2C(0, scl=machine.Pin(21), sda=machine.Pin(20), freq=100000)
mpu.writeto_mem(0x68, 0x6B, b'\x00') # Wake up MPU-6050

# Funktion: Daten von MPU-6050 lesen
def read_accel():
    data = mpu.readfrom_mem(0x68, 0x3B, 6)
    ax = int.from_bytes(data[0:2], 'big') if data[0] < 0x80 else int.from_bytes(data[0:2], 'big') - 65536
    ay = int.from_bytes(data[2:4], 'big') if data[2] < 0x80 else int.from_bytes(data[2:4], 'big') - 65536
    az = int.from_bytes(data[4:6], 'big') if data[4] < 0x80 else int.from_bytes(data[4:6], 'big') - 65536
    return ax / 16384, ay / 16384, az / 16384  # in g

def read_gyro():
    data = mpu.readfrom_mem(0x68, 0x43, 6)
    gx = int.from_bytes(data[0:2], 'big') if data[0] < 0x80 else int.from_bytes(data[0:2], 'big') - 65536
    gy = int.from_bytes(data[2:4], 'big') if data[2] < 0x80 else int.from_bytes(data[2:4], 'big') - 65536
    gz = int.from_bytes(data[4:6], 'big') if data[4] < 0x80 else int.from_bytes(data[4:6], 'big') - 65536
    return gx / 131, gy / 131, gz / 131  # in °/s

# Hauptprogramm: Endlos-Schleife
while True:
    # Sensor-Werte lesen
    ax, ay, az = read_accel()
    acc_total = ax * ax + ay * ay + az * az
    delta_acc = abs(acc_total - last_acc_total)
    last_acc_total = acc_total
    
    # Unterstützung vom Gyroskop
    gx, gy, gz = read_gyro()
    gyro_total = int(abs(gx)) + int(abs(gy)) + int(abs(gz))
    
    # Schwellwerte vergleichen
    if delta_acc > UPPER_THRESHOLD or gyro_total > GYRO_THRESHOLD:
        shaking = True
        print(f"{delta_acc:.3f}", gyro_total, 'SHAKE', end="  \r")
        led.on()
        time.sleep(.2)
    elif shaking and delta_acc < LOWER_THRESHOLD:
        shaking = False
        print(f"{delta_acc:.3f}", gyro_total, '', end="        \r")
        led.off()
        #time.sleep(1) # Unterer Schwellwert herausfinden
    else:
        print(f"{delta_acc:.3f}", gyro_total, '', end="        \r")
    time.sleep(.01)

Lösung mit KI?

Nicht zu frieden mit der Erkennungsleistung? Vielleicht klappt es besser mit künstlicher Intelligenz (KI). Zeichne die Schüttelbewegung auf. Trainiere mit den Daten ein neuronales Netz und führe an Live-Daten die Bewegungsklassifizierung durch. Und das alles auf dem Raspberry Pi Pico mit dem selben Aufbau.

Weitere verwandte Themen:

Frag Elektronik-Kompendium.de

Hardware-nahes Programmieren mit dem Raspberry Pi Pico und MicroPython

Elektronik-Set Pico Edition

Das Elektronik-Set Pico Edition ist ein Bauteile-Sortiment mit Anleitung zum Experimentieren und Programmieren mit MicroPython.

  • LED: Einschalten, ausschalten, blinken und Helligkeit steuern
  • Taster: Entprellen und Zustände anzeigen
  • LED mit Taster einschalten und ausschalten
  • Ampel- und Lauflicht-Steuerung
  • Elektronischer Würfel
  • Eigene Steuerungen programmieren

Elektronik-Set jetzt bestellen Online-Workshop buchen

Online-Workshop: Programmieren mit dem Raspberry Pi Pico

Programmieren mit dem Raspberry Pi Pico

Gemeinsam mit anderen und unter Anleitung experimentieren? Wir bieten unterschiedliche Online-Workshops zum Raspberry Pi Pico und MicroPython an. Einführung in die Programmierung, Sensoren programmieren und kalibrieren, sowie Internet of Things und Smart Home über WLAN und MQTT.

Online-Workshop buchen

Besuchen Sie unser fast monatlich stattfindendes Online-Meeting PicoTalk und lernen Sie uns kennen. Die Teilnahme ist kostenfrei.

Termine und Newsletter-Anmeldung

 

Elektronik-Sets für das Hardware-nahe Programmieren