Tilbake
5.7
Styresystemer og regulering

5.7 Styresystemer og regulering

Åpen og lukket sløyfe, enkel PID-regulering og automatisering.

35 min
5 oppgaver
StyresystemTilbakekoblingPIDRegulering
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 5 oppgaver

Prosjektarbeid med programmering

Gjennom denne seksjonen har du lært variabler, kontrollstrukturer, funksjoner, lister, filhåndtering og visualisering. Nå er det tid for å sette alt sammen i et prosjektarbeid.

Et programmeringsprosjekt er mer enn bare koding – det handler også om å planlegge, teste, feilsøke og dokumentere arbeidet ditt. Disse ferdighetene er sentrale i teknologi og forskningslære, og de gjenspeiler hvordan profesjonelle utviklere og forskere arbeider.

I dette kapittelet lærer du:
- Hvordan du planlegger et prosjekt med pseudokode og flytskjema
- Teknikker for testing og debugging (feilsøking)
- Hvordan du dokumenterer koden din med kommentarer og docstrings
- Hvordan du strukturerer et større program med funksjoner og moduler

Etter dette kapittelet vil du ha verktøyene du trenger for å gjennomføre et selvstendig programmeringsprosjekt fra start til slutt.

Planlegging med pseudokode og flytskjema
Pseudokode er en uformell beskrivelse av en algoritme som bruker vanlig språk og enkel struktur. Det er et mellomsteg mellom ideen i hodet ditt og den ferdige Python-koden.

Eksempel – pseudokode for et analyseprogram:

LES data fra fil
FOR hver måling i data:
    LEGG TIL måling i liste
BEREGN gjennomsnitt
BEREGN standardavvik
HVIS gjennomsnitt > grenseverdi:
    SKRIV advarsel
LAG graf av målingene
LAGRE rapport til fil

Et flytskjema er en visuell fremstilling av programflyten med standardiserte symboler:
- Oval: Start/slutt
- Rektangel: Prosess (handling)
- Diamant (rombe): Beslutning (if/else)
- Parallellogram: Inndata/utdata

Fordeler med planlegging:
- Du oppdager logiske feil før du begynner å kode
- Det er lettere å dele opp arbeidet i funksjoner
- Andre kan forstå planen din og gi tilbakemelding
- Du slipper å skrive om store deler av koden underveis

De fire fasene i et programmeringsprosjekt

Et godt prosjekt følger disse fasene:

1. Planlegging (20 % av tiden)
- Definer problemet tydelig: Hva skal programmet gjøre?
- Skisser løsningen med pseudokode eller flytskjema
- Identifiser hvilke funksjoner du trenger
- Bestem hvilke biblioteker som er nyttige (csv, matplotlib, math)

2. Koding (40 % av tiden)
- Skriv én funksjon om gangen
- Test hver funksjon for seg (enhetstesting)
- Bruk beskrivende variabelnavn og kommentarer
- Følg Python-konvensjoner (snake_case, innrykk med 4 mellomrom)

3. Testing (25 % av tiden)
- Test med kjente data der du vet svaret
- Test grensetilfeller (tom liste, null, negative tall)
- Test med ugyldig inndata (tekst der det forventes tall)
- Rett feil (debugging) og test på nytt

4. Dokumentasjon (15 % av tiden)
- Skriv en kort beskrivelse av programmet
- Kommenter vanskelige deler av koden
- Lag en brukerveiledning hvis programmet har brukerinteraksjon
- Dokumenter kilder (data, formler, biblioteker)

✏️Fra pseudokode til ferdig program

La oss følge prosessen for et program som analyserer temperaturdata:

Steg 1 – Pseudokode:

LES temperaturer fra CSV-fil
BEREGN gjennomsnitt, min, maks
TELL dager med frost (under 0)
LAG linjediagram av temperaturene
LAGRE rapport til tekstfil

Steg 2 – Identifiser funksjoner:
- les_data(filnavn) – leser CSV og returnerer lister
- beregn_statistikk(temperaturer) – returnerer gjennomsnitt, min, maks
- lag_graf(datoer, temperaturer) – lager og viser grafen
- skriv_rapport(statistikk, filnavn) – skriver rapport til fil

Steg 3 – Kode:

import csv
import matplotlib.pyplot as plt

