- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 5 von 5

Thema: Multithread in Basic?

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2004
    Beiträge
    378

    Multithread in Basic?

    Anzeige

    Powerstation Test
    Hi Leute,

    wie macht man zwei Schleifen unter Basic die "gleichzeitig" laufen?

    So nen art Multithread mach ich momentan so.

    Thread:
    gosub A
    gosub B
    gosub B
    goto Thread


    A:
    xxxxxxxx
    Code..
    RETURN


    B:
    xxxxxxxx
    Code..
    RETURN


    C:
    xxxxxxxx
    Code..
    RETURN


    ich müsste aber zwei Schleifen (Zähler) gleichzeitig laufen lassen.
    Schleife in Schelife geht leider nicht da die Schleife Start und Return bedingung hat wenn ein Pin High b.z.w Low wird, ich zähle damit meine
    Radimpulse aus 0 --> 200ms.
    Das bremst natürlich mein Programm

    Da ich aber schon mal gehört habe das manche einen Multihread in Basic
    Programmiert haben (AVR) könnte es ja sein das es geht?!

    Technisch kann ich mir des leider net vorstellen da ich mit Basic nur springen kann und ja dann der Code ausgeführt wird und er erst wieder
    zurückspringt wenn er fertig ist und nicht nach Maschienenzyklen?!

    Danke an alle

    By Ulli

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.08.2004
    Ort
    Stuttgart
    Alter
    49
    Beiträge
    851
    Hallo!

    1. Parallel geht mal gar nichts!
    2. Man kann nur quasi parall, also abwechslend nacheinander sehr schnell die einzelnen Tasks bedienen

    Wenn du das machen willst mußt die selber eine Zeischeibe aufbauen die deinen Anforderungen enstspricht. Darfst keine Zeiten vernichten durch Pause-Befehle und mußt eine IDLE-Loop aufbauen als zentrales Hauptpgramm. Das ist aber alles selbst zu schreiben und dem jeweiligen Fall entsprechend!

    Im einfachsten Fall geht man her und schreibt sich eine Hauptschleife in der einfach die Tasks (Unterporogramme 1...n) aufgerufen werden. Das Durchlaufen der Unterprogramme muß entweder permanent so schnell wie möglich erfolgen oder wenn es zeitgenau sein muß immer gewartet werden auf ein Ereigniss das die ganzen Tasks nacheinander ablaufen läßt (z.B. einem Timer-Interrupt).

    Zudem darf in keinem Unterprogramm zu viel Code stehen weil es in der Summe dann zuviel Zeit brauchen würde. Mußt also genau ausknobeln.

    Weiterhin mußt zusehen das jedes Unterprogram wenn es länger braucht auch mehrfach wie eine Art Schrittkette funktioniert. Also nur einen kleinen Teil seiner Aufgabe erledigt und dann erst beim nächsten Aufruf gleich in den nächsten Aufgabenteil springt und somit nach vielen Aufrufen dann ein komplexes Programm (Einzeltask) abgearbeitet hat.

    Man kann das Ganze noch weiter treiben und so eine Art Flags als Bitvariablen zuwischen Hauptprogramm (Taskmanager) und Unterprogrammen (Tasks) austauschen die anzeigen ob die Abarbeitung nötig ist, oder ob Zeit gespart werden kann.

    Grpße Wolfgang

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    29.01.2004
    Beiträge
    2.441
    Technisch kann ich mir des leider net vorstellen da ich mit Basic nur springen kann und ja dann der Code ausgeführt wird und er erst wieder
    zurückspringt wenn er fertig ist und nicht nach Maschienenzyklen?!
    Wenn du die einzelnen Routinen über einen Timer aufrufst, kannst du erreichen, dass er nach eine von dir definierten Zeit zur nächsten Routine springt und nicht erst wenn er mit der einen fertig ist.

    Das ergibt natürlich noch lange kein richtiges Multithreading, aber oft reicht es, wenn man nur wenige wirklich zeitkritische Routinen über einen Timer aufruft und den Rest in einer Schleife (so wie deine Sprungliste oben) nacheinander abarbeiten lässt.

    So ein µC ist ja ziemlich flott und bei der Abfrage von Sensoren und vielen anderen Dingen kommt es meist nicht auf ein paar mS an.
    Wenn der Controller da per Timer regelmässig zwischendurch rausspringt um einen Radencoder abzufragen oder einen Schritt auf den Schrittmotor zu geben stört das meist nicht.


    Radimpulse aus 0 --> 200ms.
    Das bremst natürlich mein Programm
    Radencoder würde ich an einen externen Interrupt anschliessen und in der entsprechenden Interrupt-Routine jedesmal eine Zählervariable um 1 hochzählen, wenn ein neuer Interrupt kommt.
    Auf diese Zählkervariable kannst du dann in deiner normalen Routine zugreifen und hast (mehr oder weniger) automatisch immer den aktuellen Stand.

    PS: ich sehe gerade, BlueNature war schneller und hat deine Frage schon beantwortet.

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.08.2004
    Ort
    Stuttgart
    Alter
    49
    Beiträge
    851
    Servus Recycle!

    Das mit dem Interrupt ist für schnelle Impulse eh unabdinglich. Da muß ich dir recht geben. Aber das wollte ich ncith alles schreiben weil es ein recht kompliziertes Thema ist bei dem ich am liebsten einen Test-Pin toggle um daran die Flanken der Tasks real zu messen.

    Wenn ich externe Interrupts mit einem Increment auswerte um damit eine globale Variable hochzuzählen setze ich noch im Interrupt nach dem Incrementieren sofort ein Flag das ich mit definiert habe. Das erleichtert den betroffenen Tasks dann zu entscheiden ob die Zählvariable sinnvoll ist neu zu berechnen oder ob es unterschlagen werden kann. Ist das Flag da, wird eben in der folgenden Zeit eiene neue Berechnung durchgeführt und ist diese erledigt wird das Flag wieder zurückgesetzt um das Ganze wieder "scharf" zu schalten. So kann man mit Interrupts sehr effektiv arbeiten.

    Grüße Wolfgang

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    23.02.2005
    Beiträge
    33
    Mein Vorschlag kommt zwar spät, aber vielleicht hilft es dem Ein oder Anderen weiter der ein ähnliches Problem mit der "Gleichzeitigkeit" von Abläufen hat.

    Will man auf Timergeschichten und Threads verzichten, eignet sich folgende Logik:

    Aufg1=“start“
    Aufg2=“start“

    Do While Aufg1<>”Ende” Or Aufg2 <>”Ende”
    Select Case Aufg1
    Case “start”: tu irgendwas, setze Aufg1=”Action1”
    Case “Action1”: tu irgendwas, setze Aufg1=”Action2”
    Case “Action2”: tu irgendwas, setze Aufg1=”Verlasse”
    Case “Verlasse” tu irgendwas, setze Aufg1="Ende"
    End Select

    Select Case Aufg2
    Case “start”: tu irgendwas, setze Aufg2=”Action1”
    Case “Action1”: tu irgendwas, setze Aufg2=”Action2”
    Case “Action2”: tu irgendwas, setze Aufg2=”Verlasse”
    Case “Verlasse” tu irgendwas setze Aufg2="Ende"
    End Select
    Loop

    Zur Erklärung, die Do While-Schleife wird solange durchlaufen bis Aufgabe1 und Aufgabe2 ihre Endebedingung zugewiesen bekommen.

    Die Variable Aufg1 und Aufg2 wird verwendet um innerhalb der zugehörigen Select Case-Anwiesung eien Logischen Ablauf zu steuern.

    Zugegeben, man muß sich mit dieser Art der Logik wirklich auseinandersetzen um den gewünschten Ablauf zu erreichen, aber es funktioniert und ist eine oft angewandte Programmiertechnik!

    MfG Uli88

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test