Page 1 of 1

Zeitstoppen mit Countdown und Buzzer

Posted: Tue Feb 16, 2016 7:05 am
by Tobuscus
Hallo liebe Raspberry Pi Gemeinde,

da mein Englisch "not the yellow from the Egg ist" ( :lol: ) dachte ich mir ich spreche das Thema zunächst im deutschsprachigen Forum an.

Ich möchte gerne unser üben für Wettkämpfe bei der Feuerwehr digitalisieren. So wie das beim richtigen Wettkampf auch gemacht wird. Ich habe auf meiner Arbeit schon mal was von Raspberry Pi und Arduino gehört, wobei ich den Raspberry Pi wegen der Computer ähnlichen Visualisierung bevorzuge.

Das ganze soll wie folgt ablaufen:

Auf dem Bildschirm soll durch klicken auf das Feld "Start" eine Audiodatei abgespielt werden. "Nach dem Countdown beginnt die Zeitmessung. 5, 4, 3,..." so etwas in der Art. Nach dem der Countdown abgelaufen ist, soll automatisch die Zeitmessung los gehen. Am besten auch auf 1/100 Sekunden.
Wenn dann der Akt vollzogen ist soll man mit Hilfe von einem Buzzers(Hot Button) die Zeit anhalten können.
Nun wäre es gut wenn man die Zeit Speichern, oder heraus kopieren könnte, um eine Tabelle anzufertigen.

Soweit alles verstanden? Danke schon mal im Vorraus!
Tobias

Re: Zeitstoppen mit Countdown und Buzzer

Posted: Tue Feb 16, 2016 10:07 am
by crumble
Wenn ihr euch lieb habt und es nicht wirklich auf die 1/100 Sekunde ankommt, sollte sich das recht leicht in python oder scratch schreiben lassen.

Ich muss mich eh ein wenig in Python einarbeiten. Wenn Du magst, kann ich Dir dafuer ein einfaches Skript in guter alter 70er Textausgabe schreiben und hier posten. Dann hast Du die Grundlagen und kannst es so anpassen, wie ihr es braucht.

Re: Zeitstoppen mit Countdown und Buzzer

Posted: Tue Feb 16, 2016 10:15 am
by Tobuscus
Danke crumble.

Das hört sich Grundsätzlich schon einmal gut an. Damit habe ich dann wohl das Grundgerüst und kann es ja eventuell noch anpassen. Vielleicht komme ich ja dann später selber drauf!

Denoch bin ich für alles was Vorschläge angeht offen.

Edit: Eine Nachkommastelle wäre dennoch gut.

Re: Zeitstoppen mit Countdown und Buzzer

Posted: Tue Feb 16, 2016 10:54 am
by ghans
@Tobuscus

Welche Programmierkenntnisse hast du ?

ghans

Re: Zeitstoppen mit Countdown und Buzzer

Posted: Tue Feb 16, 2016 10:58 am
by Tobuscus
ghans wrote:@Tobuscus

Welche Programmierkenntnisse hast du ?

ghans
Auf der Arbeit habe ich viel mit Simatic S7 und Siemens LOGO zu tun. Seid neustem ein wenig Beckhoff. Phython HTML und PHP habe ich in meinem Leben vielleicht 3 mal gesehen.

Re: Zeitstoppen mit Countdown und Buzzer

Posted: Tue Feb 16, 2016 11:03 am
by Tobuscus
So sollte es mal aussehen: https://www.youtube.com/watch?v=z9M3nGtmIjg
Sowohl wir als auch die Technik :lol: :lol:

Re: Zeitstoppen mit Countdown und Buzzer

Posted: Sun Feb 21, 2016 11:31 pm
by crumble
Erstaunlich wie schnell man eine Sprache hassen lernt. Und das auch noch bevor man in die wirklichen Probleme bei größeren Projekten kommt. Das schlimmste sind die deutschen Namen für Variablen und Methoden. Wenn man so etwas jahrelang nur auf Englisch macht, fehlt da einfach die Übung :-)

Hier ist das python3 Programm, das noch einiges an Überarbeitung braucht.
Eine Anfängerfreundlich Dokumentation, eine GUI in Tk und vor allem sollte man sich auf die Zeiten verlassen können. Irgendwas muß ich da kurz vor Schluß falsch gemacht haben, aber ich wollte Dir schon mal ein Rückmeldung geben.

So wie das Programm konfiguriert ist, brauchst Du drei Buzzer.
Einen für die Rennleitung, um die einzelnen Läufe zu starten und zu stoppen.
Zwei für die Teilnehmer.

Die verwendeten Pins, Anzahl der Runden und die verwendeten Dateien muß man im Source-Code konfigurieren.
Die aktuellen Teilnehmer werden aus einer Datei gelesen.

Alles nicht schön, aber ich habe so gelernt, daß ich einen Pi3 mit 4GB RAM haben will, damit ich meinen Pfeilsuchroboter in C#/mono zusammenschustern kann.

Code: Select all

#!/usr/bin/python3

import os
import time
import datetime
import RPi.GPIO as GPIO
import subprocess
import operator
import csv

#
# Einstellungen
#
anzahlBuzzer    = 2        # Anxzahl der Buzzer für die Teilnehmer. Die Rennleitung benötigt einen weiteren
anzahlRunden    = 5        # Die Runden pro Lauf
pinBuzzer       = [22, 27] # Die Pins an dem die Buzzer der Teilnehmer angeschlossen sind
pinRennleitung  = 17       # Der Pin  an dem der Buzzer der Rennleitung angeschlossen ist
entprellZeit    = datetime.timedelta(seconds=2) # Entprellzeit der Buzzer
dateiCountDown  = '/home/pi/Videos/test3.mp4'
dateiTeilnehmer = '/home/pi/TeamDatei.csv'
dateiErgebnisse = '/home/pi/Ergebnisse.csv'


