TigerJython4Kids
HomeTurtlegrafikRobotikDatenbanken
gpio

1. DIGITALE EIN-/AUSGÄNGE (GPIO)

 

 

DU LERNST HIER...

 

wie du einfache Aktoren ansteuerst, die nur ein- und ausgeschaltet werden, die also nur die digitalen Zustände 1 (HIGH) oder 0 (LOW) kennen.  Du lernst auch, digitale Sensoren auszulesen, die  nur zwei Zustände 1 oder 0 haben, das heisst  eine Spannung oder  keine Spannung abgeben.


 

DIGITALER AUSGANG

 

So wie fast jeder Programmierlehrgang mit dem Ausschreiben von "Hello World" beginnt, ist das klassische Einsteigerprogramm für Mikrocontroller eine blinkende LED. Dazu musst du eine LED über einen Vorwiderstand von einigen hundert Ohm an den IO-Port anschliessen, wobei die Polarität der LED wichtig ist. Ist sie verkehrt eingesteckt, so wird sie nicht beschädigt, sondern blinkt nicht.

Der Widerstand dient der Strombegrenzung (bei Miniatur-LEDs auf rund 1mA, bei normalen  LEDs auf rund 10 mA).

Im Programm definierst du zuerst ein Objekt p der Klasse Pin, wobei du angibst, welchen IO-Port du verwendest und dass es sich um einen Ausgang handelt. Eine logische 1 (also eine Spannung von 3.3V = VCC) setzt du mit p.value(1), eine logische 0 (also 0V = GND) mit p.value(0). Nach dem Setzen des Ports bleibt der Zustand erhalten, bis du einen anderen Wert auf den Port schreibst.

 

Programm:


Warning: include(bsp/Gpio1.html): failed to open stream: No such file or directory in /usr/share/nginx/html/robotik/iot/gpio.inc.php on line 53

Warning: include(): Failed opening 'bsp/Gpio1.html' for inclusion (include_path='.:/usr/local/lib/php') in /usr/share/nginx/html/robotik/iot/gpio.inc.php on line 53
► In Zwischenablage kopieren

 

Statt einer LED kannst du auch eine aktiven 3.3V-Buzzer anschliessen und damit lustige Tonfolgen (bei fester Tonhöhe) erzeugen. Auch hier musst du auf die Polarität achten. Mit folgendem Programm ertönt ein Morse-Signal.

 

Programm:

from machine import Pin
from time import sleep

P_BUZZER = 5 # adapt to your wiring
dt = 0.1     # adapt to your Morse speed

morse = {
'a':'.-'   , 'b':'-...' , 'c':'-.-.' , 'd':'-..'  , 'e':'.'    ,
'f':'..-.' , 'g':'--.'  , 'h':'....' , 'i':'..'   , 'j':'.---' ,
'k':'-.-'  , 'l':'.-..' , 'm':'--'   , 'n':'-.'   , 'o':'---'  ,
'p':'.--.' , 'q':'--.-' , 'r':'.-.'  , 's':'...'  , 't':'-'    ,
'u':'..-'  , 'v':'...-' , 'w':'.--'  , 'x':'-..-' , 'y':'-.--' ,
'z':'--..' , '1':'.----', '2':'..---', '3':'...--', '4':'....-',
'5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.',
'0':'-----', '-':'-....-', '?':'..--..', ',':'--..--', ':':'---...',
'=':'-...-'}

def s(n):  # wait
    sleep(n * dt)

def dot():
    p.value(1)
    s(1)
    p.value(0)
    s(1)

def dash():
    p.value(1)
    s(3)
    p.value(0)
    s(1)

def transmit(text):
    for c in text:
        if c == " ":
            s(4)
        else:
            c = c.lower()
            if c in morse:
                k = morse[c]
                for x in k:
                    if x == '.':
                        dot()
                    else:
                        dash()
            s(2)

p = Pin(P_BUZZER, Pin.OUT)
transmit("cq de hb9abh pse k")
► In Zwischenablage kopieren


 

DIGITALER EINGANG

 

Ein digitaler Eingang detektiert logische Pegel 0 (LOW, GND, ca. 0V) und 1 (HIGH, VCC, ca. 3.3V).

 

 

