Med Raspberry Pi GPIO og Python tenner du en LED, leser en knapp og registrerer bevegelse med noen få linjer kode. Biblioteket gpiozero følger med Raspberry Pi OS, bruker GPIO-numrene (BCM) og virker på Raspberry Pi 5, der RPi.GPIO ikke gjør det. Du går fra en blinkende LED til et lite sensordashbord i nettleseren, med fysiske pinnenumre og koblingsskjema for kretsene.
python3 filnavn.py. I gpiozero betyr LED(17) GPIO17, som sitter på fysisk pinne 11. På Raspberry Pi 5 virker gpiozero med pinnedriveren lgpio, mens biblioteket RPi.GPIO ikke virker. Eldre kode skrevet for RPi.GPIO må skrives om eller kjøres med kompatibilitetspakken rpi-lgpio.Slik er GPIO-pinnene på Raspberry Pi ordnet
Raspberry Pi 5, 4 og de andre kortene i full størrelse har en GPIO-kontakt med 40 pinner i to rader på 20, med 2,54 mm avstand. Utformingen er den samme på Raspberry Pi B+ og nyere modeller og på alle Zero-modeller. Holder du kortet med komponentsiden opp og GPIO-kontakten langs øvre kant, sitter pinne 1 nederst til venstre i kontakten og pinne 40 øverst til høyre. På Raspberry Pi 5 og 4 vender USB- og nettverkskontaktene da mot høyre. Oddetallspinnene (1, 3, 5 og så videre) ligger i den indre raden, partallspinnene (2, 4, 6 og så videre) i raden langs kanten.
Pinnene har to nummersystemer. Det fysiske nummeret (1 til 40) forteller hvor pinnen sitter. GPIO-nummeret, også kalt BCM-nummer, er det koden bruker. GPIO17 sitter for eksempel på fysisk pinne 11. Skriv pinout i terminalen, så viser Raspberry Pi OS et kart over kontakten for akkurat ditt kort.
| Fysisk pinne | Navn | I koden | Brukes til |
|---|---|---|---|
| 2 | 5V | (strøm) | Strøm til PIR-sensoren, nivå 2 og 3 |
| 6 | GND | (jord) | Jord for PIR-sensoren |
| 7 | GPIO4 | MotionSensor(4) | Signal fra PIR-sensoren |
| 9 | GND | (jord) | Jord for LED-en |
| 11 | GPIO17 | LED(17) | Styrer LED-en |
| 13 | GPIO27 | Button(27) | Leser knappen |
| 14 | GND | (jord) | Jord for knappen |
En GPIO-pinne som er satt som utgang, gir 3,3 V (høy) eller 0 V (lav). Når pinnen er en inngang, leses 3,3 V som høy og 0 V som lav. Én pinne kan levere opptil 16 mA, og alle GPIO-pinnene til sammen høyst 50 mA. Det holder til LED-er og signaler, men ikke til motorer: de trenger en motordriver.
Raspberry Pi 5 og gpiozero: hvorfor RPi.GPIO ikke virker
På Raspberry Pi 5 går GPIO-pinnene via RP1, en egen I/O-kontroller fra Raspberry Pi som også styrer USB, Ethernet og andre grensesnitt. Derfor virker ikke alle eldre GPIO-biblioteker lenger. gpiozero velger lgpio som pinnedriver når den er installert, og ifølge gpiozero-dokumentasjonen er lgpio den eneste av bibliotekets pinnedrivere som virker på Pi 5.
| Pinnedriver i gpiozero | Raspberry Pi 5 | Pi 4 og eldre | Merknad |
|---|---|---|---|
| lgpio | Ja | Ja | Førstevalget, brukes i hele guiden |
| rpigpio (RPi.GPIO) | Nei | Ja | Var standard i eldre versjoner |
| pigpio | Nei | Ja | Brukes blant annet til fjernstyrt GPIO |
| native | Nei | Ja | Siste reserve, uten PWM |
Kode fra eldre guider med import RPi.GPIO as GPIO kan skrives om: gpiozero-dokumentasjonen har et eget kapittel om overgangen. gpiozero er forhåndsinstallert i Raspberry Pi OS, også i Lite-utgaven.
Slik lager og kjører du et Python-program
- Åpne Thonny fra Raspberry Pi-menyen under Programming. Thonny følger med Raspberry Pi OS med skrivebord.
- Lag en fil: klikk New, skriv eller lim inn koden og lagre med Save, for eksempel som
blink.pyi en mappe som hetergpioi hjemmemappen din. - Kjør: klikk Run eller trykk F5. Det programmet skriver ut med
print(), vises i Shell-feltet nederst. - Stopp: klikk Stop før du kobler om eller starter et annet program som bruker de samme pinnene.
Foretrekker du terminalen, lager du mappen og filen slik. I nano lagrer du med Ctrl+O og avslutter med Ctrl+X. Programmet kjører til du trykker Ctrl+C.
mkdir -p ~/gpio
cd ~/gpio
nano blink.py
python3 blink.py
Et Python-program avsluttes når det når siste linje, og da slipper gpiozero pinnene. Programmer som skal vente på knapper eller sensorer, slutter derfor med pause() fra modulen signal. Bare ett program kan bruke en pinne om gangen: får du feilmeldingen GPIO busy, bruker et annet program fortsatt pinnen.
Nivå 1: LED og knapp med gpiozero
Har du ikke satt opp kortet ennå, viser guiden om Raspberry Pi 5-startsett hva du trenger av strøm, kjøling og minnekort.
1. Koble til
- Slå av Raspberry Pi og trekk ut strømkabelen.
- Sett 330 Ω-motstanden (oransje-oransje-brun) fra hull c11 til c15. De fem hullene a til e i samme kolonne er koblet sammen.
- Sett LED-en med det lange beinet (anode, +) i d11 og det korte beinet (katode, −) i d10.
- Sett trykknappen over midtsporet med to bein i kolonne 20 og to i kolonne 22. En 6 × 6 mm-knapp står i hullene e20, e22, f20 og f22. En 12 × 12 mm-knapp, som i komponentsettet, står i d20, d22, g20 og g22. Ledningene til a20 og j22 er de samme i begge tilfeller.
- Koble ledningene med hunn-enden på Raspberry Pi og hann-enden i koblingsbrettet: fysisk pinne 11 (GPIO17) til a15, pinne 9 (GND) til a10, pinne 13 (GPIO27) til a20 og pinne 14 (GND) til j22.
- Sjekk strømveien før du slår på: GPIO17, motstand, langt bein, LED, kort bein, GND. Knappen ligger mellom GPIO27 og GND, og de to ledningene går til diagonalt motsatte bein.
| Fra | Til | Hvorfor |
|---|---|---|
| Pinne 11 (GPIO17) | a15 | Styresignalet til LED-en |
| Motstand 330 Ω | c11 til c15 | Begrenser strømmen |
| LED, langt bein (+) | d11 | Anoden mot motstanden |
| LED, kort bein (−) | d10 | Katoden mot jord |
| Pinne 9 (GND) | a10 | Strømmen tilbake til kortet |
| Pinne 13 (GPIO27) | a20 | Leser knappen |
| Pinne 14 (GND) | j22 | Jord til det diagonalt motsatte beinet |
Med en rød LED med rundt 2,0 V spenningsfall blir strømmen (3,3 V − 2,0 V) / 330 Ω ≈ 4 mA, godt under grensen på 16 mA per pinne. Har du LED-settet med 1 kΩ-motstander, virker kretsen også, men LED-en lyser svakere. Knappen trenger ingen egen motstand: gpiozero slår på en intern pull-up-motstand mot 3,3 V, så GPIO27 er høy når knappen er sluppet og lav når knappen kobler pinnen til GND. Les mer om motstandsverdier i guiden om motstander.
Bruker du ProtoPi Plus-adapteren fra prototypesettet, kobler du de samme signalene via adapteren. Følg merkingen på adapteren og kontroller den mot pinout.
2. Blink LED-en
Dette er eksempelet fra Raspberry Pis egen dokumentasjon. Lagre det som blink.py og kjør det.
from gpiozero import LED
from time import sleep
led = LED(17)
while True:
led.on()
sleep(1)
led.off()
sleep(1)
LED(17)bruker GPIO-nummeret, ikke det fysiske nummeret.LED("BOARD11")betyr det samme hvis du heller vil skrive det fysiske nummeret.while True:gjentar løkken til du stopper programmet, ogsleep(1)venter ett sekund.
3. Styr LED-en med knappen
from gpiozero import LED, Button
from signal import pause
led = LED(17)
knapp = Button(27)
knapp.when_pressed = led.on
knapp.when_released = led.off
pause()
Button(27)slår på den interne pull-up-motstanden. Derfor kobles knappen mot GND.knapp.when_pressed = led.onsier hva som skal skje ved trykk. Skrivled.onuten parenteser: medled.on()kjører funksjonen én gang med det samme, og hendelsen får verdienNone.pause()holder programmet i gang, slik at gpiozero kan reagere på knappen.
Prøv selv
- Bytt ut de to
when-linjene medknapp.when_pressed = led.toggle, så slår hvert trykk LED-en av eller på. Skifter den av og til to ganger, demper du prellingen i knappen medButton(27, bounce_time=0.05). - Dim LED-en med pulsbreddemodulasjon (PWM):
PWMLEDlar LED-en lyse gradvis sterkere og svakere.
from gpiozero import PWMLED
from signal import pause
led = PWMLED(17)
led.pulse()
pause()
Hvis det ikke virker
- LED-en lyser ikke: snu LED-en, for det lange beinet skal mot motstanden. Tell pinnene fra pinne 1 med
pinout. - LED-en lyser hele tiden, eller knappen reagerer aldri: kontroller at GPIO27- og GND-ledningen går til diagonalt motsatte bein, eller drei knappen en kvart omdreining.
- Feilmeldingen
GPIO busy: stopp det andre programmet i Thonny eller terminalen først.
Nivå 2: bevegelsessensor som logger til CSV
En PIR-sensor reagerer på endringer i infrarød stråling, for eksempel når et menneske går forbi. HC-SR501 får 5 V i forsyning, men ifølge databladet gir signalutgangen 3,3 V ved bevegelse og 0 V ellers, så OUT kan kobles rett til en GPIO-pinne. Det gjelder ikke alle 5 V-moduler: ultralydsensoren HC-SR04 i prototypesettet sender 5 V tilbake på ECHO og trenger en spenningsdeler.
1. Koble til sensoren
- Slå av Raspberry Pi og trekk ut strømkabelen. La LED-kretsen fra nivå 1 stå.
- Finn merkingen på sensoren: VCC (eller +Power), OUT og GND. Merkingen kan sitte under den hvite linsen, som kan løftes forsiktig av.
- Koble GND på sensoren til fysisk pinne 6 (GND) og OUT til fysisk pinne 7 (GPIO4).
- Koble VCC til fysisk pinne 2 (5V) til slutt, og kontroller at denne ledningen ikke berører noen annen pinne.
- Vri potensiometeret for forsinkelse (Time Delay) helt mot urviseren mens du tester. Sett fra komponentsiden, med pinnene nederst, sitter det til venstre, og potensiometeret for følsomhet (Sensitivity) sitter til høyre. Da holder utgangen seg høy bare noen få sekunder etter hver bevegelse.
- Slå på Raspberry Pi og vent rundt ett minutt. Ifølge databladet trenger sensoren denne tiden etter oppstart og kan gi noen falske utslag i mellomtiden.
Jumperen H/L velger om utgangen holder seg høy så lenge det er bevegelse (H) eller gir én puls (L). Med H blir en person som beveger seg foran sensoren, til én lang hendelse i loggen.
2. Koden
Programmet tenner LED-en ved bevegelse og skriver én linje per hendelse til filen bevegelser.csv: når bevegelsen startet og hvor mange sekunder utgangen var høy.
import csv
from datetime import datetime
from pathlib import Path
from signal import pause
from gpiozero import LED, MotionSensor
led = LED(17)
pir = MotionSensor(4)
FIL = Path(__file__).with_name("bevegelser.csv")
start = None
if not FIL.exists():
FIL.write_text("start,sekunder\n")
def bevegelse():
global start
start = datetime.now()
led.on()
print("Bevegelse kl.", start.strftime("%H:%M:%S"))
def stille():
led.off()
if start is None:
return
sekunder = (datetime.now() - start).total_seconds()
with FIL.open("a", newline="") as f:
tid = start.isoformat(timespec="seconds")
csv.writer(f).writerow([tid, round(sekunder, 1)])
pir.when_motion = bevegelse
pir.when_no_motion = stille
print("Venter på bevegelse. Ctrl+C avslutter.")
pause()
MotionSensor(4)leser GPIO4. Klassen slår på en intern pull-down-motstand, så inngangen er lav når sensoren ikke sender noe.Path(__file__).with_name("bevegelser.csv")legger filen i samme mappe som skriptet, uansett hvor programmet startes fra.if not FIL.exists()skriver overskriftslinjen første gang.global startlar funksjonen endre variabelen som ligger utenfor funksjonen, såstille()vet når bevegelsen begynte.if start is Nonehopper over et lavt signal som kommer før den første bevegelsen. gpiozero kjører hendelsesfunksjonene i en egen tråd menspause()venter.open("a", newline="")legger til linjer på slutten av filen, mednewline=""slik Python-dokumentasjonen anbefaler for CSV.isoformat(timespec="seconds")gir dato og klokkeslett på formen ÅÅÅÅ-MM-DDTtt:mm:ss.
Sekundene skrives med punktum som desimaltegn, så velg punktum som desimaltegn når du importerer filen i et regneark med norske innstillinger.
Prøv selv og feilsøk
- Gir sensoren ustabile utslag, kan du jevne ut avlesningene med
MotionSensor(4, queue_len=5). gpiozero bruker da gjennomsnittet av flere avlesninger. - Ingen utslag: vent ett minutt etter oppstart, og kontroller at VCC går til pinne 2 (5V) og ikke til pinne 1 (3V3).
- Utslag hele tiden: skru ned følsomheten (Sensitivity) og flytt sensoren bort fra lamper og trekk, som databladet advarer mot.
Nivå 3: sensordashbord i nettleseren med autostart
PIR-sensoren teller bevegelser, knappen slår varslingen av og på, LED-en lyser ved bevegelse når varslingen er på, og en webside viser status. Websiden lages med http.server fra Pythons standardbibliotek, så du trenger ikke installere noe. Til slutt blir skriptet en systemd-tjeneste som starter når Raspberry Pi slås på.
1. Programmet
Lagre koden som dashboard.py i mappen gpio.
from datetime import datetime
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from gpiozero import LED, Button, MotionSensor
led = LED(17)
knapp = Button(27, bounce_time=0.05)
pir = MotionSensor(4)
status = {"varsling": True, "antall": 0, "siste": "ingen ennå"}
def bevegelse():
status["antall"] += 1
status["siste"] = datetime.now().strftime("%H:%M:%S")
if status["varsling"]:
led.on()
def bytt_varsling():
status["varsling"] = not status["varsling"]
led.off()
pir.when_motion = bevegelse
pir.when_no_motion = led.off
knapp.when_pressed = bytt_varsling
SIDE = """<!DOCTYPE html>
<html lang="no"><head><meta charset="utf-8">
<meta http-equiv="refresh" content="5">
<title>GPIO-dashbord</title></head>
<body><h1>Bevegelse nå: {naa}</h1>
<p>Varsling: {varsling}</p>
<p>Bevegelser siden start: {antall}</p>
<p>Siste bevegelse: {siste}</p></body></html>"""
class Dashbord(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != "/":
self.send_error(404)
return
side = SIDE.format(
naa="ja" if pir.motion_detected else "nei",
varsling="på" if status["varsling"] else "av",
antall=status["antall"],
siste=status["siste"],
)
data = side.encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
server = ThreadingHTTPServer(("", 8000), Dashbord)
print("Dashbordet svarer på port 8000")
try:
server.serve_forever()
except KeyboardInterrupt:
server.server_close()
ThreadingHTTPServerbehandler hver forespørsel i en egen tråd, så en nettleser som åpner forbindelser på forhånd, ikke blokkerer serveren.statuser en ordbok som både gpiozero-hendelsene og websiden bruker. Funksjonene endrer innholdet og bytter ikke ut selve ordboken. Derfor trengs ingenglobal.bevegelse()teller bevegelsen og lagrer klokkeslettet, men tenner LED-en bare når varslingen er på.bytt_varsling()snur verdien mednot, ogwhen_no_motion = led.offslukker LED-en når sensorutgangen blir lav.bounce_time=0.05ignorerer prell i 50 ms, så ett trykk bytter varslingen bare én gang.SIDEer HTML-malen. Feltene i krøllparenteser, som{naa}, fylles inn avformat(). Linjen<meta http-equiv="refresh" content="5">får nettleseren til å laste siden på nytt hvert femte sekund.do_GET()kalles for hver GET-forespørsel. Andre adresser enn/, for eksempel ikonet nettleseren ber om, får svaret 404.pir.motion_detecteder True når sensoren melder bevegelse akkurat nå.encode("utf-8")gjør teksten om til bytes, ogcharset=utf-8sørger for at æ, ø og å vises riktig.send_response(),send_header()ogend_headers()må kalles i denne rekkefølgen førself.wfile.write()sender siden.("", 8000)betyr at serveren lytter på alle nettverksgrensesnitt, for eksempel WiFi og kablet nett, på port 8000.except KeyboardInterruptlukker serveren ryddig ved Ctrl+C.
2. Test fra en annen maskin
- Stopp eventuelle programmer fra nivå 1 og 2, og start dashbordet med
python3 ~/gpio/dashboard.py. - Finn IP-adressen til Raspberry Pi med
hostname -I. - Skriv
http://IP-adressen:8000i nettleseren på PC-en eller mobilen, med den faktiske adressen. - Vift med hånden foran sensoren: innen fem sekunder skal siden vise «Bevegelse nå: ja». Trykk på knappen og sjekk at varslingen skifter mellom på og av.
http.server i produksjon, fordi modulen bare har enkle sikkerhetskontroller. Ikke åpne porten i ruteren, og ikke legg inn funksjoner som slår på utstyr fra websiden uten innlogging.3. Start skriptet automatisk med systemd
Finn brukernavnet ditt med whoami. Kjør også which python3: viser den noe annet enn /usr/bin/python3, bytter du ut stien i ExecStart med den du fikk. Opprett tjenestefilen med sudo nano /etc/systemd/system/gpio-dashbord.service, lim inn teksten under og bytt ut brukernavn med ditt eget brukernavn på alle tre stedene.
[Unit]
Description=GPIO-dashbord med bevegelsessensor
[Service]
WorkingDirectory=/home/brukernavn/gpio
ExecStart=/usr/bin/python3 -u /home/brukernavn/gpio/dashboard.py
User=brukernavn
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
ExecStartstarter skriptet med full sti. Flagget-uskrur av bufring, såprint()havner i loggen med en gang.WorkingDirectorylar skriptet kjøre fra mappengpio. Pinnedriveren lgpio lager en liten hjelpefil i arbeidsmappen, og uten denne linjen prøver den å skrive i rotmappen, der brukeren din ikke har skrivetilgang. Da finner ikke gpiozero noen pinnedriver på Raspberry Pi 5, og tjenesten stopper.Userkjører skriptet som din vanlige bruker i stedet for root. Hovedbrukeren i Raspberry Pi OS er med i gruppengpioog har tilgang til pinnene.Restart=on-failurestarter skriptet på nytt hvis det stopper med en feil, ogRestartSec=5venter fem sekunder først.WantedBy=multi-user.targetunder[Install]kobler tjenesten til vanlig oppstart når du aktiverer den.
sudo systemctl daemon-reload
sudo systemctl enable --now gpio-dashbord.service
systemctl status gpio-dashbord.service
journalctl -u gpio-dashbord.service -f
daemon-reload leser inn den nye filen, og enable --now aktiverer tjenesten ved oppstart og starter den med det samme. status viser om den kjører, og journalctl med -f følger loggen til du trykker Ctrl+C, uten å stoppe tjenesten. Har tjenesten feilet, står årsaken i loggen: oftest feil brukernavn eller sti i ExecStart eller WorkingDirectory, eller GPIO busy fordi et annet program bruker pinnene. Stopp tjenesten med sudo systemctl stop gpio-dashbord.service før du tester i Thonny igjen, og fjern autostarten med sudo systemctl disable --now gpio-dashbord.service.
Vanlige spørsmål
Hvilket pinnenummer skal jeg skrive i koden?
GPIO-nummeret (BCM). LED(17) betyr GPIO17 på fysisk pinne 11. Vil du heller bruke det fysiske nummeret, skriver du LED("BOARD11").
Virker RPi.GPIO på Raspberry Pi 5?
Nei. gpiozero-dokumentasjonen oppgir at bare pinnedriveren lgpio virker på Pi 5, mens RPi.GPIO, pigpio og native er merket som ikke støttet. Bruk gpiozero, som velger lgpio når den er installert.
Kan jeg koble en 5 V-sensor direkte til Raspberry Pi?
Bare når signalutgangen gir 3,3 V, slik HC-SR501 gjør. En modul som sender 5 V tilbake, som ECHO på HC-SR04, trenger en spenningsdeler. gpiozero-dokumentasjonen bruker 330 Ω og 470 Ω, som gir rundt 3 V inn på GPIO-pinnen.
Må jeg installere gpiozero?
Nei, gpiozero følger med Raspberry Pi OS. Mangler den, installerer du den med sudo apt install python3-gpiozero. Fra og med Raspberry Pi OS Bookworm stopper systemet pip install utenfor et virtuelt miljø med feilen externally-managed-environment.
Veien videre
Resten av prototypesettet, som servo, temperatursensor og display, følger de samme reglene: 3,3 V på GPIO, motstand foran LED-er og ett program per pinne. Er du usikker på modellvalget, gir guiden om hva Raspberry Pi er en oversikt. Vil du programmere en mikrokontroller i stedet, passer Raspberry Pi Pico med MicroPython, og oversikten over programmering med elektronikk hjelper deg med å velge plattform. Neste store steg kan være et AI-kamera med Raspberry Pi.
Kilder: Raspberry Pis dokumentasjon om GPIO-kontakten, GPIO fra Python i Raspberry Pi OS, gpiozero-dokumentasjonen, Python-dokumentasjonen for http.server og systemd-dokumentasjonen for tjenester.