#
# Globale Variablen
#
pinZuIndex      = {}
rundenZaehler   = [0 for b in range(anzahlBuzzer)]
rundenAnkuenfte = [[datetime.datetime.max for r  in range(anzahlRunden)] for b in range(anzahlBuzzer)]
teamReihenfolge = []
rangliste = {}


#
# Unterprogramme
#

def leseTeamReihenfolge():
    with open(dateiTeilnehmer, 'r') as teamDatei:
        teamReader = csv.reader(teamDatei, dialect='excel')
        for zeile in teamReader:
            teamReihenfolge.append(zeile)
            
            
def schreibeErgebnisListe(lauf, gestartetUm):
    with open(dateiErgebnisse, 'a') as ergebnisDatei:
        ergWriter = csv.writer(ergebnisDatei, dialect='excel')
        for t in range(anzahlBuzzer):            
            neueZeile = []
            neueZeile.append(lauf[t])
            neueZeile.append(str(gestartetUm))

            # Gesamtzeit
            if rundenAnkuenfte[t][anzahlRunden-1] == datetime.datetime.max :
                neueZeile.append("dnf")
                rangliste[lauf[t]] = datetime.timedelta.max
            else:
                zeit = rundenAnkuenfte[t][anzahlRunden-1]-gestartetUm
                neueZeile.append(str(zeit))
                rangliste[lauf[t]] = zeit

            # Rundenzeiten
            for r in range(anzahlRunden):
                if rundenAnkuenfte[t][r] == datetime.datetime.max:
                    neueZeile.append("dnf")
                else:
                    if r == 0:
                        zeit = rundenAnkuenfte[t][r]-gestartetUm
                    else:
                        zeit = rundenAnkuenfte[t][r]-rundenAnkuenfte[t][r-1]
                    neueZeile.append(str(zeit))

            ergWriter.writerow(neueZeile)

def zeigeReihenfolge():
    print("Reihenfolge:")
    i = 1
    for lauf in teamReihenfolge:
        s = "  Lauf " + str(i) + ": "
        for t in lauf: 
            s += t + ", "
        i += 1
        print(s)


def zeigeRangliste():
    print("")
    print("Rangliste:")
    sortiert = sorted(rangliste.items(), key=operator.itemgetter(1))
    r = 1
    for i in sortiert:
        s = str(r) + ". " + i[0] + " - "
        if i[1] == datetime.timedelta.max:
            s += "dnf"
        else:
            s += str(i[1])
        print(s)
        r += 1
    print("")


def initialisiereGPIO():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(pinRennleitung, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    for pin in pinBuzzer:
      GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)


def macheBuzzerScharf():
  for pin in pinBuzzer:
    GPIO.add_event_detect(pin, GPIO.FALLING, ankunft)


def sicherBuzzer():
  for pin in pinBuzzer:
    GPIO.remove_event_detect(pin)

  
# Callback, der die Rundenzeiten waehrend des Rennens speichert
def ankunft(pin):
    ankunftsZeit = datetime.datetime.now();
    i = pinZuIndex[pin]
    runde = rundenZaehler[i]
    if runde < anzahlRunden:
      #if runde>0:
        #print(ankunftsZeit - rundenAnkuenfte[i][runde-1])
      if runde == 0 or (ankunftsZeit - rundenAnkuenfte[i][runde-1]) > entprellZeit:
        rundenAnkuenfte[i][runde] = ankunftsZeit
        rundenZaehler[i] += 1
        print(str(pin) + " Runde " + str(runde) + " gewertet")
      else:
        print(str(pin) + " entprellt")
    else:
      print(str(pin) + " zu viele Runden")


# Bereitet die globalen Variablen für den nächsten Lauf vor
def initLauf():
  rundenAnkuenfte = [[datetime.datetime.max for r  in range(anzahlRunden)] for b in range(anzahlBuzzer)]
  i = 0
  for pin in pinBuzzer:
    pinZuIndex[pin] = i
    rundenZaehler[i] = 0
    i += 1


#
# Hautprogramm
#

print("fireWorkOut V0.1")
print("")
initialisiereGPIO()
leseTeamReihenfolge()
zeigeReihenfolge()
print("")
print("")

laufNr = 0          
for lauf in teamReihenfolge:
    laufNr += 1
    print("Lauf " + str(laufNr))
    print("Teilnehmer:")
    for teilnehmer in lauf:
        print("  " + teilnehmer)
    print("")
    
    initLauf()
    time.sleep(1) # schlechte Entprellung der beiden Rennleitungsklicks pro Lauf
    print("Warte auf OK von Rennleitung")
    GPIO.wait_for_edge(pinRennleitung, GPIO.FALLING)

    retcode = subprocess.call(['/usr/bin/omxplayer', dateiCountDown], stdout=subprocess.DEVNULL)
    #print(retcode)

    laufGestartetUm = datetime.datetime.now()

    macheBuzzerScharf()

    print("Gestartet um " + str(laufGestartetUm) + ". Warte auf Rennleitung")
    ende = False
    while not ende:
      GPIO.wait_for_edge(pinRennleitung, GPIO.FALLING)
      laufGestopptUm = datetime.datetime.now()
      if (laufGestopptUm - laufGestartetUm) > entprellZeit:
        print("Lauf beendet")
        ende = True
      else:
        print("rennleitung entprellt")

    sicherBuzzer()

    schreibeErgebnisListe(lauf, laufGestartetUm)
    zeigeRangliste()
Eine Teilnehmerdatei muss genauso viele Spalten haben wie die definierten Buzzer

Code: Select all

Anton,Berta
Cäsar,Dora
Emil,Frida