📂 Verkefnasafn

Safn af verkefnum þar sem lýsing og kóði eru geymd saman.

#001 – Fjarlægðamælir og vefsíða

Verkefnið notar ultrasonic fjarlægðaskynjara tengdan Raspberry Pi. Mælingar eru birtar á vefsíðu með Flask.

Uppsetning

sudo apt-get update
sudo apt-get install python3-flask
    

Python kóði Sækja með txt skrá


# Flytjum inn nauðsynleg forritasöfn:
from flask import Flask, jsonify, render_template_string # Flask fyrir vefinn, jsonify fyrir JSON gögn
import RPi.GPIO as GPIO # Notað til að stjórna GPIO pinnum á Raspberry Pi
import time # Til að mæla tíma í fjarlægðarútreikningum

# Búum til Flask vef-forrit
app = Flask(__name__)

# Skilgreinum hvaða GPIO-pinna eru notaðir fyrir ultrasonic skynjara
TRIG, ECHO = 23, 24

GPIO.setwarnings(False) # Slökkvum á viðvörunum ef pinnar eru þegar í notkun
GPIO.setmode(GPIO.BCM) # Notum BCM skíráningu fyrir pinnana (frekar en physical order)
GPIO.setup(TRIG, GPIO.OUT) # TRIG (sendingarpinni) er stilltur sem útgangur
GPIO.setup(ECHO, GPIO.IN) # ECHO (móttökupinni) er stilltur sem inngangur

# Fall sem mælir fjarlægð með ultrasonic skynjara
def get_distance():
# Sendum mjög stuttan háspennu-púls á TRIG
GPIO.output(TRIG, True)
time.sleep(0.00001) # 10 míkrósekúndur
GPIO.output(TRIG, False)

# Mælum hvenær við fáum endurkast frá hljóðbylgju (byrjun og endir)
while GPIO.input(ECHO) == 0:
start = time.time()
while GPIO.input(ECHO) == 1:
end = time.time()

# Reiknum tíma sem bylgjan tók og umbreytum því í fjarlægð í cm
return round((end - start) * 17150, 2) # hraði hljóðs í lofti: ~343 m/s → 17150 cm/s (frem og til baka)

# Fall sem breytir fjarlægð yfir í lítra
def calculate_liters(distance):
max_height = 100 # Hámarks hæð t.d. á vatnstank í cm
# Reiknar hversu mikið tankurinn er fullur hlutfallslega og margfaldar með 100 lítrum
return round(max(0, (1 - distance / max_height)) * 100, 1)

# Aðalsíða: HTML + JavaScript sem birtir mælingar og uppfærir þær sjálfkrafa
@app.route('/')
def index():
return render_template_string(
# HTML og JavaScript í einni línu fyrir einfaldan vef
'<h1>📏 <span id=d>...</span></h1>' # Fjarlægð verður birt hér
'<h2>💧 <span id=l>...</span></h2>' # Rúmmál verður birt hér
'<script>'
'setInterval(()=>' # Keyrir á 1000ms (1 sek fresti)
'fetch("/data")' # Sækir nýjustu mæligögn frá /data route
'.then(r=>r.json())'
'.then(g=>{' # Þegar gögnin eru móttekin...
'd.innerText=g.distance+" cm";' # ...birtum fjarlægð
'l.innerText=g.liters+" lítrar"})'
',1000)' # Endurtaka á hverri sekúndu
'</script>'
)

# Þessi route skilar mæligögnum sem JSON – sem JS á síðunni les
@app.route('/data')
def data():
d = get_distance() # Fáum fjarlægð
l = calculate_liters(d) # Reiknum lítra út frá fjarlægð
return jsonify({'distance': d, 'liters': l}) # Skilum JSON svari

# Keyrir Flask vefþjón og lokar GPIO-pinnum þegar hætt er
if __name__ == '__main__':
try:
app.run(host='0.0.0.0', port=5000) # Keyrir vefinn á öllum IP tölum Raspberry Pi (getur séð úr vafra á netinu)'
    )

@app.route('/data')
def data():
    d = get_distance()
    l = calculate_liters(d)
    return jsonify({'distance': d, 'liters': l})

if __name__ == '__main__':
    try:
        app.run(host='0.0.0.0', port=5000)
    finally:
        GPIO.cleanup()
    

#002 – GPIO vakt

