Beetje Coderen

Les 5

Knoppen en sensoren

Digitale ingangen uitlezen: een knop met een interne pull-up, contactdender opvangen en een digitale sensor zoals een PIR-bewegingsmelder gebruiken.

โฑ 45 minuten leestijd + oefenen

๐ŸŽฏ Na deze les kun je

  • een pin als ingang instellen en uitlezen
  • uitleggen waarom een ingang een pull-up of pull-down nodig heeft
  • contactdender herkennen en opvangen
  • een digitale sensor (PIR-bewegingsmelder) uitlezen

Een LED aansturen is uitvoer. Nu de andere kant op: de chip laten meten of er iets gebeurt. De eenvoudigste ingang is een drukknop; daarna een bewegingsmelder die precies hetzelfde signaal geeft: hoog of laag.

Een pin als ingang

from machine import Pin
knop = Pin(14, Pin.IN, Pin.PULL_UP)
print(knop.value())   # 1 = niet ingedrukt, 0 = ingedrukt

Waarom een pull-up?

Een ingang zonder iets erop aangesloten "zweeft": hij vangt storing op en leest willekeurig 0 of 1. Daarom trek je hem met een weerstand naar een vaste waarde:

3,3 V
  โ”‚
 [pull-up, intern ~50 kฮฉ]
  โ”‚
GP14 โ”€โ”€โ”€โ”€โ”€โ”€โ”
           โ”‚  knop
GND โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Knop los: de pull-up trekt de pin naar 3,3 V โ†’ 1.
  • Knop ingedrukt: de pin is direct met GND verbonden โ†’ 0.

Dat "ingedrukt = 0" heet actief laag. Het voelt omgekeerd, maar het is de meest gebruikte schakeling, omdat de knop alleen naar GND hoeft en de interne pull-up gratis is. Pin.PULL_DOWN bestaat ook (knop naar 3,3 V, ingedrukt = 1), maar de ESP32 heeft op sommige pinnen geen interne pull-down, en pinnen 34โ€“39 van de ESP32 hebben helemaal geen interne weerstanden.

Om de rest van je code leesbaar te houden:

def ingedrukt():
    return knop.value() == 0

Knop schakelt LED

from machine import Pin
import time

knop = Pin(14, Pin.IN, Pin.PULL_UP)
led = Pin(15, Pin.OUT)

while True:
    led.value(knop.value() == 0)   # LED aan zolang de knop ingedrukt is
    time.sleep_ms(10)

Contactdender

Nu wil je dat elke druk de LED omschakelt. Een eerste poging: kijk of de knop net is ingedrukt (hij was 1 en is nu 0).

vorige = 1
while True:
    nu = knop.value()
    if vorige == 1 and nu == 0:
        led.toggle()
    vorige = nu

Probeer het: soms schakelt de LED twee of drie keer per druk. Oorzaak: contactdender (bounce). De metalen contacten in de knop stuiteren een paar milliseconden, en de chip is zo snel dat hij elke stuiter als een aparte druk ziet:

ingedrukt:  1 1 1 0 1 0 0 1 0 0 0 0 0 0 0
                  โ”” 1โ€“10 ms dender โ”˜

De eenvoudigste oplossing: na een gedetecteerde verandering even wachten, en dan pas weer kijken.

from machine import Pin
import time

knop = Pin(14, Pin.IN, Pin.PULL_UP)
led = Pin(15, Pin.OUT)
vorige = 1

while True:
    nu = knop.value()
    if vorige == 1 and nu == 0:
        led.toggle()
        time.sleep_ms(30)      # dender laten uitsterven
    vorige = nu
    time.sleep_ms(5)

Een nettere manier zonder blokkerend wachten zie je in les 8 en 14.

Een digitale sensor: PIR

Een PIR-sensor (bijvoorbeeld de HC-SR501) meet infraroodstraling van warme lichamen en geeft een digitaal signaal: hoog zolang er beweging is gezien. Gebruik een versie die 3,3 V als uitgang geeft (de HC-SR501 doet dat, ook al voed je hem met 5 V; controleer het voor jouw module).

from machine import Pin
import time

pir = Pin(16, Pin.IN)       # de sensor stuurt zelf actief hoog of laag
led = Pin(15, Pin.OUT)