def les_data(filnavn):
    """Leser temperaturdata fra en CSV-fil."""
    datoer = []
    temperaturer = []
    with open(filnavn, "r") as fil:
        leser = csv.reader(fil)
        next(leser)  # Hopp over overskrift
        for rad in leser:
            datoer.append(rad[0])
            temperaturer.append(float(rad[1]))
    return datoer, temperaturer

def beregn_statistikk(temperaturer):
    """Beregner og returnerer statistikk som en dictionary."""
    return {
        "antall": len(temperaturer),
        "gjennomsnitt": sum(temperaturer) / len(temperaturer),
        "maks": max(temperaturer),
        "min": min(temperaturer),
        "frost": sum(1 for t in temperaturer if t < 0),
    }

def lag_graf(datoer, temperaturer):
    """Lager et linjediagram av temperaturene."""
    plt.figure(figsize=(12, 5))
    plt.plot(temperaturer, "b-", linewidth=1.5)
    plt.axhline(y=0, color="red", linestyle="--", alpha=0.5)
    plt.xlabel("Dag nr.")
    plt.ylabel("Temperatur (°C)")
    plt.title("Daglige temperaturer")
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig("temperaturgraf.png", dpi=150)
    plt.show()

def skriv_rapport(statistikk, filnavn):
    """Skriver en rapport med statistikk til fil."""
    with open(filnavn, "w") as fil:
        print("TEMPERATURRAPPORT", file=fil)
        print("=" * 30, file=fil)
        for nokkel, verdi in statistikk.items():
            if isinstance(verdi, float):
                print(f"{nokkel:15s}: {verdi:8.1f}", file=fil)
            else:
                print(f"{nokkel:15s}: {verdi:8d}", file=fil)

# Hovedprogram
datoer, temperaturer = les_data("temperaturer.csv")
statistikk = beregn_statistikk(temperaturer)
lag_graf(datoer, temperaturer)
skriv_rapport(statistikk, "temperaturrapport.txt")

print("Analyse fullført!")

Legg merke til at hovedprogrammet på slutten er svært lesbart – hver linje beskriver ett steg i analysen.

📝Oppgave 1

Hvilken fase av et programmeringsprosjekt bør du bruke mest tid på?

Testing og debugging
Testing handler om å sjekke at programmet fungerer korrekt. Debugging handler om å finne og rette feil.

Tre typer tester:

1. Test med kjente data: Bruk inndata der du vet svaret.

# Test: gjennomsnitt av [2, 4, 6] skal gi 4.0
resultat = beregn_gjennomsnitt([2, 4, 6])
print(f"Forventet: 4.0, Fikk: {resultat}")

2. Test grensetilfeller: Sjekk at programmet håndterer spesielle verdier.

# Test med tom liste
# Test med ett element
# Test med negative tall
# Test med veldig store tall

3. Test med ugyldig inndata: Sjekk at programmet ikke krasjer.

# Hva skjer hvis brukeren skriver "abc" i stedet for et tall?
try:
    tall = float(input("Tall: "))
except ValueError:
    print("Ugyldig inndata – skriv inn et tall.")

Debugging-teknikker:
- Print-debugging: Legg til print() for å se verdier underveis
- Les feilmeldingen nøye: Python forteller deg type feil og linjenummer
- Kommenter ut kode: Isoler problemet ved å deaktivere deler av koden
- Gummiand-metoden: Forklar koden høyt for en «gummiand» (eller en medstudent)

Vanlige feil og hvordan du fikser dem

Her er de vanligste feilene nybegynnere møter i Python:

1. SyntaxError – skrivefeil i koden

# Feil: mangler kolon
if x > 5
    print("Stor")

# Riktig:
if x > 5:
    print("Stor")

2. IndentationError – feil innrykk

# Feil: blander mellomrom og tab
def funksjon():
    print("a")
      print("b")    # For mye innrykk!

# Riktig: konsekvent innrykk med 4 mellomrom
def funksjon():
    print("a")
    print("b")

3. NameError – variabelen finnes ikke

# Feil: skrivefeil i variabelnavn
temperatur = 22.5
print(tempratur)    # NameError!

# Riktig:
print(temperatur)

4. TypeError – feil datatype

# Feil: kan ikke legge sammen streng og tall
alder = "17"
neste_ar = alder + 1    # TypeError!

