- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 6 von 6

Thema: task_ACS(); oder setACSPwr...(); tut nicht

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2008
    Beiträge
    9

    task_ACS(); oder setACSPwr...(); tut nicht

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hi,
    ich wolte einen ACS-Eventhandler schreiben welcher versucht den Hindernissen auszuweichen und die Entfernung zum Hinderniss berücksichtigt und dementsprechend enge Kurven macht indem die ACS-Leistung laufend geändert wird um festzustellen wie nahe das Honderniss ist.
    Code:
    enum direction {Right, Left, Forwd, Backwd}
    
    void zuruecksetzendrehen (enum direction dir)
    {
        setLEDs(0b100000);
        move (50, BWD, DIST_MM(150), false);
        while (!isMovementComplete())
        {
            task_motionControl();
        }
        
        if (dir==Right)
        {
            rotate (40, RIGHT, 90, false);
            while (!isMovementComplete())
            {
                task_motionControl();
            }
        };
        
        if (dir==Left)
        {
            rotate (40, LEFT, 90, false);
            while (!isMovementComplete())
            {
                task_motionControl();
            }  
        }
        
        changeDirection(FWD);
    }
    
    void ACSHandler_UmfahrenNahe(void)
    {
        setLEDs(0b111111);
            setACSPwrLow();
            task_ACS();
            mSleep(100);
             while (obstacle_left)
             {
                 if (obstacle_right && obstacle_left)
                 {
                     zuruecksetzendrehen(Right);
                     setLEDs(0b111111);
                 }
    
                 task_ACS();
                 mSleep(100);
                 moveAtSpeed(100,30);
                 task_motionControl();
             }
            
            while (obstacle_right)
            {
                 if (obstacle_right && obstacle_left)
                 {
                     zuruecksetzendrehen(Right);
                     setLEDs(0b011011);
                 }
    
                 task_ACS();
                 mSleep(100);
                 moveAtSpeed(30,100);
                 task_motionControl();
            }
        setLEDs(0b111111);
    }
    
    void ACSHandler_UmfahrenMittel (void)
    {
        setLEDs(0b011011);
        setACSPwrMed();
            task_RP6System();
            mSleep(100);
             while (obstacle_left)
             {
                 if (obstacle_right && obstacle_left)
                 {
                     zuruecksetzendrehen(Right);
                     setLEDs(0b011011);
                 }
                 
                 setACSPwrLow();
                 task_ACS();
                 mSleep(100);
                 if (obstacle_left || obstacle_right)
                     ACSHandler_UmfahrenNahe();
                 
                 setACSPwrMed();
                 task_ACS();
                 mSleep(100);
                 moveAtSpeed(100,50);
                 task_motionControl();
             }
            
            while (obstacle_right)
            {
                 if (obstacle_right && obstacle_left)
                 {
                     zuruecksetzendrehen(Right);
                     setLEDs(0b011011);
                 }
                 
                 setACSPwrLow();
                 task_ACS();
                 mSleep(100);
                 if (obstacle_left || obstacle_right)
                     ACSHandler_UmfahrenNahe();
                 
                 setACSPwrMed();
                 task_ACS();
                 mSleep(100);
                 moveAtSpeed(50,100);
                 task_motionControl();
            }
        setLEDs(0b001001);
    }
    
    void ACSHandler_UmfahrenWeit(void)
    {
        setLEDs(0b001001);
        task_ACS();
        mSleep(100);
        while (obstacle_left)
        {
            if (obstacle_right)
            {
                zuruecksetzendrehen(Right);
                setLEDs(0b001001);
            }
                 
            setACSPwrMed();
            mSleep(100);
            task_ACS();
            mSleep(100);
            if (obstacle_left || obstacle_right)
                ACSHandler_UmfahrenMittel();
                 
            setACSPwrHigh();
            moveAtSpeed(100,70);
            task_motionControl();
            task_ACS();
            mSleep(100);
        }
            
          while (obstacle_right)
          {
                if (obstacle_right && obstacle_left)
                 {
                     zuruecksetzendrehen(Right);
                     setLEDs(0b001001);
                 }
                 
                 setACSPwrMed();
                 mSleep(100);
                 task_ACS();
                 mSleep(100);
                 if (obstacle_left || obstacle_right)
                     ACSHandler_UmfahrenMittel();
                 
                 setACSPwrHigh();
                 moveAtSpeed(70,100);
                 task_motionControl();
                 task_ACS();
                 mSleep(100);
            }
        setLEDs(0b000000);
    }
    ich habe nach jedem Aufruf von task_ACS() mSleep(100) aufgerufen um der Funktion Zeit zu geben sich abzuarbeiten um zu verhindern dass die Funktion noch garnicht fertig ist wenn obstacle_right oder obstacle_left abzufragen.

    Der Roboter geht aber sofort nach dem Aufruf von ACSHandler_UmfahrenWeit() in ACSHandler_UmfahrenMittel() und sofort danach in ACSHandler_UmfahrenNahe() wie die LEDs mir sagen.

    Kann es sein dass ich auch den Funktionen setACSPwr...() Zeit geben muss bevor ich task_ACS() aufrufen kann?

    Gruß Jan Lukas

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    Nein so geht das leider nicht. Der Controller auf dem Mainboard muss viele Aufgaben quasi parallel ausführen.

    Wenn Du task_IRGENDWAS Funktionen aus der RP6Lib verwendest, darfst Du NIRGENDWO im Programm mSleep verwenden. Naja - jedenfalls nicht länger als vielleicht knappe 10ms.
    Die task_IRGENDWAS Funktionen sind drauf ausgelegt SEHR OFT aufgerufen zu werden.
    Die haben intern eigene Timer und führen ihre jeweilige aufgabe in gewissen mindest zeitabständen aus. Du darfst sowas wie ACS und motionControl aber nicht zu lange warten lassen... die müssen sich ständig updaten sonst funktionierts nicht richtig.

    --> Stichwort Statemachines / Zustandsautomaten. Schau Dir das mal in der Anleitung an...

    MfG,
    SlyD

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2008
    Beiträge
    9
    Gibt es denn eine Möglichkeit zu sagen dass der Programmablauf erst weitergehen soll wenn task_ACS() fertig ist? Vielleicht indem man das ACS anders abfragt?

    Gruß Jan Lukas

    P.S. task_mtionControl hat kein Problem damit eine Zehntelsekunde lang nicht aufgerufen zu werden, der Roboter fährt trotz mSleep(100) flüssig.

  4. #4
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    Das funktioniert, da die Regelung nur alle 200ms aufgerufen wird. Die Überstromabschaltung und Fehlererkennung läuft jedoch nicht mehr unbedingt korrekt mit so langen Pausen.

    Mit dem ACS geht das aber definitiv nicht, das muss sehr oft aktualisiert werden sonst reagiert es entweder gar nicht mehr oder wird sehr träge.

    Du kannst warten indem Du eine Stopwatch verwendest und das alles in eine kleine lokale while(true) Schleife packst (mit break; verlassen sobald die Zeit verstrichen ist).

    Aber aufpassen - die Event Handler werden ggf. MEHRFACH hintereinander aufgerufen (Event Handler wird aus Event Handler aufgerufen der wiederum einen Event Handler aufruft usw. irgendwann kommt sich das dann ins Gehege.
    Daher ist das mit State Machines deutlich eleganter und zuverlässiger lösbar)


    MfG,
    SlyD

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2008
    Beiträge
    9
    Hi,
    ich habe jetzt jeden Aufruf von mSleep() durch einen Aufruf einer Stopwatch und einer while-Schleife erstzt, das Ergebniss war aber das gleiche.
    Deshalb habe ich geschaut ob die Funktion setACSPwr...() eventuell nicht schnell genug reagiert und siehe da, folgender Code brachte die Ausgabe GarnichGarnichtGarnicht........

    Code:
    #include "RP6RobotBaseLib.h"
    
    void warte()
    {
        setStopwatch1(0);
        startStopwatch1();
        while (getStopwatch1()<1000)
            task_ACS();
    }
    void STDStart()
    {
        initRobotBase();
        mSleep(1000);
        setLEDs(0b111111);
        mSleep(1000);
        setLEDs(0b000000);
        powerON();
        
    }
    
    int main()
    {
        STDStart();
        int ACSWeitR;
        int ACSMittelR;
        int ACSNaheR;
        int ACSWeitL;
        int ACSMittelL;
        int ACSNaheL;
        while (true)
        {
            setACSPwrHigh();
            task_ACS();
            ACSWeitR = obstacle_right;
            ACSWeitL = obstacle_left;
            
            setACSPwrMed();
            task_ACS();
            ACSMittelR = obstacle_right;
            ACSMittelL = obstacle_left;
            
            setACSPwrLow();
            task_ACS();
            ACSNaheR = obstacle_right;
            ACSNaheL = obstacle_left;
            
            if (ACSWeitR || ACSWeitL)
            {
                if (ACSMittelR || ACSMittelL)
                {
                    if (ACSNaheR || ACSNaheL)
                    {
                        writeString ("Nahe");
                    }
                    
                    else
                        writeString ("Mittel");
                }
                else writeString("Weit");
            }
            else writeString ("Garnicht");
            
            warte();
        }
        return (0);
    }
    Deshalb glaube ich dass man die Funktion setzACSPwr...() nicht zu oft aufrufen sollte, warum auch immer.

    Gruß Jan Lukas

  6. #6
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    Hallo,

    > ich habe jetzt jeden Aufruf von mSleep()
    > durch einen Aufruf einer Stopwatch und einer while-Schleife erstzt,


    Du musst dann aber in der while Schleife natürlich weiterhin alle benötigten task_IRGENDWAS funktionen aufrufen und ggf. darauf reagieren - sonst macht auch das keinen Unterschied.



    Zum Code:




    setACSPwrHigh();
    task_ACS();
    ACSWeitR = obstacle_right;
    ACSWeitL = obstacle_left;

    setACSPwrMed();
    task_ACS();
    ACSMittelR = obstacle_right;
    ACSMittelL = obstacle_left;

    setACSPwrLow();
    task_ACS();
    ACSNaheR = obstacle_right;
    ACSNaheL = obstacle_left;


    Das ist so leider quatsch

    task_ACS muss nicht nur häufig aufgerufen werden - die Funktion muss auch MEHRMALS für eine gewisse Zeit hintereinander aufgerufen werden.
    Schau Dir die Funktion doch einfach mal in der Lib an!
    Die hat mehrere Zustände die ZEITGESTEUERT nacheinander durchlaufen werden (links senden, links warten + empfangen, rechts senden, rechts warten + empfangen, ... warten ob RC5 Codes empfangen werden ... )

    Das da oben KANN also gar nicht so klappen wie gedacht, vermutlich modulierst Du da die IR LEDs nochmal weil dauernd die Sendestärke umgestellt wird


    Mein Rat:
    Schau Dir wirklich mal die Beispiele mit den Zustandsautomaten an.
    (hier im Forum gab es da auch ein oder zwei Threads zu)

    MfG,
    SlyD

Berechtigungen

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

Labornetzteil AliExpress