- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 10 von 10

Thema: Arduino Leistungsfähig genug? 6 Schrittmotoren + Inkrementalgeber

Hybrid-Darstellung

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

    Arduino Leistungsfähig genug? 6 Schrittmotoren + Inkrementalgeber

    Hallo,

    folgendes Problem beschäftigt mich zurzeit. Da ich selber noch recht wenig Erfahrung habe, hoffe ich dass einige von euch mir weiter helfen können.

    Ich Suche momentan einen Weg 6 Schrittmotoren sowie deren Inkrementalgeber zu steuern sowie auszulesen.
    Nun liegt das Problem in der Sache, dass ich die Inkrementalgeber gerne über Interrupts auslesen würde, um möglichst keine Schritte zu verpassen. Bei 6 Inkrementalgebern die jeweils ungefähr 7000 mal pro Sekunde ein Signal senden, kommt da einiges zusammen. Ist das direkt auf einem Arduino von der Geschwindigkeit realisierbar?
    Desweiteren bräuchte ich ja dann 6 Interrupt pins, allerdings habe ich da noch keinen Weg gefunden, da die Arduinos meistens ja 2 Interruptpins besitzten. Wenn jemand einen Link zu einem Shield hätte, der mir da weiterhilft wäre das echt super.
    Welches Arduino Board benutzt wird, steht noch offen, daher haben wir da noch freie Wahl

    Ansonsten sollte auf diesem Arduino noch 7 Servomotoren in einem vorher festgelegten Bewegungsablauf gesteuert werden, was ich über eine Maestro Karte realisieren werde.

    Die alternative Idee, sollte die Schrittmotorsteuerung nicht möglich sein, wäre diese durch Nanotec Treiber zu realisieren, die sich dann mittels RS485 Bus mit dem Arduino unterhalten. Dies wäre allerdings erheblich teurer mMn.

    Gruß,
    Sagre

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.188
    Bei den Arduinos sind meines Wissens AVR Controller verbaut.
    Einige, vor allem die neueren Typen unterstützen Pin Change Interrupts.
    Das bedeutet ein Interrupt wird ausgelöst, sobald sich ein Pegel an einem Pin der Gruppe ändert.
    Welcher das nun war müsstest Du in der Interruptroutine selber rausfinden.
    Ich fürche auch fast, das das ein ATMEGA auch nicht mehr schafft.
    Im Extremfall hast Du ja 7000 x 6 = 42000 Interrupts pro Sekunde.
    Auch wenn der Controller mit 20MHz läuft hast Du gerade mal 476 Maschinenzyklen ( Takte ) pro Interrupt.
    Das geht mit Assembler sicher noch, mit Bascom wird das wohl nichts mehr.
    Zusätzlich entstehen ja noch weitere Interrupts duch die Servoroutinen.

    Wenn dein Programm für den Interrupt fertig ist, kannst Du per Simulator erproben, wieviele Zyklen der Controller für die Abarbeitung der Interruptroutine braucht.

    Ob das mit den Servos noch geht oder nicht lässt sich vermutlich nur in der Praxis erproben.
    Du könntest ja zum Beispiel einen Port auf 1 setzen, sobald der Controller im Interrupt ist, verlässt der Controller den Interrupt kannst Du diesen Port wieder auf 0 setzen.
    Wenn Du dann ein Oszilloskop auf diesen Pin hängst siehst Du, ob der Controller noch Zyklen frei hat.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    21.12.2009
    Beiträge
    8
    Hallo, danke dir erst einmal für deine Antwort.

    Ich werde mich ersteimal langsam herantasten, und erst einmal einen Sensor und einen Motor steuern. Leider bin ich sehr unerfahren was Mikokontroller anbegeht, und muss mich ersteinmal für jeden Begriff einlesen. Aber das wird schon

    Vermutlich meinst du mit den Interupts einen Pin Change interrupt? Dadrin werde ich mich aufjedenfall mal einlesen, scheint genau das zu sein was ich brauche
    Wir sind allerdings jetzt von einem Arduino weg, und versuchen uns gerade an einem Atmega32, der hier noch herumlag.

    Da ist bereits bei uns eine Frage aufgetaucht:

    Momentan versuchen wir erst einmal die USB-Kommunikation mit einem Rechner aufzubauen, um überhaupt rückmeldungen über die Sensor Daten zu erhalten. Das schicken von Nachrichten vom Atmega zum Rechner (hTerm) funktioniert schonmal super.
    Nur leider reagiert der Atmega rein gar nicht auf die Nachrichten des Rechners.
    Wir arbeiten mit der UART Library von PeterFleury. Kann uns da evt jemand weiterhelfen?

    char UART_RECIEVE(void) {
    unsigned int x;
    for(; {
    x= uart_getc();
    if(!(x&UART_NO_DATA)) return (char)x;
    }
    }


    in der main sieht es dann so (im Ausschnitt) so aus:

    int main() {
    while(1){
    char c = UART_RECIEVE();
    uart_puts(c);
    sleep(1000);
    }

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.653
    ... meinst du mit den Interupts einen Pin Change interrupt? ... mal einlesen ... Atmega32, der hier noch herumlag ...
    Nur mal so als Anmerkung: gerade der ATmega32/ATmega32L hat keinen Pin Change Interrupt, siehe das (vermutlich aktuellste) Datenblatt 2503Q–AVR–02/11. Hier wird der pinkompatible mega1284 Deinen Vorstellungen eher entsprechen, drei externe Interrupts und vier Pingruppen ready for PCI - somit theoretisch sieben (externe, pinbezogene) Interrupts. Selbst beim Übertakten der maximal spezifizierten 20 MHz wirst Du aber feststellen müssen, dass wkrug mit seiner Abschätzung ziemlich gut liegt.

    ... Wenn dein Programm für den Interrupt fertig ... wieviele Zyklen ... für die Abarbeitung der Interruptroutine ...
    Die Zyklenzahl kannst Du aus der deincompilat.lls herauslesen. Da drin stehts nämlich haarklein. Ein Beispiel dazu hier.
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Roboter Genie Avatar von malthy
    Registriert seit
    19.04.2004
    Ort
    Oldenburg
    Beiträge
    1.379
    Hi!

    Vermutlich geben die Inkrementalgeber ein Quadratursignal aus. Es ist im Allgemeinen nicht die beste Lösung, dieses per ext. Interrupts (INTx/PCINT) auzuwerten (siehe: http://www.mikrocontroller.net/articles/Drehgeber). Unter gewissen Randbedingungen (insb. Encocder prellt nicht, weil magnetischer Encoder) mag das dennoch eine Variante sein. Grundsätzlich sollte man die Encodersignale besser per Timerinterrupt mit festem Intervall abtasten und auswerten. Dann müsstest Du pro Timer-ISR Aufruf dann eben alle Encoder auswerten. Die Auswertung ist nicht sonderlich rechenintensiv. Wenn Du Dir sicher bist dass die 7k Ticks/s reichen, sollte das grundsätzlich mit einem AVR zu machen sein. Ob das High-Level mit dieser Arduino Sprache hinhaut, kann ich nicht beurteilen, damit kenne ich mich nicht aus. Das wäre ansonsten ein klassischer Fall für Assembler. Zum Festlegen der Abtastrate solltest Du brücksichtigen, dass das Quadratursignal in den seltensten Fällen wirklich symmetrisch ist, zur Sicherheit könnte man größenordnungsmäßig mit Faktor zwei Abtasten.

    Gruß
    Malte
    Geändert von malthy (10.09.2014 um 12:50 Uhr) Grund: typos

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    15.12.2008
    Ort
    Bad Ems
    Alter
    62
    Beiträge
    109
    Hallo,

    ich muss malthy Recht geben. Die Auswertung per Pin-Change-Interrupt ist nicht zu empfehlen. Für Dein Problem solltest Du den oder die Encoder im Timer-Interrupt mit einer festen Frequenz abfragen. Mir ist allerdings nicht ganz klar, ob Du jetzt nur einen AVR-Controller oder aber wirklich einen Arduino benutzt. Falls Du den Arduino nimmst, könntest Du einmal hier nachlesen: http://www.meinduino.de/drehencoder.shtml. Da ist in Teil I die Auswertung per Polling und in Teil II die Auswertung des Encoders im Timer-Interrupt beschrieben. Vielleicht gelingt es Dir, den Sketch im II. Teil an Deine Bedürfnisse anzupassen.

    Gruß,
    Ralf
    Geändert von Schachmann (10.09.2014 um 22:43 Uhr) Grund: Tippfehler
    http://www.Elektronik-Bastelkeller.de - Elektronik und Mikrocontroller als Hobby

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.653
    ... Vermutlich geben die Inkrementalgeber ein Quadratursignal ... im Allgemeinen nicht die beste Lösung, dieses per ext. Interrupts ... auzuwerten ...
    Die Frage ist ja, ob es Sinn macht das komplette Quadratursignal (wenn es eins ist) auszuwerten.

    ......Bild hier  

    Warum? Weil ich einigermassen sicher bin, dass der Versatz der Signalflanken nicht genau gleich ist (so lange ich den Encoder nicht selbst hergestellt oder ausführlich getestet habe). Dann kommt eine Ungenauigkeit rein, die sich bei hohen Drehzahlen - und den damit verbundenen wenigen Timerticks schon wesentlich auf die Regelung auswirken kann. Hier wäre zu überlegen, ob man nicht (nur) jede gleichsinnige Flanke einer Encoderspur auswertet. Wenns nicht gerade eine hochgenaue Drehzahlregelung für etliche zehntausend Touren sein soll dürfte das reichen und möglicherweise eine genauere Regelungsgrundlage liefern als die Auswertung aller Flanken.

    Die Lösung mit dem externen Interrupt ist nicht die schlechteste. Ich fahre bei meinem Dottie, beim MiniD0 und beim Archie, alles aber KEINE Schrittmotoren, mit dem externen Interrupt für steigende Flanke (beim Archie nur für EINE Endoderspur - je Motor *gg*) und werte in der zugehörigen ISR natürlich auch gleich die zweite Spur zur korrekten Wegberechnung (Drehrichtungserkennung) aus. Der Erfolg ist eine überraschend hohe Geschwindigkeitstreue. Ob Schrittmotoren in dieser Hinsicht empfindlicher sind, kann ich aber nicht sagen.

    ... Inkrementalgeber gerne über Interrupts auslesen würde, um möglichst keine Schritte zu verpassen ...
    Wenns nicht um genaue Drehzahlregelung geht, sondern nur um exakte Wegerfassung (Drehwinkel), dann sehe ich das CPU-Laufzeitproblem nicht so gravierend, weil es nur wenige Codezeilen sind:

    Die vollständige ISR für (m)einen Encoder bei Archie (der zugehörige *lls-Auszug ist gaaaanz unten) :
    Code:
    // ============================================================================= =
    // ===  Nicht unterbrechbare ISR für EXT_INT0 auf Pin 4/PD2/mega328
    // Der Timer tmrE0 für Laufzeit des EXT_INT0 wird ausgelesen
    //      Der zugehörige Motor auf PD7/PB0 = re,li und PB1 Geschwind./PWM
     ISR(INT0_vect)                 // INT0 triggert auf RISING edge => 
     {                              //   => Wenn Aufruf, dann PORTD2 = high
    // - - - - - - - - - - - - - - - -
    //      Encoderticks Iencdrx nur hochzählen, IencBx rauf- od runterzählen
      Iz_diff0  = tmrE0;    // Abspeichern Zeit seit dem letzten ISR-Aufruf
      tmrE0     =    0;     // Resetten ##>> IN der ISR ohne CLI/SEI möglich
      Iencdr0 ++;           // Incrementiere Encodercounter, zählt NUR aufwärts
      if (IsBitSet (PIND, 4)) IencB0++;     // Rad treibt vorwärts,  math. negativ
      else                    IencB0--;     // Rad treibt rückwärts, math. positiv
     }      // Ende ISR(INT0_vect)
    // ============================================================================= =
    In der Timer-ISR - 20 kHz <=> 50 µs - wird der Zeitwert tmrE0 getickert:
    Code:
    // ===  Nicht unterbrechbare ISR für timer2 =================================== */
    // Routine zählt hoch im Takt 20 kHz = 50 µs.  Der Zählerwert wird von den ISR für
    //      EXT_INT0 und -INT1 ausgelesen
     ISR(TIMER2_COMPA_vect)         // 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     {                              //
      Izeit_1 --;           //  ###>>> Izeit_1 ist aktuell int16_t ==>>
                            //  Izeit_1 bleibt bis 32000 in der int16-Grenze
      tupUM0 ++;            // Tupsicounter für Umdrehungsmessung(en)
      tmrE0   ++;           // Encodertimer hochtickern
      tmrE1   ++;           // Encodertimer hochtickern
    //RCzeit1 ++;           // Tupsicounter uint16_t für RC-5-Decoding
    
      if ( Izeit_1 )        // Interrupt-Timer = 1 ... 20 000 ... (1 sec blink)
        {  }                // WENN Izeit_1 =|= Null => wahr => Anweisung ausgeführen
      else                  // Izeit_1 = Null = unwahr, daher "else" ausführen
      {                     // Eine Sekunde ist voll =>
        Izeit_1 = Izthrznt; // ansonsten: Rückstellen auf Zeithorizont
        ToggleBit (PgLED, L1g);     // gnLED toggeln    HEARTBEAT <<####, aktuell PC1
        Isecundn ++;                // Sekundenzähler hochtackern, max 9 Std
      }             // Ende if (Izeit_1 )
    
      if (tmrE0 > 2000)     // Grenzwert für Stillstand
    // ... usf
    Der *lls-teil zur Encoder-ISR:
    Code:
    // ============================================================================= =
    // ===  Nicht unterbrechbare ISR für EXT_INT0 auf Pin 4/PD2/mega328
    // Der Timer tmrE0 für Laufzeit des EXT_INT0 wird ausgelesen
    //      Der zugehörige Motor auf PD7/PB0 = re,li und PB1 Geschwind./PWM
     ISR(INT0_vect)                 // INT0 triggert auf RISING edge => 
     {                              //   => Wenn Aufruf, dann PORTD2 = high
         8d4:    1f 92           push    r1
         8d6:    0f 92           push    r0
         8d8:    0f b6           in    r0, 0x3f    ; 63
         8da:    0f 92           push    r0
         8dc:    11 24           eor    r1, r1
         8de:    8f 93           push    r24
         8e0:    9f 93           push    r25
    // - - - - - - - - - - - - - - - -
    //      Encoderticks Iencdrx nur hochzählen, IencBx rauf- od runterzählen
      Iz_diff0  = tmrE0;    // Abspeichern Zeit seit dem letzten ISR-Aufruf
         8e2:    80 91 2f 07     lds    r24, 0x072F
         8e6:    90 91 30 07     lds    r25, 0x0730
         8ea:    90 93 0f 07     sts    0x070F, r25
         8ee:    80 93 0e 07     sts    0x070E, r24
      tmrE0     =    0;     // Resetten ##>> IN der ISR ohne CLI/SEI möglich
         8f2:    10 92 30 07     sts    0x0730, r1
         8f6:    10 92 2f 07     sts    0x072F, r1
      Iencdr0 ++;           // Incrementiere Encodercounter, zählt NUR aufwärts
         8fa:    80 91 0a 06     lds    r24, 0x060A
         8fe:    90 91 0b 06     lds    r25, 0x060B
         902:    01 96           adiw    r24, 0x01    ; 1
         904:    90 93 0b 06     sts    0x060B, r25
         908:    80 93 0a 06     sts    0x060A, r24
      if (IsBitSet (PIND, 4)) IencB0++;     // Rad treibt vorwärts,  math. negativ
         90c:    4c 9b           sbis    0x09, 4    ; 9
         90e:    06 c0           rjmp    .+12         ; 0x91c <__stack+0x1d>
         910:    80 91 48 06     lds    r24, 0x0648
         914:    90 91 49 06     lds    r25, 0x0649
         918:    01 96           adiw    r24, 0x01    ; 1
         91a:    05 c0           rjmp    .+10         ; 0x926 <__stack+0x27>
      else                    IencB0--;     // Rad treibt rückwärts, math. positiv
         91c:    80 91 48 06     lds    r24, 0x0648
         920:    90 91 49 06     lds    r25, 0x0649
         924:    01 97           sbiw    r24, 0x01    ; 1
         926:    90 93 49 06     sts    0x0649, r25
         92a:    80 93 48 06     sts    0x0648, r24
     }      // Ende ISR(INT0_vect)
         92e:    9f 91           pop    r25
         930:    8f 91           pop    r24
         932:    0f 90           pop    r0
         934:    0f be           out    0x3f, r0    ; 63
         936:    0f 90           pop    r0
         938:    1f 90           pop    r1
         93a:    18 95           reti
    ... das sind schlappe vierzig Maschinenzyklen für einen Encoder.
    Ciao sagt der JoeamBerg

Ähnliche Themen

  1. Schrittmotoren + Arduino Motorshield
    Von horschl im Forum Suche bestimmtes Bauteil bzw. Empfehlung
    Antworten: 0
    Letzter Beitrag: 28.05.2014, 11:44
  2. Inkrementalgeber
    Von baensch im Forum Suche bestimmtes Bauteil bzw. Empfehlung
    Antworten: 2
    Letzter Beitrag: 16.07.2009, 16:37
  3. Inkrementalgeber
    Von bartolomeos im Forum Sensoren / Sensorik
    Antworten: 9
    Letzter Beitrag: 09.11.2005, 19:16
  4. inkrementalgeber
    Von curmet im Forum Sensoren / Sensorik
    Antworten: 8
    Letzter Beitrag: 17.06.2005, 21:11
  5. Inkrementalgeber
    Von demerzel im Forum Motoren
    Antworten: 2
    Letzter Beitrag: 25.06.2004, 20:53

Berechtigungen

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

12V Akku bauen