Seite 1 von 1

Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 18:12
von urmelausdemeis
Hallo zusammen,

wir steuern derzeit ein Fahrstuhlmodell mit Python, doch leider funktioniert das noch nicht wie gewünscht. Vielleicht könnt Ihr uns sagen, wo unser Fehler liegt/unsere Fehler liegen.

Zunächst einmal der Code:

Code: Alles auswählen

from camface import *
import time
writeCom1(0)
def superfahrstuhl():
    setCom1()
    global position, anzahl_etagen, ruf_etage, wahl_etage
    anzahl_etagen=0
    position=0
    ruf_etage=0
    wahl_etage=0
    eingabe()
    writeCom1(0)
    while readCom1()==0:
        if (readCom1()>0 and readCom1()<=8):
            print readCom1()
            print ("Aufzug wird gerufen")
            rufen()
            position=ruf_etage
            writeCom1(0)
        if readCom1()>8:
            waehlen()
            position=wahl_etage
            writeCom1(0)
 
def eingabe():
 global dpe
 dpe=input("Gib die Drehzahl pro Etage ein.")
 print ("Rufe den Fahrstuhl oder waehle ein Stockwerk.")
 
def rufen():
    if readCom1()==1:
        ruf_etage=0
        print ruf_etage

    if readCom1()==2:
        ruf_etage=1
        print ruf_etage

    if readCom1()==4:
        ruf_etage=2
        print ruf_etage

    if readCom1()==8:
        ruf_etage=3
        print ruf_etage

    anzahl_etagen=ruf_etage-position
    
    fahren(anzahl_etagen)    

def tuerauf():
    writeCom1(64)

def pause():
    time.sleep(100)

def tuerzu():
    writeCom1 (128)

def fahrstuhlfaehrt():
    writeCom1 (16)

def fahrstuhlsteht():
    writeCom1 (32)    

def fahren(anzahl_etagen):

    tuerzu()
    
    fahrstuhlfaehrt()
    
    if anzahl_etagen==-3:
        for g in range (1,3*dpe):
            writeCom1(10)
            time.sleep(0.001)
            writeCom1(6)
            time.sleep(0.001)
            writeCom1(5)
            time.sleep(0.001)
            writeCom1(9)
            time.sleep(0.001)

    elif anzahl_etagen==-2:
        for g in range (1,2*dpe):
            writeCom1(10)
            time.sleep(0.001)
            writeCom1(6)
            time.sleep(0.001)
            writeCom1(5)
            time.sleep(0.001)
            writeCom1(9)
            time.sleep(0.001)

    elif anzahl_etagen==-1:
        for g in range (1,1*dpe):
            writeCom1(10)
            time.sleep(0.001)
            writeCom1(6)
            time.sleep(0.001)
            writeCom1(5)
            time.sleep(0.001)
            writeCom1(9)
            time.sleep(0.001)

 
    elif anzahl_etagen==1:
        for g in range (1, 1*dpe):
              writeCom1(9)
              time.sleep(0.001)
              writeCom1(5)
              time.sleep(0.001)
              writeCom1(6)
              time.sleep(0.001)
              writeCom1(10)
              time.sleep(0.001)

    elif anzahl_etagen==2:
        for g in range (1, 2*dpe):
              writeCom1(9)
              time.sleep(0.001)
              writeCom1(5)
              time.sleep(0.001)
              writeCom1(6)
              time.sleep(0.001)
              writeCom1(10)
              time.sleep(0.001)
              
    elif anzahl_etagen==3:
        for g in range (1, 3*dpe):
              writeCom1(9)
              time.sleep(0.001)
              writeCom1(5)
              time.sleep(0.001)
              writeCom1(6)
              time.sleep(0.001)
              writeCom1(10)
              time.sleep(0.001)

              
    elif anzahl_etagen==0:
        print ("Sie sind bereits da.")

        fahrstuhlsteht()

        tuerauf()
        
def waehlen():
              
    if readCom1()==16:
        wahl_etage=0
        print wahl_etage

    if readCom1()==32:
        wahl_etage=1
        print wahl_etage

    if readCom1()==64:
        wahl_etage=2
        print wahl_etage

    if readCom1()==128:
        wahl_etage=3
        print wahl_etage

    anzahl_etagen=wahl_etage-position

    fahren(anzahl_etagen)
