- SF800 Solar Speicher Tutorial         
Ergebnis 1 bis 10 von 246

Thema: Autonom in kleinen Dosen: R2_D03 + Nachfolger R3D01

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #11
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.694
    Hallo ?ternthaler¿

    Zitat Zitat von Sternthaler
    ... Der mit Fragezeichen versehene ... Sternthaler
    Tut mir leid, dass ich Dich mitternächtlicher Weise ins Grübeln und zum Durcheinanderrechnen bringe. Die 1220 Hz stammen primär von der PwM für die Motoren. Die anderen Timer sind/werden genutzt, wie es die untenstehenden Übersicht zeigt. Ich nehme die gleiche Aufteilung beim MiniD0 wie beim R2D03.

    ............Bild hier  

    Die ursprünglich höhere Frequenz für die Motor-PwM, 4,88 kHz, musste ich nach unten korrigieren, damit mir die davon abgeleiteten ISR für die irDME´s - Deine CIRperei - nicht zu viel CPU-Auslastung in den Interrupts bringt. Außerdem passte die niedrigere Frequenz dann auch noch fürs Auslesen des ADC-Sharp (alle 10 ms ist etwas schnell, aber dadurch bekomme ich die neuesten Ergebnisse des Sharp eben recht flott) und für die Regelung. Der Ablauf sieht in einem simplen Diagramm damit so aus:

    Code:
    ---C---1---2---3---4---5---6---7---8---9---A---B---C---1---2---3---4--> >
       |               |               v               |               |
       |               v               AR *) Mot34     |               v
       v               AR Mot 12                       v               AR Mot 12
       Auslesen des ADC/Sharp                          Auslesen des ADC/Sharp
       
     *) AR: Aufruf der Regelungsroutine
    Die externen Interrupts der Encoder/Gabellichtschranken werden so initialisiert und ausgelesen (Ausleseroutine sinngemäß für beide) :

    Code:
    /* ============================================================================== */
    /* ===  Initialisierung fuer EXT_INT0/1 auf Pin 4+5/PD2,3 bei m168  ================
    $002 jmp SIG_INTERRUPT0 ; IRQ0 Handler   _VECTOR(1)
    $004 jmp SIG_INTERRUPT1 ; IRQ1 Handler   _VECTOR(2)              ================ */
    void XTI_0_1_init( void )    
    {                //Initialisiere beide Interrupts auf rising edge
                    //  d.h. EICRA ISC00,01,10+11 auf 1 (doc,S68)
        EICRA |= (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);
        EIMSK  |= (1<<INT1)|(1<<INT0);    //  und erlaube diese I´s in EIMSK
    // Initialisierung der Zeiten:
      Iencdr0      = 0;
      Iz_diff0     = 0;
      Iz_yseci0    = 0;
      Iz_ysecv0    = 0;
    }
    /* ============================================================================== */
    
    
    // =================================================================================
    // ===  Nicht unterbrechbare ISR für EXT_INT0 auf Pin 4/PD2/mega168  ===============
    /* Routine setzt einen Zähler hoch. Der Zähler wird im main ausgelesen
         ##>> cli/sei setzen ?? <<## und nach 2 (od. 5) hunderstel Sekunden
         auf den Speicher WEG_L/_R vorzeichenrichtig aufaddiert und dann zurückgesetzt.
         ##>> Beim Richtungswechsel (cli/sei) wird der Zähler ausgelesen und genullt,
         damit ist eine saubere Wegmessung möglich.
         Der zugehörige Motor auf PD7/PB0 = re,li und PB1 Geschwind./PWM           */
      ISR(INT0_vect)                        // hiess mal: ISR(SIG_INTERRUPT0)
      {                                     //
        if (nenc0     <  4)                      
          nenc0       =  nenc0 + 1;             
        else                                    
        {                                   // Zähle NUR jeden vierten Interrupt
          nenc0       =  1;                     
          Iencdr0 ++;                       //zähle Counter/encoder0 hoch
          Ienc0alt  = Iencdr0;                   
          Iz_yseci0 = Izeit_1;              //Weise Iz_ysec-ist-0 dem akt. Timerwert zu
          Iz_diff0 = Iz_yseci0-Iz_ysecv0;    //Neue Zeit-Differenz1 ausrechnen
          Iz_ysecv0 = Iz_yseci0;            //der aktuelle Zeitwert wird "Alter"
        }                                     
      }                                       
    /* ============================================================================== */
    Die Größe Iencdr0 dient für allfällige Odometrieaufgaben, also z.B. um eine Drehung um genau 60° oder so zu erzeugen. Sie wird entweder sinnlos rundum gezählt, oder bei Bedarf auf Null gesetzt und in der entsprechenden Routine abgefragt.

    Damit sollte Deine Frage nach dem Gewinnen der Encoderdaten doch beantwortet sein!? Also für mich sieht das nicht aus wie Pollen. Sowas brächte ja blos Heuschnupfen! Jede extINT-ISR holt sich (ja ja, das wär aber doch pollen) den aktuellen Zeitwert Izeit_1 aus dem 50µs-Timer und weist ihm dem Wert Iz_yseci0 --- i wie "ISTzeit" --- zu, errechnet daraus die Zeitdifferenz zum vorherigen Interrupt und merkt sich die aktuelle ISTzeit als Iz_ysecv0=VORheriger Wert. Ok?

    Die Initialisierung der PWMs etc hatte ich in diesem Thread bereits vorgestellt und die Regelung zum Dottie hatten wir bereits diskutiert (da gings um die Asymmetrie von iesum12 - ich kann den Link gerade nicht finden). Den Code für MiniDO stelle ich vor (wenns Dir recht ist), sobald die aktuelle Version auch weitgehend stimmt - derzeit sind die Parameter keinesfalls optimal.

    Code:
    /* ============================================================================== */
    /* ===  Regelungsroutine für Motor 12  ========================================== */
    /* Die gemessene Zeitdifferenz Iz_diff0 wird zur Regelung verwendet   
                                                                                      */
      void rgl_mo_12(void)          // (Wird) Regelung für Motor 12
    {                                 
      if (stupsi12 <= 5)            // Soll überhaupt gefahren werden?
      {                              
        OCR0A = 0;
        return;
      }                            
      tupsi12      = Iz_diff0;                      // Übernahme Iz-Wert in Regelung
      ndrz12       = stupsi12;
      if ( tupsi12 > 100 )  { tupsi12  = 100; }     // Eingrenzen
      idrz12      = 1000 / tupsi12;
      ie_mot12     = ndrz12 - idrz12;               // Vergleich => Regelabweichung
      iesum12      = iesum12 + ie_mot12;
      if  (iesum12 < -10) { iesum12  = -10;}
      if  (iesum12 >  500) { iesum12  =  500;}
      iy12         = iesum12/2;
      iy12         = iy12 + ie_mot12 + ie_mot12 + ie_mot12 + ie_mot12 + ie_mot12;
                    // Diese Rechenoperation benötigt in float 0,20 bis 0,25 ms!
                            
      if ( iy12    <   0 )   { iy12   =    0;}
      if ( iy12    > 255 )   { iy12   =  255;}
                    
      OCR0A = iy12;                 // Ansteuerung der PWM direkt statt "setPWMlinks"
                                        
      return;                          
    }               
    /* ============================================================================== */
    So, damit habe ich hoffentlich für Deine Feiertagsruhe gesorgt - wenigstens soweit, dass Du nicht nach meinem Cäh-Code grübeln musst. Wenn Du mehr Softfutter möchstest - kein Problem.

    Übrigens hatte ich die Sprungantwort fürs MiniD0 etwas oberflächlich gemessen (auch nur ein Mal *brrrr*) und eine entdeckte Macke im Kurvenverlauf lasch als Aussreisser interpretiert und unbeachtet gelassen. Tatsächlich war die Messung für die Tonne, an neueren Messungen habe ich schon gearbeitet, aber heute standen auch (wieder) ein paar geradelte Straßenkilometer, gepaart mit Höhenmetern, auf dem Plan.
    Geändert von oberallgeier (17.10.2016 um 17:13 Uhr) Grund: neuer Bildserver
    Ciao sagt der JoeamBerg

Berechtigungen

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

Solar Speicher und Akkus Tests