threading Probleme

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

__deets__ hat geschrieben:Den globalen Zustand kann man natuerlich auch noch beseitigen, dazu habe ich gerade keine Lust. Ich denke mal es wird eh gefrickelt wie es nur geht... wie immer beim Pi.. *seufz*
Und falls der Quellcode von MegaPi als Vorbild genommen wird, ist auch keine Besserung zu erwarten. Bei der Beseitigung von global ist auch zu beachten, dass die Funktion 'sensorCallback' in einem anderen Thread läuft als 'work'.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: ob es eine gute Idee ist, ständig neue Reads abzusetzen, obwohl der vorherige möglicherweise noch gar nicht fertig ist, bezweifle ich mal. Normalerweise würde ein Callback den nächsten anstoßen.

Code: Alles auswählen

import time
from megapi import MegaPi

class UltrasonicSensor(object):
    def __init__(self, bot, port):
        self.bot = bot
        self.port = port
        self._request_callback()
        self.value = 0

    def _request_callback():
        self.bot.ultrasonicSensorRead(self.port, self._callback)

    def _callback(self, value):
        self.value = value
        self._request_callback()

def main():
    bot = MegaPi()
    bot.start()
    sensor = UltrasonicSensor(bot, 7)
    while True:
        if sensor.value < 50:
            stop()
        else:
            forward()
        time.sleep(0.1)

if __name__ == '__main__':
    main()
emilio20
User
Beiträge: 22
Registriert: Donnerstag 17. Oktober 2013, 21:08

Hallo Sirus2,
ich habe noch mal eine Verständnisfrage. In der SPS Programmierung kann ich einen Funktionsbaustein Programmieren der Ein und Ausgangsvariablen hat.
Wenn die Logik zum auslesen des Sensors dieselbe ist kann ich diese für Ultraschall und Kompasse nutzen. Ich übergebe dann an die Funktion den Port und den Befehl und erhalte die jeweilige Variable zurück.
Ich habe mal das Programm so abgeändert weiß aber nicht ob das so richtig ist?

Code: Alles auswählen

 import time
    from megapi import MegaPi
     
    class ReadSensor(object):
        def __init__(self, bot, port, funktion):
            self.bot = bot
            self.port = port
            self.funktion = funktion
            self._request_callback()
            self.value = 0
     
        def _request_callback():
            self.bot.self.funktion(self.port, self._callback)
     
        def _callback(self, value):
            self.value = value
            self._request_callback()
     
    def main():
        bot = MegaPi()
        bot.start()
        Ultrasonic = ReadSensor(bot, 7, ultrasonicSensorRead)
        Compass = ReadSensor(bot, 8, compassRead)
        while True:
            if Ultrasonic.value < 50:
                stop()
            else:
                forward()
            if Compass.value < 50:
                stop()
            else:
                forward()
            time.sleep(0.1)
     
    if __name__ == '__main__':
        main()



__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3 wo du recht hast... allerdings ist auch dein Ansatz nur ein erster Schritt IMHO. Denn so ballert man die serielle Verbindung zu, und ggf. kommen Motordaten oder andere nicht verzoegert zum Zuge. Da waere wahrscheinlich noch ein Throttling obendrauf nett.

@emilio20 Programmieren ist nicht raten. self.bot.self.funktion funktioniert nicht (und das es das nicht tut kannst du auch alleine ausprobieren).

Was du brauchst ist

Code: Alles auswählen

Ultrasonic = ReadSensor(7, self.ultrasonicSensorRead)
als Parameter. Den bot als Argument kann man dann gleich eliminieren, weil er eh an der "bound method" die du uebergeben hast "dranhaengt".


Und zum Aufruf in _request_callback sollte

Code: Alles auswählen

self._funktion(self.port, self._callback)
ausreichen.
emilio20
User
Beiträge: 22
Registriert: Donnerstag 17. Oktober 2013, 21:08

Hallo
das Script von Sirus2 funktioniert leider nicht. Fehler erhalte ich keinen wenn ich es Starte.

Code: Alles auswählen

import time
from megapi import MegaPi
 
class UltrasonicSensor(object):
    def __init__(self, bot, port):
        self.bot = bot
        self.port = port
        self._request_callback()
        self.value = 0
 
    def _request_callback():
        self.bot.ultrasonicSensorRead(self.port, self._callback)
 
    def _callback(self, value):
        self.value = value
        self._request_callback()
 
def main():
    bot = MegaPi()
    bot.start()
    sleep(1)
    sensor = UltrasonicSensor(bot, 7)
    while True:
        try:
            if sensor.value < 50:
                print "Stop"
            else:
                print "Forword"
            print "distance:"+str(sensor.value)+" cm"
            time.sleep(0.1)
        except Exception,ex:
            print str(ex)
 
if __name__ == '__main__':
    main()




das geht

Code: Alles auswählen

from megapi import *

def onDistance(dist):
	print "distance:",dist
	if dist<50 :
		#bot.encoderMotorRun(1,0);
		#bot.encoderMotorRun(2,0);
                print"Stop"
	else:	
                #bot.encoderMotorRun(1,-100);
                #bot.encoderMotorRun(2,100);
                print "FWD"