Statt eine externe Spannung zu verwenden (die nie höher als 3.3V sein darf) erzeugst du eine 1 so, dass du mit einem Widerstand den Port auf VCC "hoch ziehst".

Einen solchen Widerstand nennt man daher "Pullup". Eine logische 0, also 0V, kannst du so anlegen, dass du den Port mit einer gedrückten Taste mit GND verbindest ("hinunter ziehst").

Ein externer Pullup kann entfallen, da du im Programm einen internen Pullup aktivieren kannst.

In deinem Programm willst du beim Drücken des Buttons alle LEDs des Displays von rot auf  grün schalten. Dazu erzeugt du wie oben ein Pin-Objekt p, wobei du angibst, dass es sich um einen Eingang handelt und ein interner Pullup aktiviert werden soll. Die Methode value() (ohne Parameter) liefert den aktuellen Zustand des Pins als 0 oder 1.

 

Programm:

from oxocard import *
from machine import Pin
from time import sleep

P_BUTTON = 5
p = Pin(P_BUTTON, Pin.IN, Pin.PULL_UP)    
while True:
    v = p.value()  # 1: released, 0: pressed
    if v == 0:
        clear(GREEN)
    else:
        clear(RED)
► In Zwischenablage kopieren

Beim Button kann es sich um einen Berührungssensor handeln, der in  einer Anlage eingebaut ist und durch irgendeine mechanische Betätigung ausgelöst wird, aber auch um einen Schalter, der ein- oder ausgeschaltet ist.

Achtung: Die Eingänge sind ungeschützt und eine Spannung grösser als 3.3 V oder eine negative Spannung  (falsche Polarität) zerstören den Mikrocontroller!


 

PIR-SENSOR AM DIGITALEN EINGANG

 

Der Pyroelektrische Infrarot-Sensor (PIR) verwendet die Eigenschaft einiger Halbleiter, dass eine Temperaturänderung zu einer elektrischen Spannung führt. Da Lebewesen eine Temperaturstrahlung im Infrarot-Bereich abgeben, können PIR-Sensoren die Bewegung von Lebewesen im Bereich von bis zu einigen Metern detektieren. Sie werden vor allem in Alarmanlagen eingesetzt.

  Der PIR wird normalerweise auf einem Breakout-Board mit einer Elektronik verbaut, die bei Bewegung ein digitales Signal HIGH abgibt, das nach kurzer Zeit wieder auf LOW geht, falls keine Bewegung mehr stattfindet.


Es gibt verschiedene Bauformen. Hier wird der Sensor von Seed verwendet, der einen (analogen) Grove-Stecker hat.

Über eBay kann man einen sehr preisgünstigen Sensor beschaffen, der wie folgt angeschlossen wird:

 

 

Es werden nur die 3 Kabelverbindungen GND (schwarz), VDD (rot) und Signal (gelb) benötigt, die du mit den entsprechenden GPIO-Buchsen der Oxocard verbindest.

 

Als Anwendung schreibst du ein Programm für eine Alarmanlage. Ohne Alarm sind alle LEDs des Displays grün. Wird ein Objekt detektiert, so färbst du den Display rot und erzeugst im angeschlossenen Lautsprecher ein Warnsignal.

 

Programm:

from oxocard import *
from machine import Pin
from music import playTone

def alert():
    playTone(1500, 200)
    playTone(2000, 200)

P_PIR = 19
p = Pin(P_PIR, Pin.IN, Pin.PULL_UP)    
while True:
    v = p.value() 
    if v == 0:
        clear(GREEN)
    else:
        clear(RED)
        alert()
► In Zwischenablage kopieren

 

 

MERKE DIR...

 

Digitale Ein- und Ausgangsports (GPIO) stellen das einfachste Interface eines Mikrocontrollers mit seiner Umwelt dar. Ein bestimmter Port wird softwaremässig als Input oder Output definiert. Als Output musst du darauf achten, dass der Port einen maximalen Strom von 40 mA liefern kann (sowohl beim Ziehen auf GND oder VCC). Als Input kannst du einen internen Pullup, ein Pulldown oder einen hochohmigen Eingang definieren..

 

 

ZUM SELBST LÖSEN

 

 

1.

ToDo

 
 
 


 

ZUSATZSTOFF: ZUSTANDSPROGRAMMIERUNG, SCHALTERPRELLEN

 

