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

Thema: Verschiedene Taktraten im Atmega?

Hybrid-Darstellung

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

    Frage Verschiedene Taktraten im Atmega?

    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
    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?!

  4. #4
    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.

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.677
    .. 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

  6. #6
    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.

  7. #7
    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.

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.677
    .. 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

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.677
    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

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.677
    Zitat Zitat von Don Simon Beitrag anzeigen
    .. ich werke .. mit eingebautem Atmega64 und externem 16 MHz Quarz, programmiere mit Bascom/Ponyprog/ISP ..
    .. Das wusste ich nicht. Wo finde ich die Datei? ..
    Oh weh, böses Eigentor - ich hatte nicht daran gedacht, dass Du mit Bascom arbeitest. Ich programmiere meine Atmels mit C (kaum C++) und AVRStudio4 oder Studio7. Da finde ich diese Datei im Projektordner, Subdirectory "default". Sieht etwa wie folgt aus; im Beispiel heißt die Datei ARCo.lss, hier nur Anfang, danach stark gekürzt :
    Code:
    ARCo.elf:     file format elf32-avr
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 .data         00000d9e  00800100  00005922  000059d6  2**0
                      CONTENTS, ALLOC, LOAD, DATA
      1 .text         00005922  00000000  00000000  000000b4  2**1
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      2 .bss          000003b7  00800e9e  00800e9e  00006774  2**0
                      ALLOC
      3 .eeprom       000001ea  00810000  00810000  00006774  2**0
                      CONTENTS, ALLOC, LOAD, DATA
      4 .debug_aranges 00000020  00000000  00000000  0000695e  2**0
                      CONTENTS, READONLY, DEBUGGING
      5 .debug_pubnames 000008ef  00000000  00000000  0000697e  2**0
                      CONTENTS, READONLY, DEBUGGING
      6 .debug_info   00003355  00000000  00000000  0000726d  2**0
                      CONTENTS, READONLY, DEBUGGING
      7 .debug_abbrev 000003eb  00000000  00000000  0000a5c2  2**0
                      CONTENTS, READONLY, DEBUGGING
      8 .debug_line   000045d7  00000000  00000000  0000a9ad  2**0
                      CONTENTS, READONLY, DEBUGGING
      9 .debug_frame  00000600  00000000  00000000  0000ef84  2**2
                      CONTENTS, READONLY, DEBUGGING
     10 .debug_str    00000897  00000000  00000000  0000f584  2**0
                      CONTENTS, READONLY, DEBUGGING
     11 .debug_loc    00001f04  00000000  00000000  0000fe1b  2**0
                      CONTENTS, READONLY, DEBUGGING
     12 .debug_ranges 00000270  00000000  00000000  00011d1f  2**0
                      CONTENTS, READONLY, DEBUGGING
    
    Disassembly of section .text:
    
    00000000 <__vectors>:
           0:    0c 94 46 00     jmp    0x8c    ; 0x8c <__ctors_end>
           4:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
           8:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
           c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          10:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          14:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          18:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          1c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          20:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          24:    0c 94 32 0b     jmp    0x1664    ; 0x1664 <__vector_9>
          28:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          2c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          30:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          34:    0c 94 ce 07     jmp    0xf9c    ; 0xf9c <__vector_13>
          38:    0c 94 b3 0a     jmp    0x1566    ; 0x1566 <__vector_14>
          3c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          40:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          44:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          48:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          4c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          50:    0c 94 a4 00     jmp    0x148    ; 0x148 <__vector_20>
          54:    0c 94 d3 00     jmp    0x1a6    ; 0x1a6 <__vector_21>
          58:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          5c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          60:    0c 94 14 0c     jmp    0x1828    ; 0x1828 <__vector_24>
          64:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          68:    0c 94 1d 02     jmp    0x43a    ; 0x43a <__vector_26>
          6c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          70:    0c 94 76 01     jmp    0x2ec    ; 0x2ec <__vector_28>
          74:    0c 94 a6 01     jmp    0x34c    ; 0x34c <__vector_29>
          78:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          7c:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          80:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          84:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
          88:    0c 94 65 00     jmp    0xca    ; 0xca <__bad_interrupt>
    
    0000008c <__ctors_end>:
          8c:    11 24           eor    r1, r1
          8e:    1f be           out    0x3f, r1    ; 63
          90:    cf ef           ldi    r28, 0xFF    ; 255
          92:    d0 e4           ldi    r29, 0x40    ; 64
          94:    de bf           out    0x3e, r29    ; 62
          96:    cd bf           out    0x3d, r28    ; 61
    
    00000098 <__do_copy_data>:
          98:    1e e0           ldi    r17, 0x0E    ; 14
          9a:    a0 e0           ldi    r26, 0x00    ; 0
          9c:    b1 e0           ldi    r27, 0x01    ; 1
          9e:    e2 e2           ldi    r30, 0x22    ; 34
          a0:    f9 e5           ldi    r31, 0x59    ; 89
          a2:    00 e0           ldi    r16, 0x00    ; 0
          a4:    0b bf           out    0x3b, r16    ; 59
          a6:    02 c0           rjmp    .+4          ; 0xac <__do_copy_data+0x14>
          a8:    07 90           elpm    r0, Z+
          aa:    0d 92           st    X+, r0
          ac:    ae 39           cpi    r26, 0x9E    ; 158
          ae:    b1 07           cpc    r27, r17
          b0:    d9 f7           brne    .-10         ; 0xa8 <__do_copy_data+0x10>
    
    000000b2 <__do_clear_bss>:
          b2:    12 e1           ldi    r17, 0x12    ; 18
          b4:    ae e9           ldi    r26, 0x9E    ; 158
          b6:    be e0           ldi    r27, 0x0E    ; 14
          b8:    01 c0           rjmp    .+2          ; 0xbc <.do_clear_bss_start>
    
    000000ba <.do_clear_bss_loop>:
          ba:    1d 92           st    X+, r1
    
    000000bc <.do_clear_bss_start>:
          bc:    a5 35           cpi    r26, 0x55    ; 85
          be:    b1 07           cpc    r27, r17
          c0:    e1 f7           brne    .-8          ; 0xba <.do_clear_bss_loop>
          c2:    0e 94 06 2a     call    0x540c    ; 0x540c <main>
          c6:    0c 94 8f 2c     jmp    0x591e    ; 0x591e <_exit>
    
    000000ca <__bad_interrupt>:
          ca:    0c 94 00 00     jmp    0    ; 0x0 <__vectors>
    
    000000ce <init_uart0>:
                        // count up and wrap around
    
    // ============================================================================== =
    void init_uart0( u16 bauddivider )
    {
      UBRR0H = bauddivider >> 8;
          ce:    90 93 c5 00     sts    0x00C5, r25
      UBRR0L = bauddivider;            // set baud rate
          d2:    80 93 c4 00     sts    0x00C4, r24
      UCSR0A = 0;                // no U2X, MPCM
          d6:    10 92 c0 00     sts    0x00C0, r1
      UCSR0C = 1<<UCSZ01^1<<UCSZ00        // 8 Bit
          da:    86 e0           ldi    r24, 0x06    ; 6
          dc:    80 93 c2 00     sts    0x00C2, r24
    #ifdef URSEL0
           ^1<<URSEL0            // if UCSR0C shared with UBRR0H
    #endif
           ;
      UCSR0B = 1<<RXEN0^1<<TXEN0^        // enable RX, TX
          e0:    88 e9           ldi    r24, 0x98    ; 152
          e2:    80 93 c1 00     sts    0x00C1, r24
           1<<RXCIE0;            // enable RX interrupt
      rx_in = rx_out;            // set buffer empty
          e6:    80 91 21 0f     lds    r24, 0x0F21
          ea:    80 93 20 0f     sts    0x0F20, r24
      tx_in = tx_out;
          ee:    80 91 a3 0f     lds    r24, 0x0FA3
          f2:    80 93 a2 0f     sts    0x0FA2, r24
    }
          f6:    08 95           ret
    
    000000f8 <ukbhit0>:
    
    
    // ============================================================================== =
    u8 ukbhit0( void )
    {
      return rx_out ^ vu8(rx_in);        // rx_in modified by interrupt !
          f8:    90 91 21 0f     lds    r25, 0x0F21
          fc:    80 91 20 0f     lds    r24, 0x0F20
    }
         100:    89 27           eor    r24, r25
         102:    08 95           ret
    
    00000104 <ugetchar0>:
    
    
    // ============================================================================== =
    u8 ukbhit0( void )
    {
      return rx_out ^ vu8(rx_in);        // rx_in modified by interrupt !
         104:    90 91 21 0f     lds    r25, 0x0F21
         108:    80 91 20 0f     lds    r24, 0x0F20
    // ============================================================================== =
    u8 ugetchar0( void )
    {
      u8 data;
    
      while( !ukbhit0() );            // until at least one byte in
         10c:    98 17           cp    r25, r24
         10e:    d1 f3           breq    .-12         ; 0x104 <ugetchar0>
      data = rx_buff[rx_out];        // get byte
         110:    e0 91 21 0f     lds    r30, 0x0F21
         114:    f0 e0           ldi    r31, 0x00    ; 0
         116:    e0 56           subi    r30, 0x60    ; 96
         118:    f1 4f           sbci    r31, 0xF1    ; 241
         11a:    e0 81           ld    r30, Z
      ROLLOVER( rx_out, RX0_SIZE );
         11c:    80 91 21 0f     lds    r24, 0x0F21
         120:    8f 5f           subi    r24, 0xFF    ; 255
         122:    80 93 21 0f     sts    0x0F21, r24
         126:    80 91 21 0f     lds    r24, 0x0F21
         12a:    87 ff           sbrs    r24, 7
         12c:    02 c0           rjmp    .+4          ; 0x132 <ugetchar0+0x2e>
         12e:    80 e0           ldi    r24, 0x00    ; 0
         130:    02 c0           rjmp    .+4          ; 0x136 <ugetchar0+0x32>
         132:    80 91 21 0f     lds    r24, 0x0F21
         136:    80 93 21 0f     sts    0x0F21, r24
      URX0_IEN = 1;                // enable RX interrupt
         13a:    80 91 c1 00     lds    r24, 0x00C1
         13e:    80 68           ori    r24, 0x80    ; 128
         140:    80 93 c1 00     sts    0x00C1, r24
      return data;
    }
         144:    8e 2f           mov    r24, r30
         146:    08 95           ret
    
    00000148 <__vector_20>:
    ...
    ...
    und so weiter
    // ============================================================================== =
    Hier könnte man (wenn man viel Zeit hat - und Lust, oder wenn man es nötig findet) die Befehle jmp, ldi, out oder alle andern MAschinenbefehle im Datenblatt suchen und deren Anzahl von CPU-Takten notieren. Diese Taktanzahl für die jeweils interessierenden Abschnitte (Subroutinen, ISR etc) zusammenzählen und mit der Taktdauer multiplizieren . . .

    .. Nebenbei, Archie sieht nach einem sehr interessanten Projekt aus!
    Danke. Ja, schon etwas zeitintensiv, ich lass mir halt Zeit.
    Geändert von oberallgeier (07.09.2018 um 17:08 Uhr) Grund: Kurz erläutert: Zeitbedarf von Routinen
    Ciao sagt der JoeamBerg

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
  •  

fchao-Sinus-Wechselrichter AliExpress