Þetta verkefni les stöðu á nokkrum GPIO inntakspinnum á Raspberry Pi og birtir stöðuna á einfaldri vefsíðu með Flask.

Uppsetning

sudo apt-get update
sudo apt-get install python3-flask

Python kóði Sækja með txt skrá

from flask import Flask, jsonify, Response
import RPi.GPIO as GPIO, atexit

# Listi af pinnum (BCM)
PINS = [4, 6, 11, 12]

GPIO.setmode(GPIO.BCM)
for p in PINS:
GPIO.setup(p, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

app = Flask(__name__)

HTML = """
<!doctype html> <!-- segir vafranum að þetta sé HTML5 skjal -->
<html>
<head>
<meta charset="utf-8"> <!-- tryggir íslenska stafi rétt -->
<title>GPIO vakt</title> <!-- titill sem birtist í flipanum -->
<style>
/* Stíll fyrir allt body: hvítur bakgrunnur, sans-serif letur,
miðjuð efni með flexbox */
body { background:#fff; font-family:sans-serif; display:flex; justify-content:center; }

/* umgjörð utan um allar einingar (ljósin) með bil á milli */
.wrap { display:flex; gap:30px; padding:40px; }

/* grunnstíll fyrir ljósahringina */
.lamp { width:100px; height:100px; border-radius:50%; background:#eee; border:2px solid #999; }

/* ef GPIO er HIGH bætist við .red klasanum => rauður hringur */
.lamp.red { background:#c00; }

/* textamerki fyrir hvern pinna */
.label { text-align:center; margin-top:8px; font-size:14px; }

/* hver eining (hringur + merki) er í miðju */
.unit { text-align:center; }

/* klukkan birtist fast neðst hægra megin, monospace letur */
#clock { position:fixed; bottom:10px; right:15px; font-family:monospace; color:#333; font-size:16px; }
</style>
</head>
<body>
<!-- umgjörð sem heldur utan um öll ljósin -->
<div class="wrap">
<!-- hvert ljós fær sitt eigið div + merki -->
<div class="unit"><div id="p4" class="lamp"></div><div class="label">GPIO 4</div></div>
<div class="unit"><div id="p6" class="lamp"></div><div class="label">GPIO 6</div></div>
<div class="unit"><div id="p11" class="lamp"></div><div class="label">GPIO 11</div></div>
<div class="unit"><div id="p12" class="lamp"></div><div class="label">GPIO 12</div></div>
</div>

<!-- klukkan sjálf birtist hér -->
<div id="clock"></div>

<script>
// fall sem sækir stöðuna frá Flask (/status) og litar ljósin
async function tick(){
try {
// biður Flask server um JSON með stöðu allra pinna
const r = await fetch('/status', {cache:'no-store'});
const d = await r.json(); // d er object: {4:true,6:false,11:true,12:false}

// förum í gegnum alla pinna í JSON og setjum class eftir stöðu
for (const pin in d){
// ef true (HIGH) => lamp red, annars bara lamp (hvítur)
document.getElementById("p"+pin).className = d[pin] ? "lamp red" : "lamp";
}
} catch (e) {
// ef fetch bregst má bæta inn villumeðhöndlun hér
}
}

// keyrum tick á 700 ms fresti
setInterval(tick, 700);
// köllum tick strax í byrjun svo við fáum stöðu strax
tick();

// fall sem uppfærir klukkuna á hverri sekúndu
function updateClock(){
const now = new Date(); // núverandi tími
const hh = String(now.getHours()).padStart(2,"0"); // klukkustundir með 2 tölustöfum
const mm = String(now.getMinutes()).padStart(2,"0"); // mínútur
const ss = String(now.getSeconds()).padStart(2,"0"); // sekúndur
// skrifum texta í <div id="clock">
document.getElementById("clock").textContent = hh + ":" + mm + ":" + ss;
}

// uppfærum klukkuna á 1000 ms fresti
setInterval(updateClock, 1000);
// köllum strax í byrjun svo hún birtist samstundis
updateClock();
</script>
</body>
</html>
"""

@app.route("/")
def index():
return Response(HTML, mimetype="text/html")

@app.route("/status")
def status():
vals = {p: bool(GPIO.input(p)) for p in PINS}
return jsonify(vals)

@atexit.register
def cleanup():
GPIO.cleanup()

if __name__ == "__main__":
app.run(host="0.0.0.0", port=5055)

Svona verður þá útkoma á vefsíðu og verður litur í hring rauður ef það er kveit