# Riktig:
neste_ar = int(alder) + 1

5. IndexError – ugyldig indeks

# Feil: listen har bare 3 elementer (indeks 0–2)
tall = [10, 20, 30]
print(tall[3])    # IndexError!

# Riktig:
print(tall[2])    # Siste element

Tips: Les alltid hele feilmeldingen. Den forteller deg type feil, linjenummer og ofte hva som gikk galt.

✏️Systematisk testing av en funksjon

Her tester vi en funksjon som beregner karaktergjennomsnitt:

def beregn_snitt(karakterer):
    """Beregner gjennomsnittet av en liste med karakterer (1-6)."""
    if len(karakterer) == 0:
        return 0.0
    return sum(karakterer) / len(karakterer)

# === TESTER ===

# Test 1: Vanlig tilfelle
resultat = beregn_snitt([4, 5, 3, 6, 4])
forventet = 4.4
print(f"Test 1: {resultat} == {forventet}? {'OK' if abs(resultat - forventet) < 0.01 else 'FEIL'}")

# Test 2: Alle like
resultat = beregn_snitt([5, 5, 5])
forventet = 5.0
print(f"Test 2: {resultat} == {forventet}? {'OK' if abs(resultat - forventet) < 0.01 else 'FEIL'}")

# Test 3: Bare én karakter
resultat = beregn_snitt([6])
forventet = 6.0
print(f"Test 3: {resultat} == {forventet}? {'OK' if abs(resultat - forventet) < 0.01 else 'FEIL'}")

# Test 4: Tom liste (grensetilfelle)
resultat = beregn_snitt([])
forventet = 0.0
print(f"Test 4: {resultat} == {forventet}? {'OK' if abs(resultat - forventet) < 0.01 else 'FEIL'}")

Utskrift:

Test 1: 4.4 == 4.4? OK
Test 2: 5.0 == 5.0? OK
Test 3: 6.0 == 6.0? OK
Test 4: 0.0 == 0.0? OK

Legg merke til at vi bruker abs(resultat - forventet) < 0.01 for å sammenligne desimaltall – direkte sammenligning med == kan gi feil på grunn av avrunding.

📝Oppgave 2

Hva er en docstring i Python?

Dokumentasjon av kode

God dokumentasjon gjør koden din forståelig for andre – og for deg selv om noen uker!

Kommentarer forklarer hvorfor du gjør noe (ikke hva – det ser man av koden):

# Dårlig kommentar (sier hva koden gjør – det ser vi allerede):
x = x + 1  # Øker x med 1

# God kommentar (sier hvorfor):
x = x + 1  # Kompenser for 0-indeksering i utskriften

Docstrings dokumenterer funksjoner:

def beregn_bmi(vekt_kg, hoyde_m):
    """
    Beregner Body Mass Index (BMI).

    Parametre:
        vekt_kg (float): Vekt i kilogram
        hoyde_m (float): Høyde i meter

    Returnerer:
        float: BMI-verdien
    """
    return vekt_kg / (hoyde_m ** 2)

Filhode – en kommentar øverst i filen som beskriver programmet:

"""
Temperaturanalyse – Prosjektoppgave ToF 1

Programmet leser temperaturdata fra en CSV-fil,
beregner statistikk og lager visualiseringer.

Forfatter: Kari Nordmann
Dato: 2024-03-15
"""

Husk: Kode leses mye oftere enn den skrives. God dokumentasjon er en investering i fremtidig leseforståelse.

✏️Et godt dokumentert miniprosjekt

Her er et komplett miniprosjekt med god struktur og dokumentasjon:

"""
BMI-kalkulator med statistikk

Programmet lar brukeren registrere BMI for flere personer,
beregner statistikk og lager et stolpediagram.

Forfatter: Elev Elevesen
Dato: 2024-03-20
"""

import matplotlib.pyplot as plt

def beregn_bmi(vekt_kg, hoyde_m):
    """Beregner BMI basert på vekt (kg) og høyde (m)."""
    return vekt_kg / (hoyde_m ** 2)

def bmi_kategori(bmi):
    """Returnerer BMI-kategori som tekst."""
    if bmi < 18.5:
        return "Undervekt"
    elif bmi < 25:
        return "Normalvekt"
    elif bmi < 30:
        return "Overvekt"
    else:
        return "Fedme"