def main():	
        bot = MegaPi()
	bot.start()
	while(1):
		try:
                        sleep(0.2)
			bot.ultrasonicSensorRead(7,onDistance);
		except Exception,ex:
			print str(ex)

if __name__ == '__main__':
        main()




__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was heisst denn "geht nicht"? Kommt keine Sensorwert an?
emilio20
User
Beiträge: 22
Registriert: Donnerstag 17. Oktober 2013, 21:08

Hallo
Das Script arbeitet nicht erhalte keinen rückgabewert

testUS2.py von Sirus2

Code: Alles auswählen

pi@raspberrypi:~ $ cd robot
pi@raspberrypi:~/robot $ python testUS2.py
init MegaPi
<megapi.mSerial instance at 0x7674de90>



testUS3 das andere das geht.


Code: Alles auswählen


pi@raspberrypi:~ $ cd robot
pi@raspberrypi:~/robot $ python testUS3.py
init MegaPi
<megapi.mSerial instance at 0x76796d28>
distance: 155.379302979
FWD
distance: 155.810348511
FWD
distance: 155.810348511
FWD
distance: 155.39654541
FWD
distance: 155.810348511
FWD
distance: 155.379302979
FWD
distance: 155.379302979
FWD
distance: 155.913787842
FWD
distance: 155.5
FWD
^Cpi@raspberrypi:~/robot $

__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Woher weisst du denn, das es nicht geht? Es sind keine print-anweisungen enthalten, die das laufen dokumentieren. Und damit sind wir auch schon beim pro-tipp: bau doch mal prints ein, um zu sehen, wo das programm ist....
emilio20
User
Beiträge: 22
Registriert: Donnerstag 17. Oktober 2013, 21:08

Hallo
sind doch enthalten ? Zeile 26, 28 und 29

Das Programm kommt bis zu sensor = UltrasonicSensor(bot, 7)
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hm, da hab ich mich mit dem scrollen selbst verwirrt & die nicht gesehen.

Aber das es nicht klappt wird bei genauerem hinschauen klar... und dem waelzen des Sourcecodes vom MegaPi: tatsaechlich ist es ok, so wie ich es gemacht habe, permanent neu eine Anfrage zu schedulen. Denn die Callbacks werden ueber eine eindeutige ID abgelegt.

Was Sirius macht geht hingegen nicht, weil der Callback in einem Hintergrund-Thread aufgerufen wird, und das re-schudulen in demselbigen verhindert, dass das Programm weiter laeuft. Das nehem ich zumindest an.

Statt also selbst in UltrasonicSensor _request_callback aufzurufen, benenn das um in "read_sensor", und ruf es auf sensor in deiner Hauptschleife auf.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@emilio20: zu den ersten beiden Zeilen der Ausgabe finde ich aber kein print. Wenn Du das Programm wirklich so ausgeführte wurde, sollte Python in Zeile 21 mit einem NameError ausssteigen.

@__deets__: es wird bei ultrasonicSensorRead nicht nur ein Callback gesetzt, sondern auch jedesmal etwas über die serielle Schnittstelle geschickt. Was Du da zu weiterlaufen, etc. annimmst, finde ich nicht im Quellcode.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius: das mit der Kommunikation ist richtig, aber danach kommen ja ggf. Motorsteuerbefehle - und ggf. blockiert das senden, wenn der buffer voll ist.

Zum Rest:
https://github.com/Makeblock-official/P ... api.py#L85
https://github.com/Makeblock-official/P ... pi.py#L307 (im Thread)
https://github.com/Makeblock-official/P ... pi.py#L331 (dann auch im Thread)

Damit wird also im Lesethread geschrieben, *warum* sich das verklemmt kann ich ohne Debugger auch nicht nachvollziehen, halte es aber schon fuer ziemlich wahrscheinlich - denn sonst haette emilio ja seine prints in der Konsole.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: ich verstehe nicht, was Du mit den Code-Zeilen sagen willst. Ich beziehe mich auf
Zeile 121, dort wird was über die Serielle Leitung geschickt.
emilio20
User
Beiträge: 22
Registriert: Donnerstag 17. Oktober 2013, 21:08

Hallo
wenn ihr nochmal ein Beispiel für mich habt wäre ich euch dankbar. Kann leider nicht nachvollziehen von was ihr redet.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3 die Zeilen belegen, dass dein re-scheduling im event-callback dazu fuehrt, dass der eigentlich nur fuer das lesen der seriellen Schnittstelle zustaendige Thread ploetzlich auch schreibt. Ich bezweifele, dass das so gewollt ist.

@emilio: Sirius3 hat einen Fehler in dem von dir geposteten Skript aufgezeigt, solange du den nicht behebst, oder das Skript postest, das du *wirklich* laufen laesst, kann man da wenig machen.

Und ich habe dir auch schon Hinweise gegeben, wie du dem Problem selbst auf die Spur kommen kannst - durch print-debugging, und du kannst zB die UltrasonicSensor so modifizieren, dass sie *kein* callback request macht, um zu schauen, ob dann deine Hauptschleife weiterlaeuft. Debuggen gehoert zum programmieren. Sonst hiesse es Eintippen.
Antworten