"dpe" bezeichnet dabei die Anzahl der Umdrehungen, um von einer Etage in die nächste zu gelangen, in unserem Fall liegt das bei etwa 165.

Bei der Position vor tuerauf und tuerzu, pause sowie dem fahrstuhllicht (alles Lämpchen am Modell) waren wir uns ob der Position im Quelltext nicht sicher.

Über Hilfe wären wir wirklich sehr dankbar!

urmelausdemeis

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 18:55
von EyDu
Hallo und willkommen im Forum!

Erstmal wäre es natürlich ganz hilfreich wenn du erzählen würdest, was nich funktioniert ;-) Gibt es eine Fehlermeldung, bleibt das Programm irgendwo hängen oder was für ein Ergebnis erwartest du? Von einmal durchscrollen würde ich sagen, dass du nirgends eine Funktion aufrufst und daher gar nichts passiert.

Außerdem ist es sinnvoll, wenn du ein minimales lauffägiges Beispiel zeigst. Dann steigt die Motivation dir zu helfen deutlich, da sich keiner mehr durch Tonnen an Code wühlen muss. Dein Code hat noch eine ganze Menge weitere Probleme, aber dazu fehlt es mir im Detail gerade ein wenig an Zeit. Es wird sich sicher jemand anders finden, der dazu noch etwas schreibt.

Sebastian

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 19:17
von urmelausdemeis
Hallo Sebastian,

vielen Dank für deine Antwort!

Zunächst zum Aufbau: Der Computer ist über die serielle Schnittstelle mit einem Camface verbunden, dieses mit einem selbstgebauten Fahrstuhlmodell.
Der Fahrstuhl ist per Faden mit einem Motor verbunden, im Hintergrund sind die Etagen eingezeichnet, an denen sich dieser "entlangbewegt". An jeder Etage befindet sich ein Knopf "rufen", jeweils mit den Zahlen von 1 (Erdgeschoss) über 2 (1. Etage) und 4 (2. Etage) bis 8 (3. Etage) versehen. Drückt man nun einen dieser Knöpfe, soll der Fahrstuhl in die entsprechende Etage fahren, da sich der ReadCom1()-Bereich verändert und dieser ja über die While-Schleife ausgelesen wird. Auf der anderen Seite des Modells, gibt es Knöpfe für Waehle(). Drückt man diese (mit den Zahlen von 16 bis 128 versehen), wird der elif-Teil der While-Schleife aufgerufen. Dieser funktioniert jedoch, wenn auch nur einmalig.

Ich mache das ganze nun einmal an einem Beispiel deutlich.

Ich starte das Hauptprogramm im über superfahrstuhl().
Gebe die "dpe"-Zahl ein, in diesem Beispiel 165.
Nun wird die Meldung "Rufe den Fahrstuhl oder waehle ein Stockwerk." ausgegeben. Soweit funktioniert auch alles.
Drücke ich jedoch nun den Knopf für die dritte Etage, sollte der Fahrstuhl zuerst die Zahl 8 ausgeben (da print ReadCom1) und anschließend die Meldung "Aufzug wird gerufen", dann die Etage, in der der Aufzug gerufen wurde.
Zuletzt soll sich der Aufzug in Bewegung setzen und in die 3. Etage fahren. Doch genau da liegt das Problem. Da macht er nicht das, was er soll.
Anschließend sollte man nun eig. ein Stockwerk wählen, in das der Fahrstuhl fahren soll. Dann kann ein Anderer den Aufzug wieder rufen und immer so weiter.

Fahren() funktioniert hingegen z.B. komplett, da kann der Fehler nicht liegen.

Ich hoffe, das war nun einigermaßen verständlich ;)

Danke im Voraus

urmelausdemeis

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 19:19
von BlackJack
@urmelausdemeis: Also ich möchte mich nicht durch so einen langen Quelltext mit globalen Namen und Sternchenimporten lesen, der voll von magischen Zahlen ist, deren Bedeutung man höchstens erraten kann.

Werdet den Sternchenimport los und schreibt echte Funktionen mit Argumenten und Rückgabewerten um die ganzen ``global``\s loszuwerden, statt Funktionen als blosse „Sprungmarken” für Quelltextabschnitte zu missbrauchen.