def les_inn_data():
    """Leser inn navn, vekt og høyde for flere personer."""
    navn_liste = []
    bmi_liste = []

    print("BMI-kalkulator (skriv 'ferdig' for å avslutte)")
    while True:
        navn = input("Navn: ")
        if navn.lower() == "ferdig":
            break
        try:
            vekt = float(input("Vekt (kg): "))
            hoyde = float(input("Høyde (m): "))
            bmi = beregn_bmi(vekt, hoyde)
            navn_liste.append(navn)
            bmi_liste.append(bmi)
            print(f"  BMI: {bmi:.1f} ({bmi_kategori(bmi)})")
        except ValueError:
            print("  Ugyldig input – prøv igjen.")

    return navn_liste, bmi_liste

def vis_statistikk(navn_liste, bmi_liste):
    """Skriver ut en oppsummering av BMI-dataene."""
    print("\nOPPSUMMERING")
    print("=" * 35)
    for navn, bmi in zip(navn_liste, bmi_liste):
        print(f"  {navn:15s} BMI: {bmi:5.1f} ({bmi_kategori(bmi)})")
    print("-" * 35)
    print(f"  Gjennomsnitt: {sum(bmi_liste) / len(bmi_liste):.1f}")

def lag_diagram(navn_liste, bmi_liste):
    """Lager et stolpediagram over BMI-verdiene."""
    farger = ["green" if 18.5 <= b < 25 else "orange" for b in bmi_liste]
    plt.figure(figsize=(8, 5))
    plt.bar(navn_liste, bmi_liste, color=farger)
    plt.axhline(y=18.5, color="gray", linestyle="--", alpha=0.5)
    plt.axhline(y=25, color="gray", linestyle="--", alpha=0.5)
    plt.ylabel("BMI")
    plt.title("BMI-oversikt")
    plt.tight_layout()
    plt.savefig("bmi_oversikt.png", dpi=150)
    plt.show()

# === HOVEDPROGRAM ===
navn, bmi = les_inn_data()
if len(navn) > 0:
    vis_statistikk(navn, bmi)
    lag_diagram(navn, bmi)
else:
    print("Ingen data registrert.")

Programmet viser alle elementene i et godt prosjekt: filhode, docstrings, feilhåndtering, modulær oppbygging med funksjoner, og en tydelig hovedprogramdel.

Oppsummering

I dette kapittelet har du lært å:

- Planlegge et programmeringsprosjekt med pseudokode og flytskjema
- Følge de fire fasene: planlegging, koding, testing og dokumentasjon
- Teste programmer systematisk med kjente data, grensetilfeller og ugyldig inndata
- Debugge vanlige Python-feil: SyntaxError, IndentationError, NameError, TypeError og IndexError
- Dokumentere kode med kommentarer, docstrings og filhoder
- Strukturere et program med funksjoner som har tydelig ansvar

Nøkkelprinsipper for gode prosjekter:
- Planlegg før du koder – det sparer tid til slutt
- Skriv og test én funksjon om gangen
- Les feilmeldinger nøye – de forteller deg hva som er galt
- Dokumenter koden din – fremtidens deg vil takke deg
- Hold funksjoner små og med ett tydelig formål

Med ferdighetene fra hele seksjon 5 – variabler, kontrollstrukturer, funksjoner, lister, filhåndtering, visualisering og prosjektarbeid – har du et solid grunnlag for å bruke programmering som verktøy i teknologi og forskningslære.

📝Oppgave 3

Skriv pseudokode for et program som leser inn poengsummer fra en prøve, beregner gjennomsnitt og median, og avgjør om snittet er bestått (over 50 %). Oversett deretter pseudokoden til Python-kode med minst to funksjoner.

📝Oppgave 4

Gjennomfør et miniprosjekt: Lag et Python-program som fungerer som en «værstasjon». Programmet skal: a) Lese inn daglige målinger (temperatur, nedbør) i en uke (7 dager). b) Beregne og vise statistikk (gjennomsnitt, min, maks for begge). c) Lage to grafer med subplots: temperatur over uken og nedbør som stolpediagram. d) Lagre en rapport til en tekstfil. Kravliste: minst 3 funksjoner, docstrings på alle funksjoner, feilhåndtering for ugyldig inndata, og et filhode.

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.