while True:
    if pir.value():
        led.on()
        print("beweging!")
    else:
        led.off()
    time.sleep_ms(200)

Geen pull-up nodig: de sensor maakt de pin zelf hoog of laag. Een PIR heeft na het aanzetten zo'n 30 tot 60 seconden nodig om te stabiliseren; in die tijd geeft hij soms valse meldingen.

Andere sensoren met een digitaal aan/uit-signaal: een reed-contact (magneet bij een deur), een kantelschakelaar, een vochtigheidssensor met drempelmodule.

Typische fouten

  • Ingang zonder pull-up en een knop naar GND: willekeurige waardes als de knop los is.
  • Verwachten dat ingedrukt 1 is bij een pull-up-schakeling.
  • Knop dubbel geteld door dender.
  • Een 5V-sensoruitgang rechtstreeks op de pin (les 4).

Oefeningen

  1. Waarom leest een pin met pull-up 1 als de knop niet is ingedrukt?
  2. Schrijf een programma dat telt hoe vaak de knop is ingedrukt en de teller print.
  3. Laat de LED na een bewegingsmelding nog 5 seconden aan blijven, ook als de PIR alweer laag is.
Modelantwoord
  1. De pull-up-weerstand verbindt de pin met 3,3 V. Zolang de knop open is, loopt er (vrijwel) geen stroom en staat er dus 3,3 V op de pin.
  2. teller = 0
    vorige = 1
    while True:
        nu = knop.value()
        if vorige == 1 and nu == 0:
            teller += 1
            print(teller)
            time.sleep_ms(30)
        vorige = nu
        time.sleep_ms(5)
    
  3. laatste = None
    while True:
        if pir.value():
            laatste = time.ticks_ms()
        aan = laatste is not None and time.ticks_diff(time.ticks_ms(), laatste) < 5000
        led.value(aan)
        time.sleep_ms(100)
    
    time.ticks_ms() en ticks_diff zijn de juiste manier om tijd te meten op MicroPython; ze gaan goed om met het overlopen van de teller.

Lab: knop schakelt LED en bewegingsmelder

  1. Elke druk op de knop (GP14, naar GND) schakelt de LED op GP15 om, zonder dubbeltellingen.
  2. Een PIR op GP16 zet een tweede LED (GP17) aan, die nog 3 seconden na de laatste beweging blijft branden.
  3. beetje check micropython-les05 simuleert knopdrukken met dender en bewegingen.

Samenvatting

  • Pin(n, Pin.IN, Pin.PULL_UP): ingang met interne pull-up; ingedrukt = 0.
  • Een zwevende ingang geeft willekeurige waarden.
  • Contactdender: een knop stuitert enkele milliseconden; wacht even na een verandering.
  • Digitale sensoren geven zelf hoog/laag; meet tijd met ticks_ms en ticks_diff.

Volgende les: sensoren die geen 0 of 1 geven, maar een waarde ertussen.

Lab

Knop schakelt LED en bewegingsmelder

๐Ÿ’ป Dit lab doe je op je eigen computer met Docker. Start de lab-container met (geeft de opdracht een eigen startcommando, gebruik dan dat):

$ docker run -it --rm registry.wizg.it/webhosting/beetje-labs:micropython-les5

Volg daarna de stappen van de opdracht hierboven. Nog geen Docker? Zie les 14 van Een beetje Linux & Docker. Voor dit lab is er geen live lab in de browser.

Klaar? Controleer je werk met:

$ beetje check micropython-les5

๐Ÿ“ Quiz: knoppen en sensoren

5 vragen ยท 70% nodig om te slagen

1. Een knop zit tussen GP14 en GND, met Pin.PULL_UP. Wat lees je als hij ingedrukt is?
2. Wat gebeurt er met een ingang zonder pull-up of pull-down en zonder aangesloten signaal?
3. Wat is contactdender?
4. Hoe meet je in MicroPython hoeveel tijd er verstreken is?
5. Heeft een PIR-sensoruitgang een pull-up nodig?

Dit was de laatste gratis les

Je hebt les 1โ€“5 van Een beetje MicroPython gratis gevolgd. Wil je verder? Met รฉรฉn aankoop (€ 24,00, eenmalig) krijg je de overige 15 lessen, de live labs en het certificaat. Geen abonnement.

Cursus kopen en verdergaan