-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Kollisionsprogramm über interrupt

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    29.10.2008
    Beiträge
    6

    Kollisionsprogramm über interrupt

    Anzeige

    Hi leute.

    ich habe ein kleines projekt vor mit meinem asuro - und zwar für die
    schule... habe noch 2 wochen zeit und nach viielen stunden vergebener arbeit
    wende ich mich jetz hier an euch.

    ziel: asuro soll einen beliebigen parcour mit wänden welche immer im rechten
    winkel zueinander stehen durchfahren können.

    lösungsansatz:

    grundprogramm: asuro fährt geradeaus, registriert ein taster etwas springt er
    in ein interruptprogramm

    interruptprogramm: asuro macht standardmässig nach der kollision eine 90° drehung nach rechts und fährt weiter gerade aus, trifft er unmittelbar danach
    wieder auf eine wand stellt er fest dass dies der falsche weg ist und dreht
    sofort 180° (nicht 90°, weil er dann ja dahin zurückfahren würde woher
    er zuerst kam). trifft er nach der ersten kollision nicht unmittelbar auf
    etwas fährt er geradeaus weiter. die nächste kollision zählt wieder als 1.


    frage: wie kann ich sowas in ein programm fassen? ich habe mit dem C+
    inzwischen ein riesigen gedankenknäul und hab keine ahnung wie ich das
    programm lösen soll...

    wie bindet man ein interruptprogramm in ein hauptprogramm ein? und
    wie löst man das problem dass er erkennt ob es das zweite mal hintereinander
    ist dass er kollidiert oder ob es das erste mal ist?

    hoffe auf antworten.
    lg sebastian

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    01.03.2008
    Ort
    Niederlanden
    Beiträge
    1.167
    Die lib erweiterung (sicher 2.71 und 2.8rc1,aber vielleicht auch orginal lib) hier im forum hat schön ein "interrupt service routine" fur die kollisiontaster eingestelt. Du kannst dah reinschauwen (switches.c un asuro.c) wie das gemacht ist. Die ISR setzt ein globale variable wenn er kontakt macht (und ISR wird 'abgeschaltet' fur neuere kollisionen ). Du kannst das in deiner main() program pollen und controlieren/testen mit 2xPollswitch (dannach ISR wieder reinstellen). Dan folgt deiner entscheidung links oder rechts zu drehen. Und dann wieder noch ein mall im endlos schleife reingehen.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    29.10.2008
    Beiträge
    6
    hi danke für die hilfe.
    könntest du das evt kurz skizzieren?

    mit welchem befehl könnte ich das abfragen? und vor allem mit welchem befehl erkennt er das es das zweite mal in folge ist?

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    01.03.2008
    Ort
    Niederlanden
    Beiträge
    1.167
    Im asuro.h (lib 2.8rc1) steht:
    Code:
    /*
     * Tastsensor Wert bei Interrupt Betrieb. 0=keine Taste, 1= Taste gedrueckt
     */
    /*!
     * \~english
     * \brief any switch pressed?
     *
     * is being set to TRUE by interrupt if a switch is pressed\n
     * remember to set it to false again, since it is not reset automatically
     * \see StartSwitch
     */
    extern volatile int switched;
    Also, etwas wie:

    Code:
    while (1) {
    if (switched=True) CheckCollision();  
    switched=False;
    StartSwitch();
    if (collision)
      {
      ...
      do_something();
      ...
      }
    }
    ...
    
    NOTE: CheckCollision(), do_something() und collision ist nur pseudo-code von mir... nicht im Lib zu finden.

    Und fur 2 mal taster abfragen wie im KollisionTest example program:

    ...
    while (1)
    {
    t1 = PollSwitch();
    t2 = PollSwitch();
    if (t1 == 0 && t2 == 0) /* keine Taste */
    {

    MotorFwd(); /* vorwärts fahren */
    FrontLED(ON);
    BackLED(OFF,OFF);
    }
    else if (t1 && t2 && t1 == t2)
    {

    MotorStop();
    if (t1 & 0x07) /* Tasten links gedrückt? */
    {
    MotorRwdL(); /* Rückwärtskurve links fahren */
    FrontLED(OFF);
    BackLED(ON,OFF);
    }
    if (t1 & 0x3 /* Tasten rechts gedrückt? */
    {
    MotorRwdR(); /* Rückwärtskurve rechts fahren */
    FrontLED(OFF);
    BackLED(OFF,ON);
    }
    Msleep(1000); /* 1 Sekunde fahren */

    }
    ...
    Schau mal die Quell code an. Du muss nur selbst raus finden wie du die drehungen organisiert wenn ein kollision sicher erkannt ist.

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    26.09.2008
    Ort
    Wien
    Alter
    31
    Beiträge
    94
    Sorry für die Frage, aber warum muss es eine Interruptroutine sein?
    Ich würde es so machen:
    while(true)
    Asuro fährt
    wenn Kollision
    -> Stop und Drehen + Kontrollvariable setzen, eventuell kurz warten.
    Danach wieder von vorne, das heisst Asuro fährt wieder los.
    Falls es jetzt wieder zu einer Kollision kommt muss Asuro schaun ob die Kontrollvariable noch gesetzt ist. Wenn ja, 180° Drehung.
    Wenn nein, 90° Drehung.
    Die Kontrollvariable müsstest du nach einem gewissen Durchlauf wieder zurücksetzen. Mit sleeps würde ich nicht arbeiten, da für die "sleep-Zeit" der Programmablauf blockiert ist und somit auf eine eventuelle Kollision nicht reagiert werden kann.
    while (!asleep()) sheep++;
    RP6 und Asuro Befehlsübersicht

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hi sebär,

    für M1.R hatte ich mal im Thread "Der ASURO als Wecker" eine 'kleine' Erklärung zusammengestellt wie man mit Interrupts umgeht.
    Eventuell hilft dir die Beschreibung unter: http://www.roboternetz.de/phpBB2/zei...=336794#336794
    Es ist keine Lösung für ein bestimmtes Problem, sondern beschreibt allgemein, wie man vorgehen muss/sollte wenn man Interrupts nutzen will.

    Viel Erfolg, und herzlich willkommen im Forum.
    Gruß Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    29.10.2008
    Beiträge
    6
    so hab mich jetz endlich mal am sonntag morgen in ner freien stunde hingesetzt und das interruptzeugs mal durchgeackert. so sieht der quellcode jetz aus.

    aktuelle funktion: fährt wo rein und dreit dann rechts zurück.

    #include "asuro.h"

    #define FULL_L 240
    #define FULL_R 220



    void Fahren(void) /* Vorwärts fahren */
    {
    StatusLED(GREEN);
    BackLED(OFF,OFF);
    MotorDir(FWD,FWD);
    MotorSpeed(FULL_L,FULL_R);

    }


    void Zurueck(void) /* Zurück fahren */
    {
    StatusLED(YELLOW);
    BackLED(ON,ON);
    MotorDir(RWD,RWD);
    MotorSpeed(FULL_L,FULL_R);
    }


    void KurveLR(void) /* Kurve rückwärts Links */
    {
    StatusLED(YELLOW);
    BackLED(ON,OFF);
    MotorDir(RWD,RWD);
    MotorSpeed(FULL_L,0);
    }


    void KurveRR(void) /* Kurve rückwärts Rechts */
    {
    StatusLED(YELLOW);
    BackLED(OFF,ON);
    MotorDir(RWD,RWD);
    MotorSpeed(0, FULL_R);
    }


    void Anhalten(void) /* Anhalten */
    {
    StatusLED(RED);
    BackLED(OFF,OFF);
    MotorSpeed(0,0);
    }



    int main (void)
    {
    Init ();
    switched = 0;
    StartSwitch ();
    while (1)
    {
    if (switched == 1)
    {
    Anhalten();
    Msleep(250);

    Zurueck();
    Msleep(250);

    Anhalten();
    Msleep(250);

    KurveRR();
    Msleep(1000);

    Anhalten();
    Msleep(250);

    switched = 0;
    StartSwitch ();
    }

    else

    Fahren();
    }

    return 0;

    }

    sodele. soweit so gut - habs noch nicht testen können - asuro is in der schule und ned bei mir zuhause, aber weiter im text!

    folgendes problem: wie kann asuro entscheiden ob er zum ersten mal wo reingefahren ist oder ob er unmittelbar zuvor schon eine kollision hatte?

    das ziel ist, dass falls es das erste mal war, dass er die 90° zurück macht standardmässig. falls es das zweite mal ist soll er eine 180° drehung machen.

    ich bitte um ziemlich ausführliche erklärungen :S bin noch absoluter noob was C angeht.

    danke schon im voraus

    lg sebastian

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    26.09.2008
    Ort
    Wien
    Alter
    31
    Beiträge
    94
    Also in normalen C würdest du das am Besten mit nem Thread lösen. Sowas gibts bei µC aber nicht, also kannst du nur "hintereinander" statt "gleichzeitig" Kollisionen abfragen. Allgemeine Lösung wäre eine Kontrollvariable, siehe dazu meinen Lösungsansatz weiter oben.
    Problem bei der Abfragung "hintereinander": Der weitere Programmablauf wird blockiert. Bei Threads könnte das normale Programm weiterlaufen während die Abfrage durchgeführt wird.
    Bitte um Entschuldigung falls die Beschreibung etwas umständlich war, bin hunde müde.
    Also im Prinzip nochmal kurz gefasst, einfach ne Variable nach dem zusammenstoss setzen, den Ausweichvorgang durchführen, dann wieder losfahren und nen "time" abwärtszählen lassen. Wenn er auf 0 ist, die Kontrollvariable rücksetzen, was einen zusammenstoss nach längerer Zeit bedeuten würde. Falls der Zusammenstoss erfolgt während die Variable noch gesetzt ist, war es ein direkt nach dem ersten Kontakt folgender Zusammenstoss. Und das angesprochene Problem dabei: Wenn der Zusammenstoss genau dann erfolgt, während die Routine wartet (um die Variable runterzuzählen) kann nicht darauf reagiert werden, weil das Programm blockiert.
    So, ab ins Bett
    while (!asleep()) sheep++;
    RP6 und Asuro Befehlsübersicht

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hi sebär,

    wenn du immer abwechseln mal 90° und 180° drehen möchtest, benötigst du eine Variable, die einfach nur hochzählt, wenn du ein Hindernis findest und drehen willst/musst.
    Ist der Wert gerade, dann 180°, sonst 90°.

    Such mal im angepassten Code nach 'zaehler'.
    Code:
    #include "asuro.h"
    
    #define FULL_L 240
    #define FULL_R 220
    
    
    
    void Fahren (void) /* Vorwärts fahren */
    {
       StatusLED (GREEN);
       BackLED (OFF, OFF);
       MotorDir (FWD, FWD);
       MotorSpeed (FULL_L, FULL_R);
    }
    
    
    void Zurueck (void) /* Zurück fahren */
    {
       StatusLED (YELLOW);
       BackLED (ON, ON);
       MotorDir (RWD, RWD);
       MotorSpeed (FULL_L, FULL_R);
    }
    
    
    void KurveLR (void) /* Kurve rückwärts Links */
    {
       StatusLED (YELLOW);
       BackLED (ON, OFF);
       MotorDir (RWD, RWD);
       MotorSpeed (FULL_L, 0);
    }
    
    
    void KurveRR (void) /* Kurve rückwärts Rechts */
    {
       StatusLED (YELLOW);
       BackLED (OFF, ON);
       MotorDir (RWD, RWD);
       MotorSpeed (0, FULL_R);
    }
    
    
    void Anhalten (void) /* Anhalten */
    {
       StatusLED (RED);
       BackLED (OFF, OFF);
       MotorSpeed (0 ,0);
    }
    
    
    
    int main (void)
    {
       unsigned char zaehler = 0;
    
       Init ();
       switched = 0;
    
       StartSwitch ();
    
       while (1)
       {
          if (switched == 1)
          {
             zaehler++;
    
             Anhalten ();
             Msleep (250);
    
             Zurueck ();
             Msleep (250);
    
             Anhalten ();
             Msleep (250);
    
             KurveRR ();
             if (zaehler & 0b00000001)
                Msleep (1000);
             else
                Msleep (2000);
    
             Anhalten ();
             Msleep (250);
    
             switched = 0;
             StartSwitch ();
          }
          else
             Fahren ();
       }
    
       return 0;
    }
    Das "if (zaehler & 0b00000001)" prüft nur, ob das letzte Bit in der Variablen gesetzt ist. Das reicht aus um entscheiden zu können ob die Zahl gerade oder ungerade ist.
    Du brauchst auch keine Angst vor dem "zaehler++" zu haben. Damit wird nur folgendes gemacht "zaehler = zaehler + 1;"
    Und wenn der Wert in zaehler von 255 nochmal um eins erhoeht wird, dann passiert in C kein Fehler, obwohl der Wert ja eigentlich auf 256 gehen will, die Variable aber nur von 0 bis 255 geht.
    Der Wert wird einfach wieder auf 0 gesetzt und schon geht es weiter.

    Viel Erfolg und
    Gruß Sternthaler

    P.S.: Wenn du demnächst selber wieder Programmcode posten möchtest, schreib bitte ein [ code ] vorher und hinterher ein [ /code ]
    ABER OHNE die Leerzeichen in den Klammern.
    Dann bekommst du auch so ein schönes Kästchen wie hier gerade, und die Formatierung bleibt erhalten.
    Lieber Asuro programieren als arbeiten gehen.

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    02.01.2008
    Alter
    26
    Beiträge
    239
    hallo zusammen

    @sternthaler:
    also wenn ich das richtig verstanden habe muss sebär nicht einmal 90°, 180°, 90°... sondern nur dann 180° wenn innerhalb einer best. zeit ein taster gedrückt wird.
    daher glaube ich, dass dein version nicht wirklich passt (sry)

    sondern man müsste irgend wie eine zeit abfage einbauen. ich weiß nur nicht, ob es solch eine möglichkeit gibt, wie ich sie mir grade vorstelle.
    da müsste ich nämlich nach einer kollision und erfolgter 90°-kurve die aktuelle zeit abrufen (hoffe es gibt eine funktion die die zeit zurückliefern kann, welche seit dem letzten einschalten vergangen ist), diese in eine variable speichern und bei der nächsten kollision wieder die aktuelle zeit abrufen und schauen ob es noch in einer vorgegebenen zeit ist ( dh. 2. kollison mit wand, daher 180°dreheung), oder ob schon zu viel zeit vergangen ist und er wieder mit einer 90°drehung "anfangen" soll.

    ich hoffe das war verständlich
    mfg hai1991

    P.S.: wer großbuchstaben oder rechtschreibfehler findet darf sie behalten

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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