Die ganzen Quelltextwiederholungen in `fahren()` müssen auch nicht sein. Die Werte zu `anzahl_etagen` lassen sich doch recht einfach aus eben dieser Zahl errechnen, da braucht man nicht so viele ``if``/``elif``-Zweige für. Ebenso gehört der Quelltext innerhalb der ``for g``-Schleife selbst in eine Schleife über die Werte die geschrieben werden. Stell Dir mal vor die Steuerung würde auf einen Hochausfahrstuhl mit 40 Stockwerken ausgeweitet — das wird doch niemand ernsthaft *so* lösen wollen. Ähnliches gilt bei `rufen()` und `waehlen()`

Abkürzungen sollte man vermeiden wenn sie nicht allgemein bekannt sind. `dpe` könnte man vielleicht auch so benennen, dass man nicht extra erklären muss wofür der Name steht.

Falls `fahrstuhlsteht()` eine Funktion sein soll die den Fahrstuhl anhält, sollte sie besser `fahrstuhl_stoppen()` oder `fahrstuhl_anhalten()` heissen, und vielleicht sollte man sie am Ende von `fahren()` unbedingt ausführen und nicht nur in dem Fall in dem der Fahrstuhl gar nicht fahren muss. *Den* Fall könnte man dort auch ganz am Anfang abhandeln und den Fahrstuhl gar nicht erst fahrbereit machen (hier rate ich mal wieder was `fahrstuhlfaehrt()` machen soll).

Ansonsten könnte man noch die eigentliche Fahrstuhllogik von der konkreten Ansteuerung über das `camface`-Modul entkoppeln. Dann könnte man das später auch für andere Ansteuerungsmethoden umschreiben, einen Simulator schreiben, oder zusätzlich eine GUI aufsetzen.

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 19:35
von urmelausdemeis
Hallo BlackJack,

zunächst einmal Danke für Deine Hilfe!

Das mit dem Camface-Import war eine Vorgabe unseres Lehrers, der uns diese Aufgabe als Projekt gab.
In der Methode fahren() braucht man doch wenigstens eine Schleife, um zwischen Links- (<0) und Rechtsdrehung (>0) des Motors zu unterscheiden, ansonsten hast Du Recht, danke dafür!

fahrstuhlfaehrt() und fahrstuhlsteht() sind nur writeCom-Befehle, die das Fahrstuhllämpchen aus und einschalten. Tut mir leid, das habe ich vergessen zu erwähnen.

Grundsätzlich geht es darum, dass irgendwas in superfahrstuhl() bzw. in der Kommunikation zwischen superfahrstuhl() und rufen() sowie rufen() und fahren() nicht funktioniert. Wir vermuten den Fehler bei Anzahl_etagen=ruf_etage-position. Ist da irgendetwas falsch?


Gruß

urmelausdemeis

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 20:19
von BlackJack
@urmelausdemeis: Man muss nicht alles bei den Vorgaben des Lehrers belassen wenn man es besser machen kann. Bei Sternchenimporten verliert man schnell den Überblick welche Namen wo her kommen. Ich kenne das Modul nicht und musste mir deshalb den gesamten Quelltext aufmerksam durchlesen um heraus zu finden, dass es die Namen `readCom1`, `setCom1`, und `writeCom1`. `setCom1` hatte ich beim ersten drüber schauen übersehen.

Bei `fahren()` reicht eine Schleife. Man muss vorher nur enstprechend der Richtung festlegen über welche Werte die geht. Es gibt da so eine praktische Funktion zum „umdrehen” einer Liste (beziehunsweise eines beliebigen iterierbaren Objekts).

Da stimmt tatsächlich etwas mit der Kommunikation zwischen den Funktionen nicht: Ihr macht das über globale Variabelen und das auch nicht immer richtig. Versucht gar nicht erst diesen fehlerträchtigen ``global``\s-Kram zu verschlimmbessern sondern lasst die Funktionen über Argumente und Rückgabewerte kommunizieren, wie sich das in einem sauberen Programm gehört.

Ich habe ja weder ein Fahrstuhlmodell noch ein Camface, also ist das hier natürlich ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from contextlib import contextmanager
from time import sleep
from camface import readCom1, setCom1, writeCom1


