python zu langsam dafür?

  • Hallo

    Könnte es sein, dass python dafür einfach zu langsam ist, oder muss doch noch irgendwo ein Fehler vergraben sein?

    Es geht um die Ansteuerung des 7-Segment Displays tm1637.
    Ich habe dafür ja eine C++ Implementierung geschrieben. Siehe LED 4 Segment I2C Display

    Und jetzt kämpfe ich mit einer davon abgeleiteten python implementierung, die aber leider zu keinem Ergebnis führt.
    Da es hier offenbar um doch sehr schnelle Signalwechsel auf den beiden GPIO-Pins geht, befürchte ich, dass das nicht Funktionieren eben daran liegt, dass python einfach zu langsam dafür ist.

    Könnte ich da richtig liegen?

    Das wäre z.B. die Funktion, die _ein_Byte_ zum Display schiebt.
    Da bleibt das Ding dann in der while-Schleife hängen, weil offenbar das ACK nicht kommt.

    Gruß
    Franz

  • Ich finde die Methode, in einer Endlosschleife permanent einen Zähler hochzujagen und erst ab einem bestimmten Wert was zu tun, ziemlich unglücklich gewählt. Übersetzt heißt das, dass dein Python-Skript um die 200 Abfragen losschickt, bevor der Pin-Modus geändert wird. Wenn ich das richtig sehe, würde ich den ganzen If-Block weglassen und am Schluss der While-Schleife eine Pause von wenigen Millisekunden einlegen... Hat u.a. auch den Vorteil, dass das Python-Skript dann nicht den Prozessor vollständig belastet.

    Ansonsten würde ich ganz auf Anfang zurückgehen und eines der elementarsten Sätze beim Programmieren loslassen: Kann man ein Problem nicht lösen, zerlegt man es in einzelne Teilprobleme und testet diese unabhängig voneinander. Konkret: Kopier dir dein Skript und in der Kopie schmeißt du alles Unnötige raus. Dann kannst du gut testen, ob und warum der Quellcode funktioniert oder eben nicht funktioniert...

  • Hi

    Die Vorgehensweise, also der genaue Programmmablauf entstammt direkt einem Beispielprogramm in C, welches ich auf der Herstellerseite gefunden hatte.

    In C++ funktioniert das auch gut so.
    Ich denke (habs nicht nachgeprüft) dass dort auch der Zähler kaum mal über 5 hochzählen wird.

    Und ich wollte das natürlich mal so nahe an einem funktionierenden Beispiel wie möglich ausprobieren, bevor ich mir Verbesserungen überlege, die dann vielleicht erst recht wieder nicht funktionieren.

    Das Thema ist jetzt also weniger ob es eine CPU-Zeit schonendere Methode gäbe. Ausser das Display könnte damit zur Zusammenarbeit bewegt werden.

    Ich vermute viel mehr, dass die Signalwechsel _vor_ der Schleife zu langsam sind, so dass das Display das nicht akzeptiert und daher die Leitung nicht runterzieht.
    Wenn das Ding die Leitung nicht runterzieht, wird wohl auch kein Interrupt helfen. Weil der kommt dann ja auch nicht.

    Gegenstand der Frage ist also nicht die CPU-Zeit fressende Schleife, sondern die Verarbeitungsgeschwindigkeit der paar Zeilen vor der Schleife.

    Gruß
    Franz

    ... und des Rätsels Lösung:

    for i in range(0,7): <<<<-- zählt nicht von 0 bis 7 sondern nur von 0 bis 6

    Dem Display fehlte daher noch ein Bit und deshalb gabs auch kein ACK.

    Einmal editiert, zuletzt von sd582 (27. Februar 2015 um 06:04)

  • Hallo,

    grundsätzlich ist Python nicht zu langsam. Es gibt z.B. wohl auch Projekte, die machen Echtzeit Gesichtserkennung mit Python.

    Die Fage ist dann halt nur, wie schnell die Hardware ist und was da sonst noch drauf läuft ;)

    C / C++ Code 1:1 in Python umzusetzen ist in der Regel keine gute Idee, weil der Code dann sehr "un-pythonisch" wird, was u.a. in einer suboptimalen Peformance resultieren könnte.

    Und wenn du auf eine bestimmtes Signal wartest, dann würde ich das in der Tat auch eher interupt-driven / event-driven machen. Der Event-Listener lauscht ja dann im Hintergrund und löst eine Callback-Funktion aus, wenn das Event eintritt. Gut, wenn man das selber programmieren muss, weil's kein fertiges Modul gibt, ist das natürlich alles andere als trival ;)

    Und wenn du wissen willst, wo dein Python-Code wie viel Zeit verbringt: Python hat ein Profiler-Modul an Bord.

    Gruß, noisefloor

  • Naja wir kennen nicht den C code, ich kann mir aber auch nicht vorstellen das der C code exakt genau so aussieht - oder das es nur an der Passage liegt die du gepostet hast...

    Diese ganzen while Sachen bremsen halt generell aus, der Rest des Scripts wird solange blockiert und macht nichts.
    Und die while Schleife wird mit absoluter Sicherheit so wie du es hier gepostet hast auch komplett bis 200 hoch zählen sobald sie gestartet wurde, das sagt jedenfalls der Code aus. Aber Warum sollte sie das? Den Sinn dahinter versteh ich absolut nicht :s

    Also Ich bin mir ziemlich sicher das es am Code liegt wenns nicht schnell genug sein sollte. Es gibt immer Programmiersprachen-Abhängige Sachen die man optimieren kann.

  • Und nochmal:

    ... und des Rätsels Lösung:

    for i in range(0,7): <<<<-- zählt nicht von 0 bis 7 sondern nur von 0 bis 6

    Dem Display fehlte daher noch ein Bit und deshalb gabs auch kein ACK.

    Die while schleife kommt garnicht zum hochzählen, weil typischerweise die Leitung bereits low ist.
    Wie gesagt, die Funktionalität der Schleife ist offenbar eine reine Vorsichtsmaßnahme, für den Fall, dass sich das ACK doch einmal verzögern sollte.

    Und in diesem Fall ist es absolut gewünscht, dass das Script nichts anderes macht, bevor die Schleife beendet werden kann!

    Gruß
    Franz

  • Und noch mal:

    die while Schleife wird mit absoluter Sicherheit so wie du es hier gepostet hast auch komplett bis 200 hoch zählen sobald sie gestartet wurde [...]

    Wenn, dann zählt sie also 100% bis 200 hoch. Du sagtest vorher aber "kaum mal über 5 hochzählen"... :s

    Da die Schleife einfach nur hoch zählt, ohne jegliche Verzögerung, kann es also unterschiedlich schnell fertig sein. Wer garantiert also das diese Vorsichtsmaßnahme ausreicht? Wäre es dann nicht besser eine tatsächliche Prüfung durchzuführen oder tatsächlich so lange zu warten bis ein ACK stattfindet?


    Und da du ja anscheint auch selber schon einen Fehler gefunden hast (die for Schleife) scheint ja dann doch in python etwas anders umgesetzt zu sein als es in C der Fall ist, denn du schriebst ja das es im Original wunderbar funktionieren würde

    Wir kennen wie gesagt nicht die original Code und vielleicht tuste den auch absichtlich immer noch nicht zeigen :huh: :-/

  • Hm, aber das sieht irgendwie anders aus als er uns hier gezeigt hat :s

    &quot;Python&quot;


    [code=php]
    def writeByte( self, data :(
    for i in range(0,8):
    IO.output( self.__Clkpin, LOW)
    if(data & 0x01):
    IO.output( self.__Datapin, HIGH)
    else:
    IO.output( self.__Datapin, LOW)
    data = data >> 1
    IO.output( self.__Clkpin, HIGH)
    #endfor

    # wait for ACK
    IO.output( self.__Clkpin, LOW)
    IO.output( self.__Datapin, HIGH)
    IO.output( self.__Clkpin, HIGH)
    IO.setup(self.__Datapin, INPUT)

    while(IO.input(self.__Datapin)):
    time.sleep(0.001)
    if( IO.input(self.__Datapin)):
    IO.setup(self.__Datapin, OUTPUT)
    IO.output( self.__Datapin, LOW)
    IO.setup(self.__Datapin, INPUT)
    #endif
    # endwhile
    IO.setup(self.__Datapin, OUTPUT)
    # end writeByte
    [/php]

    Vs.

    &quot;C&quot;

    [code=php]
    void tm1637Display::writeByte(BYTE data)
    {
    for(int i=0;i<8;i++) //send 8bit data
    {
    gpioWrite(clockPin,LOW);
    gpioWrite(dataPin, (data & 0x01) ? HIGH : LOW); //LSB first
    data >>= 1;
    gpioWrite(clockPin,HIGH);
    }
    gpioWrite(clockPin,LOW); //wait for the ACK
    gpioWrite(dataPin,HIGH);
    gpioWrite(clockPin,HIGH);
    gpioSetMode(dataPin,INPUT); // switch datapin for Input
    int c = 0;
    while(gpioRead(dataPin))
    {
    if(++c == 200)
    {
    gpioSetMode(dataPin,OUTPUT); // switch datapin for output
    gpioWrite(dataPin,LOW);
    c =0;
    gpioSetMode(dataPin,INPUT);
    }
    }
    gpioSetMode(dataPin,OUTPUT);
    }
    [/php]

  • Mannohmann!

    Die schleife zählt nicht nur einfach hoch!
    Die Schleife zählt nur so lange hoch, solange der Eingang nicht auf Low ist!
    Und wenn alles passt, dann ist der Eingang auf Low - und zwar noch vor dem Eintritt in die Schleife.

    Muss ich da wirklich den Code eines mir fremden Chinesen verteidigen?

    Ich hab den Mist nur nach python übertragen (von C) und wollte dabei möglichst wenig ändern, weil ich noch nicht kapiert hatte, was das da eigentlich genau macht.

    Inzwischen ist mir sonnenklar was das Zeugs macht und das ist schon ok so als Notbremse (Panikfunktion)

    Darfst mir ruhig glauben. Ich bin seit 30 Jahren Softwareentwickler im Embeded Bereich und arbeite mit verschiedensten Sprachen von Assembler über ein paar exoten, über Java, C/C++ bis C#.

    Mein Problem war schlicht und einfach dass ich ein Bit zu wenig gesandt hatte.
    >>> for i in range(0,7): <<<<-- zählt nicht von 0 bis 7 sondern nur von 0 bis 6

    PS. das dort ist nicht der C Code.
    Das ist bereits ein stark überarbeteter C++ Code und ein Post darunter der optimierte pyton code.

    PPS.

    Das hier ist der original C Code:
    http://www.sc2web.net/Downloads/TM1637OriginalC.ZIP

    PPPS. ich habe den originalcode deshalb nicht gezeigt, weil er für meine Frage völlig unerheblich war!

    Die Frage war, ob es daran liegen kann, dass python vielleicht dafür zu langsam ist!

    Und natürlich habe ich in python etwas anders gemacht, weil for( int i=0;i<8;i++) funktioniert in python nun mal nicht.

    Sorry, dass ich mich erdreistet habe, zu fragen, ob python vielleicht langsam sein könnte :(

    Einmal editiert, zuletzt von sd582 (27. Februar 2015 um 13:22)

  • Darfst mir ruhig glauben. Ich bin seit 30 Jahren Softwareentwickler im Embeded Bereich und arbeite mit verschiedensten Sprachen von Assembler über ein paar exoten, über Java, C/C++ bis C#.

    Soll ich jetzt ehrfürchtig auf die Knie fallen und um Gnade winseln? :X

    Sorry, dass ich mich erdreistet habe, zu fragen, ob python vielleicht langsam sein könnte :(

    Wenn du seit 30 Jahren Softwareentwickler bist, müsstest du eigentlich auch wissen das es gewisse Unterschiede je nach Programmiersprache gibt. Nur weil etwas in C schnell bearbeitet wird bedeutet das nicht zwangsläufig das der selbe Weg 1:1 auch genau so schnell in Java (oder python) bearbeitet wird.

    Ich bleib dabei das ich diese while Schleife anders machen würde, und das ist weiterhin nicht über ein künstliches delay/sleep/whatever - sowas ist eh Mist
    Da du uns nur die writeByte Funktion gezeigt hast gehe ich mal davon aus das du dir sicher bist, es läge daran :huh:
    Dann überdenke noch mal diese Funktion und überlege was dort eigentlich genau passieren soll und wie man das vielleicht auch anders schreiben könnte - es gibt ja bekanntlich immer mehrere Wege. Der jetzige mag funktionieren aber muss ja nicht der beste sein.

  • Er will's einfach nicht glauben, dass ich einfach ein Bit zu wenig geschickt habe.

    Liest du nicht was man schreibt? Oder ist es dir egal was man schreibt und du musst unbedingt auf einer völlig unnötigen Schleife rumhacken, die man nach aktuellem Wissensstand auch einfach weglassen kann?

    Ich wollte mit der Anmerkung meiner Softwareentwicklerlaufbahn lediglich darauf hinweisen, daß ich nicht auf der Brennsuppe dahergeschwommen bin - dass ich schon weiß, wovon ich spreche.

    >>> Nur weil etwas in C schnell bearbeitet wird bedeutet das nicht zwangsläufig das der selbe Weg 1:1 auch genau so schnell in Java (oder python) bearbeitet wird.


    Genau deshalb hab ich ja gefragt, ob python dafür vielleicht zu langsam sein könnte.

    Schluss jetzt!
    Die Sache ist seit gestern schon erledigt und klar.
    Da muss man nicht auf einer unwichtigen Schleife rumreiten!

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!