- 3D-Druck Einstieg und Tipps         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Verschiedene Taktraten im Atmega?

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    24.06.2018
    Ort
    Bayern
    Beiträge
    8

    Frage Verschiedene Taktraten im Atmega?

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo miteinander,

    ich werke am "Robot Arm RA1-PRO V3" von Arexx mit eingebautem Atmega64 und externem 16 MHz Quarz, programmiere mit Bascom/Ponyprog/ISP.

    Das Problem ist, dass das Programm mit 7,7 MHz läuft (über LED-Geblinke und "Wait" ermittelt),
    die UART-Schnittstelle (Baud 9600 im Programm und im Bascom-Terminal) jedoch mit 16 MHz.
    Im Programm kann ich nur eine Frequenz angeben, daher funktioniert das so nicht.

    Wie kann das sein? Fuses sind auf externen Quarz gestellt.
    Im Datenblatt hab ich gelesen, dass es eine "AVR Clock Control Unit" gibt, die wohl unterschiedliche (?) Taktraten weiterleiten kann.
    In den Fusebits finde ich keine Einstellung für ein solches Register.
    Wie komme ich auf den vollen Quarz-Takt innerhalb des Programms?

    Danke und viele Grüße
    Simon

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    Eins vorweg, ich kenne mich mit Bascom nicht aus

    aber was du beschreibst klingt extrem unwahrscheinlich, mir ist nicht bekannt dass man im atmega interne und externe clock gleichzeitig einsetzen könnte

    wie genau hast du denn mit "geblinke und wait" die Geschwindigkeit gemessen?

    Zumindest vom avr-gcc weis ich, dass wenn man die "F_CPU" definition nicht richtig setzt der wait nur mist macht.

    Hier ein Artikel über F_CPU

    https://rn-wissen.de/wiki/index.php?..._(LED_blinken)

    Das Programm ist ausgelegt für eine Taktrate von 1 MHz. Wenn dein Controller mit einem anderen Takt läuft, dann hast du zwei Möglichkeiten:

    • Du lässt das Programm so, wie es ist. Dann blinkt die LED entsprechend schneller bzw. langsamer. Hast du deinen AVR zB mit 16 MHz getaktet, dann blinkt die LED mit 8 Hz.
    • Du passt die Taktfrequenz in der Quelle oder per Kommandozeile an. Für 8 MHz:
    Das erklärt glaube ich ganz gut dein beschriebenes Erlebnis in dem Zusammenhang
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    Zitat Zitat von Don Simon Beitrag anzeigen
    .. ich werke am "Robot Arm RA1-PRO V3" von Arexx mit eingebautem Atmega64 und externem 16 MHz Quarz, programmiere mit Bascom/Ponyprog/ISP .. Das Problem ist, dass das Programm mit 7,7 MHz läuft (über LED-Geblinke und "Wait" ermittelt) .. die UART-Schnittstelle (Baud 9600 im Programm und im Bascom-Terminal) jedoch mit 16 MHz. .. Im Programm kann ich nur eine Frequenz angeben, daher funktioniert das so nicht ..
    Dein ".. daher funktioniert das so nicht .." ist ja ne stolze aussage, leider völlig nichtssagend und daher unverständlich. WAS GENAU funktioniert nun nicht? Dazu kann ich mit der simplen Aussagen kein Urteil abgeben. WAS ist "das Programm" und welche Frequenz gibst Du (wo???) ein? Aber, eben ganz wichtig, WAS GENAU funktioniert nicht ?

    Wie Ceos schon schrieb, kann man mit einer "wait"-Routine prächtig daneben liegen mit der Aussage zum Prozessortakt. Wenn da parallel noch ISRn laufen gibt das keine vernünftige Aussage über den tatsächlichen CPU-Takt. Nach der Anleitung V3-1113 zu Deinem Roboter sehe ich, dass der Controllertakt mit CPU=16000000UL angegeben ist. Der sollte also wirklich mit dem Quarztakt 16 MHz tickern.

    Anmerkung, ohne Garantie, kein Regress möglich:
    Bei den Fuses würde ich (ohne Garantie, kein Regress möglich) SUT-CKSEL (Start Up Table, ClocK SELect) setzen/controllieren auf
    Ext. Crystal/Resonator High Freq.; Start-up time: 1K CK + 4 ms
    Damit dürfte ein sauberes Arbeiten möglich sein.

    .. Im Datenblatt hab ich gelesen, dass es eine "AVR Clock Control Unit" gibt, die wohl unterschiedliche (?) Taktraten weiterleiten kann ..
    Stimmt. Man kann für verschiedene, controllerinterne Baugruppen verschiedene Taktraten einstellen, für ADC, UART, etc, meinst Du das ?

    .. In den Fusebits finde ich keine Einstellung für ein solches Register. ..
    Vielleicht musst Du dazu nochn bisschen AVR-Programmierung lernen? Für ADC, für UART etc zB, auch für Timer-Interrupts und so stellt man unterschiedliche Taktraten ein - aber dazu lies Dich mal in den entsprechenen Tutorials selber ein.

    .. Wie komme ich auf den vollen Quarz-Takt innerhalb des Programms? ..
    DU ! nicht! (Na ja, Frequenz mit Messgerät direkt am Resonator abgreifen *gg*). Aber wenn Du die obige Einstellung für SUT-CKSEL benutzt dann können die verschiedenen Sektionen mit dieser Grundfrequenz arbeiten.

    .. Das Problem ist, dass das Programm mit 7,7 MHz läuft (über LED-Geblinke und "Wait" ermittelt) ..
    Das scheint mir Dein wahrer Fehlschluss zu sein. Abgesehen davon - was meinst Du mit "..das Programm .. läuft mit 7,7 MHz.."? Nur mal Beispiele:
    - Der direkte Call einer Subroutine, ein Maschinenbefehl, braucht auf Maschinenebene 1 Cyklus, bei Deinem mega64 also 1/16tel Millionstel Sekunde.
    - Der relative Jump braucht schon 2 Cyklen.
    - Der Return einer Subroutine oder einer Interruptsubroutine braucht vier Maschinenzyklen.
    Will sagen: je nach der zum Ablauf benötigten oder gewünschten Operation werden die Befehle unterschiedlich schnell abgearbeitet, nicht jeder Maschinenbefehl ist in nur einem einzigen Maschinenzyklus erledigt. Trotzdem: das ist dann die maximal mögliche Geschwindigkeit.

    Fazit: Lern mal gründlich die Programmierung des Controllers. Datenblatt, Tutorials und so. Und Zeit.
    Ciao sagt der JoeamBerg

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    24.06.2018
    Ort
    Bayern
    Beiträge
    8
    Erstmal vielen Dank für eure Hilfe!

    Zitat Zitat von Ceos Beitrag anzeigen
    .. wie genau hast du denn mit "geblinke und wait" die Geschwindigkeit gemessen? ..
    In etwa so: "LED an, warte 10 Sekunden, LED aus". Dann messe ich die Zeit, während die LED leuchtet und rechne die ungefähre "wirkliche" Taktrate aus. Diese Frequenz gebe ich dann im Programm an.
    Bei Bedarf wiederhole ich dasselbe noch mit 60 Sekunden. Die Prozedur mache ich oft bei Verwendung des internen Taktes, weil dieser sehr ungenau ist.

    Danke für den Link. Bei mir ist es genau so. Ich setze vorher eine "F_CPU" Definition, damit das Programm "weiß", mit welcher Frequenz es später arbeitet. Allerdings macht bei mir die Wait-Funktion keinen Mist, sondern nur vorhersehbar andere Zeiten entsprechend der selbst vorgegebenen Quarz-Definition.



    Zitat Zitat von oberallgeier Beitrag anzeigen
    Dein ".. daher funktioniert das so nicht .." ist ja ne stolze aussage, leider völlig nichtssagend und daher unverständlich. WAS GENAU funktioniert nun nicht? Dazu kann ich mit der simplen Aussagen kein Urteil abgeben. WAS ist "das Programm" und welche Frequenz gibst Du (wo???) ein? Aber, eben ganz wichtig, WAS GENAU funktioniert nicht ? ..
    Wie beschrieben habe ich festgestellt, dass der Takt des Programms ein anderer ist als der Takt der UART. Natürlich kann ich im Programm nur EINE Frequenz angeben, mit der das Programm arbeiten soll. Gebe ich 16 MHz an, bekomme ich von der seriellen Schnittstelle korrekte Zeichen am Terminal, gebe ich 7,7 MHz an, stimmen die "Wait"-Zeiten im Programm.
    Mit "Programm" meine ich meistens den auszuführenden Code.

    .. Wie Ceos schon schrieb, kann man mit einer "wait"-Routine prächtig daneben liegen mit der Aussage zum Prozessortakt. Wenn da parallel noch ISRn laufen gibt das keine vernünftige Aussage über den tatsächlichen CPU-Takt. ..
    Dann muss das mein Fehler sein.

    .. Bei den Fuses würde ich (ohne Garantie, kein Regress möglich) SUT-CKSEL (Start Up Table, ClocK SELect) setzen/controllieren auf
    Ext. Crystal/Resonator High Freq.; Start-up time: 1K CK + 4 ms ..
    Alle sechs Bits sind "nicht programmiert" (1en) und CKOPT ist programmiert (0), was laut Datenblatt dem externen Quarz mit hoher Frequenz und 1K CK + 4,1 ms Startzeit entspricht.

    .. Man kann für verschiedene, controllerinterne Baugruppen verschiedene Taktraten einstellen, für ADC, UART, etc, meinst Du das ? ..
    Ok, alles klar. Hab das nur vom Blockschaltbild her falsch interpretiert.

    .. was meinst Du mit "..das Programm .. läuft mit 7,7 MHz.."? ..
    Ich meine, dass der Programmcode mit der Taktrate 7,7 MHz abgearbeitet wird. Mir ist klar, dass einzelne Sprünge mehr Zyklen brauchen als andere.


    Gedankenexperiment:
    Nehmen wir an, ich definiere im Programmcode die 16 MHz als Taktfrequenz. Dann lasse ich alle Subs und Interrupts weg. Dann sollte ich doch korrekte Zeiten für eine allein stehende Wait-Routine bekommen?!

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    LED an, warte 10 Sekunden, LED aus
    Hört sich zumindest gut an, so sollten Fehler durch die Ausführungsgeschwindigkeit wie oberallgeier erklärt hat schonmal nicht ins Gewicht fallen ... definiere dein F_CPU doch mal mit 16000000 und poste hier ein stück des code und berichte mal die Zeit wie lange die LED leuchtet. Wenn da jetzt keine 10Skunden bei rauskommen, kann das nur 2 Gründe haben:

    1.) du verwendest irgend eine Art von Bilbiothek die das Verhalten deiner Wait Funktion stört
    2.) du verwendest eine Wait Funktion die nciht über Atmel Code gestuert wird

    bei 1. würde ich behaupten, dass es entweder eine "loop() funktion ist die nicht oft genug aufgerufen wird, wobei cih keine Ahnung hätte warum oder eventuell in der Bibliothek der F_CPU Wert irgendwo ein 2tes Mal falsch definiert ist (Achte auf den Compiler Output)
    bei 2. würde mich mal die quelle der wait funktion interessieren
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    .. Gedankenexperiment .. Nehmen wir an, ich definiere im Programmcode die 16 MHz als Taktfrequenz .. lasse ich alle Subs und Interrupts weg .. ?!
    So ungefähr.

    Vorschlag für nen Test, hier nur als Pseudocode

    Quellprogrammstart:
    - Initialisiere Ports (siehe Beispiel unten); es werden noch KEINE Interrupts initialisiert und schon garnicht freigegeben.

    DAnach:
    Schleife 1 (etwa zehn bis 20 mal)
    - schalte Test-LED auf aus
    - starte waitms 1000
    - schalte Test-LED auf ein
    - starte waitms
    Schleife 1 Ende

    Starte den Programmrest mit initialisierunge wie UART etc., Interrupts können freigegeben werden.

    Gib mal einen TEsttext auf UART aus.

    Schleife 2 (etwa zehn bis 20 mal)
    - schalte Test-LED auf aus
    - starte waitms 1000
    - schalte Test-LED auf ein
    - starte waitms
    Schleife 2 Ende

    Vergleiche die Laufzeiten . . .

    Hinterher allenfalls ärgern, nicht heulen. (hmmm - hoffentlich musste nicht auf mich schimpfen . . .)

    Codebeispiel (wie es bei mir auf praktisch allen Controllern läuft)
    Code:
    // ============================================================================= =
    // ===  HAUPTProgramm ========================================================== =
    // Initialisierungen, Ausgabe des Identifizierungsstrings per UART
    //      Start des aktuellen Programms
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     int main(void)                 //
     {                              //
      uint8_t i;                    //
      char abc[12];                 // Übersetzungsfeld für Werteausgabe
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // ===  Grundlegende Initialisierungen der Hardware, Portdefinition    -
    //  PCINT8,  XCK0,   T0, PB0   1        40  PA0, ADC0,  PCINT0         
    //  PCINT9,  CLKO,   T1, PB1   2        39  PA1, ADC1,  PCINT1         
    //  PCINT10, INT2, AIN0, PB2   3        38  PA2, ADC2,  PCINT2         
    //  PCINT11, OC0A, AIN1, PB3   4        37  PA3, ADC3,  PCINT3         
    //  PCINT12, OC0B,  /SS, PB4   5        36  PA4, ADC4,  PCINT4         
    //  PCINT13, ICP3, MOSI, PB5   6        35  PA5, ADC5,  PCINT5         
    //  PCINT14, OC3A, MISO, PB6   7        34  PA6, ADC6,  PCINT6         
    //  PCINT15, OC3B,  SCK, PB7   8        33  PA7, ADC7,  PCINT7         
    //                    /RESET   9        32  AREF                       
    //                       Vcc  10        31  GND                        
    //                       GND  11        30  AVcc                       
    //                     XTAL2  12        29  PC7, TOSC2, PCINT23        
    //                     XTAL1  13        28  PC6, TOSC1, PCINT22        
    //  PCINT24, RXD0,   T3, PD0  14        27  PC5, TDI,   PCINT21        
    //  PCINT25, TXD0,       PD1  15        26  PC4, TDO,   PCINT20        
    //  PCINT26, RXD1, INT0, PD2  16        25  PC3, TMS,   PCINT19        
    //  PCINT27, TXD1, INT1, PD3  17        24  PC2, TCK,   PCINT18        
    //  PCINT28, XCK1, OC1B, PD4  18        23  PC1, SDA,   PCINT17        
    //  PCINT29,       OC1A, PD5  19        22  PC0, SCL,   PCINT16        
    //  PCINT30,   OC2B, ICP PD6  20        21  PD7, OC2A,  PCINT31        
    //              ===================================================
    // ####>>>>     Initialisierung der Anschlüsse für R5M auf mega1284: <<<<####
    //           (           PB0   1 A   A  40  PA0         (CN 11-1 -Audi-Busy)
    // CN_12     (           PB1   2 A   A  39  PA1         (CN 11-3 -Audi-Clock)
    // PORTB     (           PB2   3 A   A  38  PA2         (CN 11-5 -Audi-Data)
    // (CIR od.  /           PB3   4 A?  E  37  PA3         (CN 11-4 -Audi)
    //  LCD ...  \           PB4   5 A   A  36  PA4, Servo10
    //  siehe    (     MOSI, PB5   6 A   A  35  PA5, Servo9
    //  unten    (     MISO, PB6   7 A   A  34  PA6, Servo8
    //  TasteC=3 (      SCK, PB7   8 EU  A  33  PA7, Servo7
    //  Taste /RES,       /RESET   9        32  AREF ref Vcc, aktuell
    //                       Vcc  10        31  GND                        
    //                       GND  11        30  AVcc                       
    //                     XTAL2  12     A  29  PC7, Servo6
    //                     XTAL1  13     A  28  PC6, Servo5
    //           RXD0,       PD0  14 EU  A  27  PC5, Servo4
    //           TXD0,       PD1  15 EU  A  26  PC4, Servo3
    //           RXD1,       PD2  16 EU  A  25  PC3, Servo2
    //           TXD1,       PD3  17 A   A  24  PC2, Servo1
    //           L1g         PD4  18 A   E  23  PC1, SDA   
    //           L1r         PD5  19 A   E  22  PC0, SCL   
    //             TasteA=1, PD6  20 EU  EU 21  PD7, TasteB=2, PCINT31, (Sound)
    // - - - - - - - - - - - - - - -
    // ####>>>>     PB3 ist evtl. Source für IR-DME-LED !! = CIR-LED
    // - - - - - - - - - - - - - - -
    // ####>>>>     Initialisierung/Anschlüsse von PORT B für LCD DEM 16x2
    //     data bit 4        PB0  0 A  WS Pin1 | 
    //     data bit 5        PB1  1 A     Pin2 | -- Der 10-polige Wannenstecker
    //     data bit 6        PB2  2 A     Pin3 |    ist an die Belegung wie beim
    //     data bit 7   SCK, PB3  3 A     Pin4 |    Transistortester angepasst
    //     RS line           PB4  RS      Pin5 |    es kommen noch
    //     ENABLE line MOSI, PB5  EN1     Pin6 |    Pin  9  GND und
    //     R/W (offen) MISO, PB6  R/W     Pin7 |    Pin 10  Vcc dazu
    //     NC (TasteC) SCK,  PB7  NC      Pin8 |___________________________
    //     GND                            Pin9   
    //     Vcc                            Pn10      | Anmerkg: ENABLE line !
    // - - - - - - - - - - - - - - -
    // Ports+Pins als Ein- (0) od Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren
    //      A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
      DDRA  = 0b11110110;   // PA0..2 WTV Bsy/Clk/Dto, PA3=Eingang f Sharp
      PORTA = 0b00000001;   //    und Port/Pull Ups (1)  aktivieren
                            //
      DDRB  = 0b01111111;   // siehe aktuell oben
      PORTB = 0b10000000;   //    und Port/Pull Ups (1)  aktivieren
                            //
      DDRC  = 0b11110111;   // PC0..7 (mega1284), PC0 + PC1 = I2C
      PORTC = 0b00000000;   // bis auf I2C : Alle OHNE Pullup !!
                            // 
      DDRD  = 0b00111100;   // -> siehe Schaltplan m-32-plus
      PORTD = 0b11000011;   //    Pull Ups aktivieren, NICHT bei extINT0/~1
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // <<<===  Etwa hier könnte Deine erste Testschleife stehen
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      for(i=0; i<10; i++)   // gLED1(PC3) blinken lassen bevor Interrupts erlaubt sind,
      {                     //   um ungewollte Resets u.ä. besser erkennen zu können
        SetBit(PORTD, L1g); // gnLED/PD4 schalten EIN, HELL
        wms(3);             // ###>>> HeartbeatLEDs schalten Aode -<|- Portpin <<<###
        ClrBit(PORTD, L1g); // gnLED/PD4 aus
        wms(97);            //
        SetBit(PORTD, L1r); // rtLED/PD5 schalten EIN, HELL
        wms(3);             // ###>>> HeartbeatLEDs schalten Aode -<|- Portpin <<<###
        if ( TAaus) ClrBit(PORTD, L1r);     // rtLED/PD5 aus WENN T1 nicht gedrückt
        wms(97);            //
      }                     // Ende von for(i=0; i<10; i++)
      ClrBit(PORTD, L1r);   // rtLED/PD5 auf JEDEN Fall aus
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      SrvCHK    = 1;        // Flag setzen für Extremwertprüfung aktiv             tmr
      TC1TMR_init();        // Init Tmr/Cntr1 für ServoPWMs                        tmr
    // - - - - - - - - - - - - - - -
      Izeit_1   = 20000;    // Der ZeitHorizont für ISR(TIMER2_COMPA_vect)
      Izthrznt  = 20000;    // Der ZeitHorizont für ISR(TIMER2_COMPA_vect)
      Isecundn  = 0;        // Sekundenzähler, max 9 Stunden - NUR hier nullen
      TC2TMR_init();    // Init Timer/Cntr2-Interrupt 20 kHz/50 µsec           tmr
                            //   ISR gibt auf PD4/L1g (gnLED) ein Taktsignal aus
      kal_0();              // Initialisieren aus KOnstanten-Liste = div. Vorgaben kal
    
    // - - - - - - - - - - - - - - -
      lcd_init();           //                                                     lib
      lcd_01 ( );           // Info über LCD                                       inf
    //      Anmerkung zu LCD_01     Diese Routine muss früh laufen, vor Allem
    //              VOR der UART1-Initialisierung. Denn die schnelle UART1 verzögert
    //              die Routine wms dramatisch ! ! !
    //
      STSi2c        = 0;    // Statusbyte I2C auf "nicht initialisiert" setzen
      I2C_init ();          // I2C-Buffer initialisieren, I2C-Slave-Init           I2C
    
    //init_uart0(MYUBRR);  // USART0 initialisieren m wählbarer Baudrate (s.o.)    inf
      init_uart0 ( (u16)(F_CPU / BAUD / 16 - 0.5) );    // Init UART0 nach PDannegger
    // Die ##-routinen für LCD-Betrieb wieder aktivieren - stören dann den IR-LED-Takt
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
      sei();        // Globalen Interrupt freigeben
      info01 ();            // Startinfo über USART ausgeben                      main
    //  . . .
    //  . . . 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // <<<===  Etwa hier könnte Deine zweite Testschleife stehen
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Ciao sagt der JoeamBerg

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    24.06.2018
    Ort
    Bayern
    Beiträge
    8
    .. Codebeispiel (wie es bei mir auf praktisch allen Controllern läuft) ..
    Nun hab ich ein ähnliches Programm erstellt, einmal mit den Interrupts und einmal ohne Schnickschnack.

    Ergebnis: Das Programm wird doch tatsächlich so stark gebremst, dass es nur circa halb so schnell läuft! Erstaunlich!
    Ohne die Hintergrund-Routinen stimmen dann die "Wait"-Zeiten ziemlich gut.


    --> Im Hintergrund läuft im normalen Programm die Servo-Bibliothek, die mit den sechs Servos des Roboter Arms wohl recht beschäftigt ist.


    .. Hinterher allenfalls ärgern, nicht heulen. (hmmm - hoffentlich musste nicht auf mich schimpfen . . .) ..
    Alles gut

    Vielen Dank für eure Hilfe.
    Offtopic: Wo passen denn zukünftige Beiträge rein, die den Roboterarm betreffen? Es gibt viele Unterforen zu "Asuro" usw., allerdings finde ich hierfür nichts.

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    Die Servo Lib benutzt meines Wissens nach Software PWM, schaltet die Pins also "manuell" an und aus

    Du könntest dich evtl. mal mit den Timern für Atmegas beschäftigen, die haben i.d.R. mind 2 Timer mit jeweils 2 PWM Ausgängen, die deine Servos, ohne auch nur ein einziges Stück Code (ausgenommen Initialisierung und bei Änderung der Position), ansteuern können.

    Der Timer zählt dabei einfach nur hoch und wenn der Timer dabei den WErt des Compare REgister des Ausgangs erreicht schaltet er den zugehörigen Pin an oder aus, je nachdem wie der Timer und die PWM konfigurtiert ist.

    Du musst dann praktisch nur das Compare Register mit 2-3 Prozessorzyklen ändern um den Servo passend zu verstellen (ausgenommen die Berechnung deiner Zielposition)

    PS leider ist das Pin Mapping limitiert und du musst vermutlich einige Pins umplanen und die Progammierung wird dann auch schwer in Richtung "Bare Metal" kippen, also andere Librarys verwenden wird dann evtl. Probleamtischer ... oder du findest heraus mit welcher anderen SErvo Lib oder wie du mit der bestehenden Servo Lib die Hardware PWM nutzen kannt um das Problem zu minimieren.
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    .. Programm .. einmal mit den Interrupts und einmal ohne Schnickschnack .. Programm .. so stark gebremst, dass es nur circa halb so schnell läuft ..
    Na ja, pingelig gesagt läuft "das Programm" immer gleichschnell, nur wird der Ablauf durch die Interruptroutinen zu einem guten Teil belegt, der Rest muss sich mit der von den Interruptroutinen übrig gelassenen Zeit begnügen. Und daher ist - sorry dass ich das so ausdrücke - Deine Interpretation, dass Dein Programm ".. nur circa halb so schnell läuft.. " falsch. Ohne Interrupt läuft Dein Programm sozusagen alleine, hat alle Zeit NUR für sich - und sieht daher schnelllaufend aus. Mi[ISRläuft]t Inte[ISRläuft]rrupt b[ISRläuft]leibt [ISRläuft]halt ni[ISRläuft]cht me[ISRläuft]hr all[ISRläuft]e Zei[ISRläuft]t für d[ISRläuft]en Re[ISRläuft]st ü[ISRläuft]rig. Anmerkung: die Interruptserviceroutinen sind üblicherweise nie gleich lang! Die Länge kann aus der "meinfile.lls"-Datei abgeleitet werden.

    Hauptsatz: der Controller kann vom üblichen Programmablauf nur jeweils einen Schritt abarbeiten, nie zwei Schritte gleichzeitig. Ausnahmen bilden hardwareimplantierte Dinge wie einige Zähler, Timer etc.

    .. Im Hintergrund läuft .. die Servo-Bibliothek, die mit den sechs Servos des Roboter Arms wohl recht beschäftigt ist ..
    Ach ja, soo schlimm ist es nicht - aber ich kenne leider Deine Bibliothek nicht. Ich habe bei den Armen (und im Kopf) von meinem archie jeweils einen Kontroller der maximal zehn Servos bedient. Zu diesen - interruptgetriebenen Servoroutinen - kommen noch andere Dienste. Mit Interrupt z.B. Boardtimer, UART, I²C und solcher Spass. Beim Motorcontroller ists ähnlich, aber ohne Servoroutinen, dort läuft durch ein Flag (von einem Timer-Interrupt gesetzt) im "normalen" Programmablauf z.B. die Regelroutine für die beiden Motoren. Das wird alles einigermassen gut verschachtelt.

    Verschachtelt? Beispiel Servos. Meine analogen wollen ja alle 20 ms einen Puls von beliebiger Länge 0,5 bis 2 ms. Also läuft der "Servotimer" - nennen wir ihn ST0 so, dass alle 2 (!!!) ms EIN einziger Servo mit der ID "Servopointer" eingeschaltet wird <=> Puls wird high gesetzt, dazu ein Timer ST1, der die Länge des Pulses begrenzt. Wenn ST1 abgelaufen ist, schaltet der den Puls ab UND setzt den Servopointer eins rauf. Wenn der Servopointer auf 11 ist, wird er auf 1 gesetzt. Nach dem Ablauf der 2 (!!!) ms von ST0 wird also der nächste Servo . . . usw. Diese 2 ms sind bei meinen 20Mhz-getakteten Controllern eine kleine Ewigkeit, da kann man vielerlei andere Ding zwischendurch erledigen. Und nach dem zehnten Servo sind 20 ms vorbei und der erste kommt wieder dran.

    Du siehst oben, dass Deine Interruptserviceroutinen dem Ablauf z.B. Deiner waitms-Schleife etliche Zeit wegnehmen, dadurch kann die nicht glatt, ungestört, durchlaufen. Übrigens sind diese waitms- oder delayxx-Routinen böse Bremsen, weil die ausser interruptgetriebenen Abläufen keine weiteren Aktionen zulassen. Daher erledige ich so etwas üblicherweise mit einem Flag, das im Boardtimer gesetzt wird. Dieser Boardtimer ist bei mir eine Interruptroutine, die alle 50 µs die boardinterne Zeit eins höher setzt. Also kann ich z.B. nen tmrxy1 machen, der in der ISR fallweise runtergetickert wird.

    Fallweise? Klar, dort heißt es dann
    ....if ( tmrxy1 ) tmrxy1 --; // einfach tickern bis Null; Allzwecktimer s. ~com~
    und bedeutet dass, solagen tmrxy1 ungleich null (bedeutet true ! *gg*) ist, wird er runtergezählt. Und ich kann ihn in der Zwischenzeit auf Null prüfen und ne Aktion machen sobald er wieder auf Null ist. Manche Abläufe laufen ähnlich, aber mit hochgetickerten Timer.

    Ende, viel zu viel - TL;DR. Aber vielleicht wird Dir damit der Programmablauf im Controller klar(er).
    Geändert von oberallgeier (04.09.2018 um 10:16 Uhr) Grund: Unrichtige Timingbeschreibung (20 statt 2 ms) korrigiert. Sorry.
    Ciao sagt der JoeamBerg

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    24.06.2018
    Ort
    Bayern
    Beiträge
    8
    Zitat Zitat von Ceos Beitrag anzeigen
    Die Servo Lib benutzt meines Wissens nach Software PWM, schaltet die Pins also "manuell" an und aus ..
    Davon gehe ich auch aus.

    .. Du könntest dich evtl. mal mit den Timern für Atmegas beschäftigen ..
    Hatte noch nicht die Zeit, die Servo-Bibliothek mit eigener Timer-Interrupt Steuerung zu ersetzen, hab das aber noch vor, da mir die Lib. sowieso zu ungenau unterteilt.

    .. PS leider ist das Pin Mapping limitiert und du musst vermutlich einige Pins umplanen ..
    Das hatte ich schon befürchtet.





    Zitat Zitat von oberallgeier Beitrag anzeigen
    Na ja, pingelig gesagt läuft "das Programm" immer gleichschnell ..
    Klar, das "gesamte" Programm.

    .. Deine Interpretation, dass Dein Programm ".. nur circa halb so schnell läuft.. " [ist] falsch.
    Ja. Ich denke, wir können uns darauf einigen, dass durch die Unterbrechungen der ISR die Befehle in der Hauptschleife (bzw. "Main") weniger oft ausgeführt werden (können).

    .. Die Länge [der ISR] kann aus der "meinfile.lls"-Datei abgeleitet werden. ..
    Das wusste ich nicht. Wo finde ich die Datei?

    .. der Controller kann vom üblichen Programmablauf nur jeweils einen Schritt abarbeiten ..
    Klar, Multithreading muss mit nur einem Prozessorkern hintereinander ablaufen.





    .. einen Kontroller der maximal zehn Servos bedient ..
    Sollte auch kein Problem darstellen, wenn man bedenkt, dass die ISR hier nur jeweils einen Pin setzt oder rücksetzt. Es sollten sogar mehr als zehn Servos möglich sein, da die 50 Hz normalerweise nicht so kritisch sind.

    .. "Servotimer" - nennen wir ihn ST0 [...] dazu ein Timer ST1, der die Länge des Pulses begrenzt. ..
    Es sollte auch möglich sein, beides mit einem Timer abzuarbeiten, also Pulse und Pausen - ich hab mir das für meine zukünftige Ansteuerung überlegt. Das System ist ansonsten gleich:
    Puls1, Pause1 (ausrechnen), Puls2, Pause2 (ausrechnen),... die Pause muss so berechnet werden, dass (Puls+Pause)*6=20 ms ergibt, da ich momentan maximal sechs Servos verwende.

    Man könnte die Restzeit alternativ auch hinten dran hängen, dann sollte Puls+Pause jeweils 2 ms lang sein, wobei - wie schon angemerkt - die angestrebte Frequenz nicht so wichtig ist.
    Interessant wäre daher auch noch folgender Versuch (ebenfalls mit einem Timer):
    Puls1, Puls2, ...Puls6, 11 ms Pause.
    Nach meiner Rechnung schwankt die Frequenz dann zwischen 43,5 und 58,8 Hz. Ich denke, das sollte noch problemlos funktionieren. Hat sowas schon einmal jemand versucht?

    .. Übrigens sind diese waitms- oder delayxx-Routinen böse Bremsen ..
    Das ist richtig. Die Routinen nutze ich normalerweise nur für unwichtige Sachen in der Hauptschleife. Für zeitkritische Anwendungen nutze ich auch gerne Timer, die Variablen hochzählen, um genauso eine Art Boardtimer zu erhalten, mit dem man wiederum durch Flags Teile im Hauptprogramm starten kann, um die ISR möglichst kurz zu halten.


    Nebenbei, Archie sieht nach einem sehr interessanten Projekt aus!

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Verschiedene FET's ?
    Von maxman1506 im Forum Elektronik
    Antworten: 12
    Letzter Beitrag: 11.03.2012, 18:42
  2. Schrittmotorenansteuerung: Welche Taktraten??
    Von bernhard1366 im Forum Motoren
    Antworten: 1
    Letzter Beitrag: 07.03.2008, 11:26
  3. Verschiedene Kleinmotoren
    Von $robocop$ im Forum Motoren
    Antworten: 5
    Letzter Beitrag: 08.05.2007, 20:22
  4. Verschiedene Frequenzen
    Von T.r.Agent D im Forum AVR Hardwarethemen
    Antworten: 5
    Letzter Beitrag: 28.05.2006, 17:23
  5. 2 Verschiedene Zeitabläufe ?
    Von BlaueLed im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 28.09.2005, 12:30

Stichworte

Berechtigungen

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

Labornetzteil AliExpress