Du willst ein Programm schreiben, das beim Drücken des Buttons eine Lichtquelle, hier das Pixel in der Mitte des LED-Displays, einschaltet und beim nächsten Drücken wieder ausschaltet. Da du die LED von hell auf dunkel und wieder zurück "umschaltest",  ist es sinnvoll, dazu die Funktion toggle() zu definieren.

def toggle():
    if getColor(3, 3) == BLACK:
        dot(3, 3, WHITE)
    else:
        dot(3, 3, BLACK)

Das Problem hat aber seine Tücken, denn du kannst nicht einfach in einer Schleife testen, ob der Button gedrückt ist und dann die LED umschalten. Beim nächsten Schleifendurchgang würde das Licht sofort wieder erneut umgeschaltet.

Du darfst also das Umschalten der LED nur dann ausführen, wenn der Button in der Zwischenzeit wieder losgelassen wurde. Dazu führst du  eine "Zustandsvariable" state ein, die den Wert "PRESSED" bzw. "RELEASED" hat. Nur wenn der Zustand auf PRESSED geht, schaltest du die LED um.

Programm:

from oxocard import *
from machine import Pin
from time import sleep

def toggle():
    if getColor(3, 3) == BLACK:
        dot(3, 3, WHITE)
    else:
        dot(3, 3, BLACK)

P_BUTTON = 5
p = Pin(P_BUTTON, Pin.IN, Pin.PULL_UP)    
state = "RELEASED"

while True:
    v = p.value()  # 0: pressed
    if v == 0 and state == "RELEASED":
        state = "PRESSED"
        toggle()
        
    if v == 1 and state == "PRESSED":
        state = "RELEASED"       
► In Zwischenablage kopieren

Trotz deinen Anstrengungen benimmt sich das Programm leider nicht bei jeder Betätigung korrekt. Manchmal geht die LED beim Drücken des Buttons gerade wieder in den vorhergehenden Zustand zurück. Das Fehlverhalten ist nicht reproduzierbar und tritt nur sporadisch auf. Wir haben es mit einem ganz schlimmen Programmierfehler zu tun! Wie ist der Fehler zu erklären?

Beim Schliessen des Schalters drückt man zwei mechanische Kontakte zusammen und erstellt damit eine leitende elektrische Verbindung zwischen den Kontakten.

Wenn du beim Drücken keine allzu grosse Kraft anwendet, kann sich der Kontakt für eine kurze Zeit wieder öffnen, bis er endgültig geschlossen wird. So kann passieren, dass der Schalter zweimal (oder mehrmals) kurz hintereinander geschlossen und wieder geöffnet wird, bis er wirklich geschlossen bleibt.  

Das Gleiche kann sich beim Loslassen ereignen: Der Kontakt öffnet und schliesst mehrere Male kurz hintereinander. Dieser Effekt, der als Schalterprellen bezeichnet wird, bewirkt bei Anwendungen, bei denen die Anzahl der Schliess- oder Öffnungsoperationen eine Rolle spielt, unvorhersehbare Resultate.

Wir beseitigen das Problem gemäss folgender Idee: Nach dem Erfassen des ersten Press-Ereignis unterbindest du die sofortige Abfrage des Tastenzustands während einer kurzen Zeit, indem du ein Sleep() einbaust. Damit haben die in dieser Zeit auftretenden "Preller" keine Auswirkungen. Dasselbe machst du beim Release-Ereignis.

Das gewählte Zeitintervall für Sleep() ist kritisch, da du bei zu langen Wartezeiten kurz dauernde Tastenklicks nicht mehr erfasst und bei zu kurzen die Taste prellt.

Programm:

from oxocard import *
from machine import Pin
from time import sleep

def toggle():
    if getColor(3, 3) == BLACK:
        dot(3, 3, WHITE)
    else:
        dot(3, 3, BLACK)

P_BUTTON = 5
p = Pin(P_BUTTON, Pin.IN, Pin.PULL_UP)    
state = "RELEASED"

while True:
    v = p.value()  # 0: pressed
    if v == 0 and state == "RELEASED":
        state = "PRESSED"
        toggle()
        sleep(0.05)                
        
    if v == 1 and state == "PRESSED":
        state = "RELEASED"
        sleep(0.05)                
► In Zwischenablage kopieren