Poti

Dieses Lab zeigt Ihnen wie sie die wechselnde Spannung von einem Potentiometer als User Input nutzen können.

Vorkenntnisse:

Ziel:

  • Poti verbinden
  • ADC nutzen um Spannung zu messen.
  • Wertebereich umrechnen.

Das Potentiometer

Potentiometer1

Ein Potentiometer wirkt wie ein verstellbarer Spannungsteiler, der die Spannung zwischen GND und VCC in Abhängigkeit von der Position des Schleifkontakts teilt. Durch Drehen des Potentiometers kann die Ausgangsspannung stufenlos verändert und an verschiedene Anforderungen angepasst werden

Aufbau

Aufbau Poti

Task

Bauen Sie die abgebildete Schaltung auf. (Wokwi)

Analog Digital Wandler

Zuerst müssen wir die Klasse ADC aus dem Modul machine importieren.

from machine import ADC

Der Konstruktor benötigt nur die Pin nummer.

from machine import ADC
adc = ADC(32)

Warning

Nicht jeder beliebige Pin kann als ADC verwendet werden. Welche Pins als ADC genutzt werden können steht im Pinout oder im Datenblatt des entprechenden Microcontrollers.

ADC-Block 2 wird auch von WiFi verwendet. Der Versuch, Analogwerte von den Pins des Blocks 2 zu lesen, wenn WiFi aktiv ist, führt daher zu einer Exception.

Der ADC bietet uns zwei verschieden Methoden um den aktuellen Wert am Pin zu lesen.

from machine import ADC
adc = ADC(32)
value = adc.read_u16() # Wert zwischen 0 und 2^16
microvolts = adc.read_uv()  # Wert in microvolts

Warning

Die interne ADC-Referenzspannung beträgt typischerweise 1,1 V und hat eine minimale Messspannung um 100mV, Spannungen <= diesem Wert werden als 0 gelesen.

Task

Schreiben Sie ein Program welches den Wert vom Poti einliest und jede Sekunde den aktuellen Wert über die serielle Schnittstelle wieder ausgibt.

Solution

from machine import ADC
from time import sleep

poti = ADC(32)

while True:
    value = poti.read_u16()
    print(f"Aktueller Wert: {value}")
    sleep(1)

Task

Schreiben Sie ein Program welches es ermöglicht eine LED über den Poti ein und aus zu schalten. Die Grenze soll genau in der Mitte des Wertebereichs liegen.

Solution

from machine import ADC, Pin

poti = ADC(32)
led = Pin(27, Pin.OUT)

while True:
    value = poti.read_u16()
    # Hälfte von 2¹⁶ = 32768
    if value > 32768:
        led.on()
    else:
        led.off()

Messbereich auf Steuerungsbereich mappen

Ein häufiges Problem im Zusammenhang mit dem Einlesen analoger Werte ist das Umrechnen dieser Werte in einen anderen Wertebereich. Als Beispiel soll mit einem Potentiometer eine LED gedimmt werden. Wir haben nun gesehen, dass wir Werte zwischen 0 und 2^16 einlesen können. Zum Dimmen der LED benötigen wir nun einen Wertebereich zwischen 0 und 255.

Der gewünschte Wertebereich hat also 256 Schritte. Wir müssen nun also den ursprünglichen Bereich in 256 Schritte unterteilen.

UrsprungsbereichZielbereich
0 - 2550
256 - 5121
513 - 7682
......
65024 - 65279254
65280 - 65535255

Foglende Formel kann für die Umrechnung genutzt werden: Dabei ist der Ursprungsbereich und der Zielwertebereich.

Schritt für Schritt Erklärung

  1. Normalisierung auf den Bereich Hier wird der Eingabewert relativ zu seinem Ursprungsbereich skaliert.
  2. Skalierung auf den Zielbereich: Das Ergebnis der Normalisierung wird mit der Größe des Zielbereichs multipliziert.
  3. Verschiebung in den Zielbereich: Schließlich wird das Ergebnis an den Startpunkt (min_out) des Zielbereichs angepasst.

Beispiel

Sie wollen den Wert 30 aus dem Wertebereich in den Zielbereich umrechnen.

  1. Normalisierung auf den Bereich

  2. Skalierung auf den Zielbereich: Hinweis: Beginnt der Zielbereich bei wären wir schon fertig.

  3. Verschiebung in den Zielbereich:

Das Ergebnis ist

Task

👉 Schreiben Sie eine Funktion map(value, min_in, max_in, min_out, max_out) welche diese in Code umsetzt.

Hinweis: Achten Sie darauf, dass sie nicht durch NULL teilen dürfen.

Tip

Testen Sie ihre Funktion z.B mit folgenden Werten:

ValueExpected Output
65279254,99609375
65280255

Solution

def map(value, min_in, max_in, min_out, max_out):
    if min_in == max_in:
        raise ValueError("Der Eingabebereich darf nicht null sein.")
    return (value - min_in)/(max_in - min_in) * (max_out - min_out) + min_out

Diese Funktion gibt einen float zurück. Oft brauchen wir jedoch nur den ganzzahligen Anteil (int) zum weiterrechnen. Dies können Sie zum Beispiel durch eine Typumwandlung int(output) oder eine Integer Division output//1 erreichen.

Übungsaufgaben

  1. Schreiben Sie ein Program, dass den Poti nutzt um 3 Zustände (AUS, AN, BLINKEN) einer LED auszuwählen.

  2. Schreiben Sie ein Program, dass die Blinkfrequenz einer LED über einen Poti einstellbar macht.

  3. Bauen Sie einen Spannungsteiler aus 220 Ω und 1kΩ auf. Berechnen Sie den Wert welcher vom ADC eingelesen wird und überprüfen Sie dies mit einem kleinen Program nach. Analysieren Sie mögliche Abweichungen des Messwertes von dem theoretischen Ergebnis.

  4. Der Ladestand eines Akkus soll über 5 LEDs optisch dargestellt werden. Nutzen Sie einen Poti um die Spannung des Akkus zu simulieren. Programmieren Sie Ihre Schaltung so, dass proportional zur Stellung des Potentiometers die Anzahl der leuchtenden LEDs variiert. Nutzen Sie die eine for-Schleife.

  5. Begründen Sie warum Sie einen 9V Akku nicht einfach an den ADC Pin anschließen dürfen. Skizzieren Sie anschließend eine mögliche Lösung um den Akkustand trotzdem zu messen.

  6. Werte, die über einen analogen Eingang eingelesen wurden, sollen auf dem seriellen Monitor mit einer Art Balkenanzeige dargestellt werden. Je größer der eingelesen Wert, desto mehr > werden dargestellt. Die Balkenanzeige soll 25 Balken haben und das Maximum wird durch | angezeigt. Mit einem angeschlossenen Potentiometer soll die Balkenanzeige gesteuert werden.2

Resources