def read_button_values():
    while True:
        value = readCom1()
        if value:
            yield value


@contextmanager
def doors_closed():
    writeCom1(128)      # Close doors.
    yield
    writeCom1(64)       # Open doors.


@contextmanager
def elevator_active():
    writeCom1(16)       # Light on.
    yield
    writeCom1(32)       # Light off.


def move(distance, rounds_per_distance):
    if distance != 0:
        with doors_closed():
            with elevator_active():
                stepper_values = [9, 5, 6, 10]
                if distance < 0:
                    stepper_values = reversed(stepper_values)
                for _ in xrange(abs(distance * rounds_per_distance) - 1):
                    for stepper_value in stepper_values:
                        writeCom1(stepper_value)
                        sleep(0.001)


def main():
    rounds_per_distance = 165
    value2position = dict((2**i, i % 4) for i in xrange(8))
    setCom1()
    writeCom1(0)
    position = 0
    for value in read_button_values():
        new_position = value2position[value]
        move(new_position - position, rounds_per_distance)
        position = new_position
        writeCom1(0)


if __name__ == '__main__':
    main()

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 20:39
von urmelausdemeis
Hallo Blackjack,

vielen Dank für deine Mühe!
Da wir bisher nur mit dem bisherigen System gearbeitet haben, ein paar Verständnisfragen. Den Methoden können wir doch nun z.B. auch andere Namen geben, z.B. tueren_schließen statt doors_closed, oder?
Die Variablen distance, rounds_per_distance kann man sicherlich auch beliebig umbenennen, oder?
Wieso muss man diese jetzt vorher nicht deklarieren?
Wir hatten vor Python oft mit Java gearbeitet, das ist also erst mal neu für uns.
Auch mit dieser Zeile:
value2position = dict((2**i, i % 4) for i in xrange(8))
haben wir noch Verständnisprobleme. Was bedeutet das dict und der Inhalt der nachfolgenden Klammer?

Vielen Dank noch mal!

urmelausdemeis

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 20:56
von heiliga horsd
Ein Dictionary ist ein Wörterbuch, Quasi eine Art Liste in der du einem bestimmten Wert (Key) einen bestimmten anderen Wert (Value) zuordnest.

Code: Alles auswählen

>>> dict((2**i, i % 4) for i in xrange(8))
{32: 1, 1: 0, 2: 1, 4: 2, 8: 3, 64: 2, 128: 3, 16: 0}
Sieht nach überfliegen deines Eingangscodes also nach Blackjacks Variante aus, um die Stockwerke den Zahlen zuzuordnen.

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 21:25
von urmelausdemeis
Alles klar, Danke, dann verstehe ich das nun auch. Variablen und Methoden kann man nun also frei umbenennen? value2position ist auch eine einfache Variable oder?

Gruß

urmelausdemeis

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 21:39
von cofi
Da es hier um eine Aufgabe geht und du so oft von "umbenennen" redest, sollte der Hinweis nicht fehlen, dass das Uebernehmen ohne Hinweis Plagiarismus ist.

Wenn du den Code nicht genug verstehst, um zu beurteilen, ob Umbenennen problematisch ist, dann wird das sehr schnell auffallen ;)

Re: Problem mit Fahrstuhlmodellsteuerung via Camface

Verfasst: Montag 25. Juni 2012, 21:52
von urmelausdemeis
Hallo,

es geht hier nicht um das Uebernehmen ohne Hinweis sondern lediglich um das "Verstehen" dieser für uns neuen Systematik. Wir wollen keinesfalls den Quelltext einfach kopieren und übernehmen!
Mit meinen Java-Kenntnissen würde ich sagen, dass das "Umbennen" ohne Probleme möglich ist, allerdings wollten wir hier auf Nummer sicher gehen.
Die Aufgabe wurde - so wie sie vorher von uns erstellt wurde - bereits benotet, wir wollen aber trotzdem den Fahrstuhl gerne noch zum Fahren bringen - wie gesagt ohne jede Bewertung.
Wir würden unserem Lehrer BlackJacks Quelltext daher gerne zeigen, natürlich mit dem Hinweis, dass er von BlackJack aus diesem Forum stammt.

Gruß
urmelausdemeis