- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 7 von 7

Thema: waitms wird von einer Subroutine "eingefangen"

  1. #1
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652

    waitms wird von einer Subroutine "eingefangen"

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo Alle,

    sorry für den seltsamen Titel. Ich hänge seit Stunden an einem undurchsichtigen Problem und bitte um Hilfe. Irgendwo steckt in einer Subroutine ein Fehler - den ich leider nicht finden kann. Einzig allein der Verzicht auf die (nicht unbedingt nötige) Routine RUNslow1 beseitigt die beschriebene Fehlfunktion - ABER ich würde gerne sehen/wissen/lernen wo ich den Fehler habe.

    Stand: Eine waitms-Routine (aus dem C-Code für die RN-Control abgeschrieben und seit Jahren störungsfrei in Betrieb) wird derzeit nach Benutzung in einer bestimmten Subroutine von anderen Routinen nicht mehr benutzbar - zeigt aber in der "Kidnapping"routine weiter saubere Ergebnisse.

    Die waitms aus meiner AKTUELLEN Quelle kopiert:
    Code:
    //============================================================================== =
    //### Programm 1 ms pausieren lassen  !! Der Pausenwert ist nur experimentell !
      void waitms(uint16_t ms) 
      { 
        for(; ms>0; ms--) 
        { 
          uint16_t __c = 4000; 
          __asm__ volatile ( 
             "1: sbiw %0,1" "\n\t" 
             "brne 1b" 
             : "=w" (__c) 
             : "0" (__c) 
          ); 
        } 
      } 
    // ============================================================================== =
    Auszug aus der Schleife im main:
    Code:
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - -  Testversion = ...
    // - - - - - - - - - - - - - - -
      while ( 1 )           //
      {                     //
        TC1TMR_on ();       // Vor Servofahrt(en) Servotimer enablen             ~tmr~
    //  RUNi2c_02 ();       // Servotest02, Fahre alle Servos mit I2C-Befehlen   ~tst~
    //  RUN_tst2 ();        // Servotest, Fahre alle Servos                      ~tst~
         BULid   (1);        // Servos S2+3 auf mit "1"                           ~r2n~
        waitms ( 5000);
        BULid   (0);        // Servos S2+3 zu  mit "0"                           ~r2n~
        waitms ( 5000);
        RN2aua90G ();       // Servotest, Fahre (alle) Servos 2x auf-ab-90Grad   ~r2n~
        RUNslow1 () ;       // Fahre 10 Servo slow durch Micropositionierung     ~r2n~
        uart_puts("\r\n\tVor waitms 5000 in main/while(1) \r\n");    // 
        waitms ( 5000);
        uart_puts("\r\n\tEnde main/while(1) \r\n");    // 
      }                     //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      return 0;     // Ende int main(void)
    Die verdächtige Routine "RUNslow1". Wenn die Routine RUNslow1 im obigen Code im main nicht aufgerufen wird, läuft alles bestens. Es werden in der RUNslow1 keine anderen Interrupts initialisiert - es wird dort nur das benutzt, was in den anderen Routinen auch läuft.
    Code:
    //============================================================================== =
    //    ALLE Servoports werden aus unterschiedlichen Startpositionen heraus zwischen
    //        gleichen Betriebsgrenzen mit gleichen Incrementen gewobbelt
    //   ##>> Eine Anpassung an unterschiedliche Betriebsgrenzen und Änderungsicremente
    //        ist durch leichte Änderungen möglich
    //      KEINE I²C-Funktionalität
    // ============================================================================== =
      void RUNslow1 (void)          // Fahre 10 Servo durch Micropositionierung, damit
                                    //   geringe Drehgeschwindigkeit
     {                              //      und unabhängig voneinander
      uint8_t  nservo       =  10;  //
      uint8_t  lowbyte, hibyte;     //
      uint16_t iword        =   0;  // NUR zum Auslesen
                                    //   Word-Variable für Byte 2 (low) + 3 (high)
      int16_t  mdmmy;               // Dummy-Wert
      int16_t  maxsrv, minsrv;      // allgemeine Extrema der Servo
      maxsrv        = 600;          // 28.Nov.2012, 22:59
      minsrv        = 300;          //   dto
    // - - - - - - - - - - - - - - -
      int16_t s[12];        // Vorzeichenbehaftetes Increment für Rampenwert
      for (uint8_t i = 0; i <= 12; i++) { s[i] = 2; } // Startwerte
    // - - - - - - - - - - - - - - -
    //      Ausgabe über die serielle Schnittstelle
      uart_puts("\tAktiv ist RUNslow1\r\n");
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //      und noch quick´n dirty Servos ansteuern
    //      Startwerte für Servos ##>> IM TESTbetrieb
    //      ==========
      cli();
      Srv_tm [1]  = 350;
      Srv_tm [2]  = 400;
      Srv_tm [3]  = 450;
      Srv_tm [4]  = 500;
      Srv_tm [5]  = 550;
      Srv_tm [6]  = 600;
      Srv_tm [7]  = 400;
      Srv_tm [8]  = 500;
      Srv_tm [9]  = 600;
      Srv_tm [10] = 400;
      sei();
    // - - - - - - - - - - - - - - -
      while ( 1 )                   // Endlosschleife für Test
      {                             //
        for (uint8_t n = 1; n <= 10; n++)
        {                           // Servo-Sollwerte wobbeln
          cli();                    //
          mdmmy    = Srv_tm [n];
          sei();                    //
          if (mdmmy > maxsrv) s[n]  = -2;   //
          if (mdmmy < minsrv) s[n]  =  2;   //
          cli();                    //
          Srv_tm [n]  = Srv_tm [n] + s[n];  //
          sei();                    //
        }                   // Ende for (uint8_t n = 0; n =... = EINE 10er Periode !!
        waitms (   21);             // Wartezeit für Servozyklus
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //                                 Ist die "Abbruchtaste" gedrückt?
        if ( IsBitClr (PIND, 2 )) break;
      }                     // Ende while ( 1 )
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      uart_puts("\tEnde RUNslow1\r\n");
      return;                       //
     }              // Ende RUNslow1 (void)
    // ===  Ende RUNslow1 (void)
    // ============================================================================== =
    Die Routine void "BULid (uint8_t auf)" läuft bei den ersten beiden Malen einwandfrei - mit den Parametern 0 und 1, diese Parameter werden (nach der Benutzung der RUNslow1) beim zweiten Durchlauf der BULid gut übergeben, aber die BULid (1) zeigt keine Reaktion, weil die Pause - mit waitms - danach nicht gefahren wird, ebenso nicht die nach dem BULid (0). Dagegen laufen die waitms sowohl in der RUNslow1 als auch in der RN2aua90G.

    Sorry für diese Arbeit - aber ich weiß im Moment wirklich nicht weiter.

    Danke im Voraus für Hilfe.
    Ciao sagt der JoeamBerg

  2. #2
    Erfahrener Benutzer Roboter-Spezialist Avatar von robo_tom_24
    Registriert seit
    04.02.2012
    Ort
    Burgenland, Österreich
    Beiträge
    485
    Hallo
    Endet die Endlosschleife im RUNslow1 auch wirklich? Meiner Meinung nach wäre besser gewesen du unterbrichst das nicht mit einer if-Anweisung sondern mit der Schleifenbedinung selbst...
    Code:
    while(!IsBitClr (PIND, 2 ))
    {
    //Anweisungen
    }
    Semantisch macht es keinen Unterschied, aber vielleicht wird es vom µC irgendwie falsch interpretiert....

    Hast du globale Variablen deklariert? Also, welche die irgendwie im Zusammenhang mit den Warteschlangen stehen?
    Ich weiß auch nicht ob es das ist, ist aber das einzige was mir sonst noch einfällt.

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Hast du das ganze Mal simuliert? Solche hässlichen Seiteneffekte sind mit einer Simulation oft noch am einfachsten aufzudecken (oder mit HW-Debugging). Alternativ könntest du waitms (warum verwendest du eigentlich nicht die delay-Makros aus der avr-libc?) mit Debug-Ausgaben versehen um dir einen Zeitstempel + Parameter bei Eintritt und Verlassen der Funktion auszugeben.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    14.10.2012
    Beiträge
    14
    Hallo Oberallgeier

    Meiner Meinung nach, kann man einen Code nur in seiner ganzen Form, sprich das ganze C-File beurteilen, alles andere ist gebastelt.

    Vielleicht stellst du noch den ganzen Code hoch?

    Gruss

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Wenn es 10 Servos sind und Srv_tm auf ein Array von 10 dimensioniert ist, dann wird hier:
    Code:
        for (uint8_t n = 1; n <= 10; n++)
        {
          Srv_tm [n]  = Srv_tm [n] + s[n];
        }
    die Arraygrenze überschritten und eine andere Variable überschrieben.
    Gleiches gilt für s[i] in der entsprechenden Initialisierungsschleife.
    Das <= muss jeweils zu einem < werden.

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Hallo ihr Vier, danke für die schnelle Hilfe.

    Zitat Zitat von MagicWSmoke Beitrag anzeigen
    Wenn es 10 Servos sind und Srv_tm auf ein Array von 10 dimensioniert ist ...
    Ja, zehn Servos, aber das Array hat 12 Elemente, siehe weiter unten.

    @robot_tom_24: Die Endlosschleife endet wohl (siehe Heilungserfolg), aber Deine Semantik ist eben besser als meine, danke.

    @markusj: Simulation - bitte nicht weiterlesen - hatte ich noch nie gemacht. Kann ich nicht. Na ja, im Assembler, im AVRStudio - für tiny13 etc. - hatte ich das ganz gern getan und auch mit Erfolg, aber direkt in Hochsprache hatte ich mich da nie reingearbeitet. Vermutlich nicht zuletzt deswegen, weil ich fast immer Interrupts in meinen Programmen habe und mir die Simulation von Interrupts etwas undurchsichtig vorkommt.

    @markusj: das delay-Makro aus der avr-lib kenne ich seit einigen Monaten. Aber ich hatte eben schon viel früher dieses Modulchen bei meinem ersten Kontakt mit der RNControl gesehen und dann immer mitgeschleppt. Die Testausgaben mit Ein- und Austrittsparameter, aber ohne Zeitstempel, hatte ich schon getestet gehabt vor meinem Posting. Leider ohne Erfolg.

    @ahabakukuk: Danke, Du hast sicher recht mit dem ganzen Code, der ist schon deutlich umfangreicher. Ich habe an sich keine Bange so etwas online zu stellen - ausser, dass es für die freundlichen Helfer dann abstossend viel Lesezeug sein kann. Es ist eben eine etwas zwiespältige Sache mit etlichen hundert Codezeilen (auch wenn ihr Erfahrenen da sicher ziemlich schnell den richtigen und kurzen Faden durchfindet).

    @MagicWSmoke: Huiiii! Also erstmal hatte ich so von oben herab sagen wollen (habs eigentlich deutlich gedacht): kenn ich, da schütze ich mich davor : ich habe ein Feld Srv_tm [12] - weil ich ein fauler Hund bin, nicht den ersten Servo mit Servo 0 sondern lieber mit Servo 1 bezeichne - und hintenraus kostet mich ein unbenutztes Byte nicht die Welt und bringt genau diese benötigte Sicherheit. Konntest Du natürlich leider nicht prüfen, weil ich da sicher war, dass kein Fehler vorliegt und meine Definitionen und Deklarationen weggelassen hatte. ABER - Du hast natürlich so was von Recht - im vorgelegten Code ist das Feld int16_t s[12]; eingetragen und das ist genau um ein Word zu knapp ausgelegt. >> Und das wars dann.

    Fazit: es läuft wie geschmiert. Gibt richtig Wochenendlaune ! ! Danke!

    Danke Euch für die freundliche Mithilfe. Wieder einen Klacks Semantik dazugelernt und wieder einen Fehler entfernt. Klasse von Euch und schönen Sonntag,
    Geändert von oberallgeier (01.12.2012 um 23:40 Uhr)
    Ciao sagt der JoeamBerg

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von oberallgeier Beitrag anzeigen
    ... und das ist genau um ein Word zu knapp ausgelegt. >> Und das wars dann.
    Es sind zwei Words, denn wenn Du in der For-Schleife auf <= 10 testest, dann zählst Du genau bis 11. Es wird zuerst die Bedingung geprüft und da sie auch bei 10 noch wahr ist, wird i ein weiteres Mal erhöht und der Schleifenblock ausgeführt. Wenn Du nicht auf auf 12 Elemente erhöhen willst, dann nimm das "=" raus.

Ähnliche Themen

  1. Basic: Bedeutung von "And" bei Wertzuweisung einer
    Von NeroII im Forum Software, Algorithmen und KI
    Antworten: 1
    Letzter Beitrag: 10.01.2010, 12:13
  2. Programmieren ohne "Waitms"
    Von Brantiko im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 18
    Letzter Beitrag: 12.02.2007, 16:40
  3. Alternativen zur Funktion "Wait" bzw. "Waitms
    Von pinoccio im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 30.04.2006, 14:51
  4. Bascom's "waitms" in C?
    Von TheOneBeyond im Forum C - Programmierung (GCC u.a.)
    Antworten: 13
    Letzter Beitrag: 25.10.2004, 16:04
  5. Wie wird das "Conrad Led Panel" angeschlossen???
    Von RCO im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 3
    Letzter Beitrag: 09.06.2004, 19:24

Berechtigungen

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

12V Akku bauen