Go Down

Topic: Tipp: Drehencoder per Timer-ISR auswerten - PullUP klein genug wählen (Read 477 times) previous topic - next topic

postmaster-ino

Hi

Vorweg: Das reine Mitzählen klappt.
Drehencoder, eBay (360/600 /r erhältlich)
Laut WWW sollte man mit der Versorgungsspannung nicht wirklich über 7V hinaus gehen, da dann der enthaltene 7805 wohl zu warm wird, kleiner 7V wären ungünstig, da dort der 7805 nicht arbeitet.
Das Signal zeigt aber keinerlei Änderung zwischen 18V und 3,5V (die 18 waren irrtümlich ... krumme Finger und so) - unter 3,5V versagt die interne Elektronik - die Ausgangs-Signale gehen Beide durch die PullUPs auf HIGH..

Der derzeitige Sketch entstammt Diesem hier:
Quelle:Re: Rotary Encoder, Jurs, #11
Auf dem Beispiel ist Alles rausgeflogen, was mit mehr als einem Encoder zu tun hat, sämtliche FORs, auch zählt meine ISR jetzt die absoluten Impulse, statt relativ.

Mein aktueller Encoder liefert 600 Perioden pro Umdrehung, macht 2400 Impulse.
Angestrebte Geschwindigkeit 1500r/min (Spindel Drehbank), sind 25 die Sekunde, macht 60kHz.

Lange Rede, kurzer Sinn:
Bei meinen Versuchen (die letzten drei Tage) hatte ich gerade bei höheren Drehzahlen immer wieder Fehler, also Sprünge in den Encoder-Mustern.
Die konnte ich heute ausmerzen - hatte mir die Signale am Oszi angeschaut - vll. sind die Signale ja nicht 90° versetzt, sondern nur 50°?? Dann hätte ich natürlich zwei Mal eine wesentlich kürzere Zeit zwischen den Impulsen, was die Fehl-Zählungen erklären würde. Die Lösung war aber viel primitiver - kleinerer PullUP (2k2, meine Brot-und-Butter-Widerstände, Rollenware) und der Hase rennt.
Die Impulse sind super sauber 90° auseinander.
Auch habe ich in der ISR D13 toggeln lassen ... bei angestrebten 125kHz messe ich 156kHz, das Signal ist aber sehr verwaschen - hier wollte ich eigentlich nur sichergehen, daß ich halbwegs richtig gerechnet habe und der Timer auch macht, was ich denke, daß Er macht - Er macht!

Momentane Tests per Akkuschrauber, Der - laut Aufdruck - ebenfalls 1500r/min im hohen Gang haben soll (1556 durch Arduino gemessen).
In der ISR werden nur die Encoder-Muster vorher<>jetzt verglichen, nur wenn ungleich, wird weiter geprüft.
- Beide werden zusammen kopiert/geschoben
- die 4 Fälle für + bzw. die 4 Fälle für - in switch abgefragt
- als default einen Error-Counter hochzählen

Mit kleineren PullUPs bleibt der Error-Count derzeit auf 0.
Maximal erreichte Geschwindigkeit 62250 Impulse/Sekunde (25,9r/Sek - 1556r/Min) - ohne Error.
Code: [Select]
//Quelle des Original: https://forum.arduino.cc/index.php?topic=318170.msg2202599#msg2202599

// rotary encoder demo by 'jurs' for Arduino Forum
// This is the code for the main "sketch"

#include "encoder.h"
#define BAUDRATE 115200L // serial baud rate

int32_t diff;   //Platz für die Differenz des Zählerwert binnen einer Sekunde
void setup() {
  Serial.begin(BAUDRATE);
  Serial.println();
  Serial.println("Good night and good luck!"); // print some Test-Message at beginning
  beginEncoders();
  pinMode(13, OUTPUT);
}

void printEncoders()
{ // print current count of each encoder to Serial
  Serial.print(stepsave);
  Serial.print('\t');
  Serial.print(error);
  Serial.print('\t');
  Serial.print(diff);
  Serial.println();
}

void loop() {
  if (updateEncoders()) printEncoders();
  static int32_t stepold = 0;     //Die aktuelle Geschwindigkeit (Steps pro Sekunde)
  static uint32_t oldmillis;
  if (millis() - oldmillis >= 1000) {
    oldmillis += 1000;
    diff = stepsave - stepold;
    stepold = stepsave;
  }
}

Die encoder.h :
Code: [Select]
// rotary encoder include file by 'jurs' for Arduino Forum
// This is the code for a new "Tab" within the sketch with Tab name "encoder.h"
#include <Arduino.h>

volatile boolean tic=false;   //wird auf TRUE gesetzt, wenn im Timer-ISR der Wert geändert wurde
volatile int32_t error;       //wird bei übersprungenen Mustern hochgezählt
volatile int32_t steps;       //ISR-Variable
int32_t stepsave;             //Variable für im Sketch

void startTimer2()  // start TIMER2 interrupts
{
  noInterrupts();
  // Timer 2 CTC mode
  /* Teiler CS22_CS21_CS20
     000 STOP
     001 :1   -> 16MHz
     010 :8   -> 2MHz
     011 :32  -> 500kHz
     100 :64  -> 250kHz
     101 :128 -> 125kHz
     110 :256 -> 62.5kHz
     111 :1024 -> 15.625kHz
  */
  TCCR2B = (1<<CS21) | (1<<CS20); //Teiler 32 - im Original wird WGM22 auch gesetzt
  TCCR2A = (1 << WGM21); //CTC    //WGM22 ist aber 'Reserved' ... ?? Geht auch Ohne ...
  //OCR2A = 1;  //alle 2 Counter -> ISR 250kHz
  //OCR2A = 2;    //T32, OCR2A=2, Verzählt sich trotz 166kHz Abtastrate (156kHz gemessen)
  //OCR2A = 5;  //alle 6 Counter -> ISR 83.3kHz
  //OCR2A = 6;  //alle 7 Counter -> ISR 72.4kHz
  //OCR2A = 7;  //alle 8 Counter -> ISR 62.5kHz
  //OCR2A = 9;  //alle 10 Counter -> ISR 50kHz
  //OCR2A = 19;  //alle 20 Counter -> ISR 25kHz
  OCR2A=2;
  TIMSK2 = (1 << OCIE2A); // enable Timer 2 interrupts
  interrupts();
}

void beginEncoders()
{ // active internal pullup resistors on each encoder pin and start timer2
    pinMode(2, INPUT);
    pinMode(3, INPUT);
  startTimer2();
}

boolean updateEncoders()
{ // read all the 'volatile' ISR variables and copy them into normal variables
  boolean changeState = false;
    if (tic){
      do{
        tic=false;
        stepsave=steps;
      }while(tic==true);    //wenn in der do-while die ISR zugeschlagen hat
      changeState = true;   //dann halt erneut auslesen
    }
  return changeState;
}

ISR(TIMER2_COMPA_vect)  // handling of TIMER2 interrupts
{
  static byte oldp=0;       //Merker des alten Zustand
  byte newp=(PIND>>2)&0x3;  //neuen Zustand einlesen - D2 und D3
  if (oldp!=newp){          //nur bei Änderung weiter Prüfen
    tic=true;               //Änderung nach Außen sichtbar machen
    oldp|=newp<<2;  //oldp als Temp-Variable missbrauchen
    switch (oldp){
      case 0b0100:    //von Muster  00 -> 01
      case 0b1101:    //            01 -> 11
      case 0b1011:    //            11 -> 10
      case 0b0010:steps++;break; // 10 -> 00
      case 0b0001:
      case 0b0111:
      case 0b1110:
      case 0b1000:steps--;break;
      default:error++;  //        wenn die Alle nicht gepasst haben - Problem
    }
    oldp=newp;  //neuen Wert übernehmen
  }
}

Vll kann ja Wer Was damit anfangen - frühe Alpha ;)

MfG
*Edit*
OCR2A=2 -> 166kHz, nicht wie zuvor im Kommentar stehend 125kHz (0-2 sind 3 Steps, somit bei Teiler 32 = 500kHz durch 3 -> 166kHz)

Doc_Arduino

Hallo,

ich würde mal sagen teste erstmal selbst bevor sowas postest.

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

DrDiettrich

Bei dieser Methode kommen irgendwann Artefakte aus der Differenz zwischen Encoder- und Abtastrate. Deshalb ist die Abtastung mit konstanter Zeit nur geeignet für langsame Signale, man könnte auch die Zeit zwischen zwei Flanken messen mit gleichem bzw. qualitativ besserem Ergebnis.

IMO ein weiteres Musterbeispiel für die falsche Verwendung von Interrupts :-]

combie

Quote
und der Timer auch macht, was ich denke, daß Er macht - Er macht!
Naja...
Deine Timer ISR Aufrufe kommen nicht auf den Punkt exakt.

Sie unterliegen einem Jitter.
Die Timer0 ISR und die Serial ISR verzögern (manchmal) den Aufruf deiner Timer ISR.

Tipp:
Sowohl der Arduino DUE, als auch die STM32 BluePill Boards besitzen Timer, welche einen Decoder Modus haben.
Sie zählen ohne jede ISR, handeln alles in Hardware ab.
Diese Decoder sind in der ARM Welt weit verbreitet.
Sie sind perfekt für schnelle Encoder geeignet.





Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Doc_Arduino

Hallo,

übrigens, die neuen ATmega der AVR0 Serie können so programmiert werden das sie Encodersignale in Hardware verarbeiten. Dazu gibts eine AppNote.

Zum obigen Code wollte ich noch ergänzen bzw. gestern zum Ausdruck bringen, dass er überhaupt nicht funktioniert. Mit meinem Handdrehencoder passiert nichts - absolut nichts. Viele Kommentare im Code sind zudem falsch.

Wenn die LED mit 125kHz blinken soll, so ist das möglich.


Code: [Select]

const byte pin = 28;  // Pin 28 Mega  

void setup(void) {
  
  pinMode(pin, OUTPUT);
 
  set_Timer2();  
}

void loop(void) {
  
}


// ****** Funktionen ******* //
    
void set_Timer2()         // CTC, Mode 2
{
  cli();                  // Interrupts ausschalten
  TCCR2B = 0;             // Reset Register  
  TCCR2A = 0;
  TIMSK2 = 0;
  TCNT2 = 0;                      
  OCR2B = 0;                
  OCR2A = 1;              // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
  TCCR2A = (1<<WGM21);    // set Mode
  TCCR2B = (1<<CS21)|(1<<CS20);  // Prescaler 32
  sei();              
}  


ISR(TIMER2_COMPA_vect)          // Timer 2 Interrupt
{  
  PINA = ( 1 << PA6 );      // Pin 28 Mega    
  // digitalWrite bremst bei dem Takt zu stark             
}


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Das hilft vielleicht auch:
https://www.mikrocontroller.net/articles/Drehgeber

Lässt sich leicht auf den Arduino übertragen

Doc_Arduino

Hallo,

der Artikel, der immer wieder gern verlinkt wird, kann ich nur empfehlen und die Bsp. durcharbeiten.
Darauf basiert auch meine Lib.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

postmaster-ino

Hi

Danke der Kritik - auf Mikrocontroller.net war ich, unter Anderem, auch.

@Doc
Hatte ja getestet - sonst wäre mir der Unterschied zwischen INPUT_PULLUP (klappte bis ca. 22kHz) und externem PullUP (bis jetzt >60kHz) nicht aufgefallen.
Wobei akut der Akkuschrauber schwächelt und nur noch auf 54kHz kommen will.
Alles ohne gezählte Fehler, also ohne übersprungene Muster.

@DrDiettrich
Da die Abtastrate um das Doppelte des erwarteten Signal beträgt, sollte jedes Signal sicher erkannt werden.
60kHz gewünscht <-> 125kHz Abtastrate - schaut zumindest nicht nur falsch aus.
Da Es sogar 166kHz sein sollten, stehe ich sogar noch besser da!
Wenn Du Deine Ausführungen ausführlicher ausführen würdest?

@Combie
Hatte ich mir schon gedacht, daß der Timer2 etwas weiter hinten in der Rangliste steht - aber nicht im Datenblatt nachgeschaut, welcher Vector Das nun wirklich war.
Ob dieser Encoder als 'schnell' bezeichnet werden darf - aber ok, zumindest hatte ich etwas zu Kämpfen, die 2400 Flanken dann doch noch unter zu bringen (hatte ja auch nur mit 600 gerechnet ... irgendwie).
Da ich die Auflösung (600 Perioden) nicht wirklich brauche, habe ich den Encoder in 360 erneut geordert.
Damit kann ich um Einiges langsamer Abfragen und habe dann mehr Zeit für die andere Seite - ein Motor soll sich ja auch noch proportional zum Encoder drehen, da sollten mir aber ganze Grad an der Spindel auch reichen.
Bis Der da ist, wird eh hiermit weiter gespielt, befürchte aber, daß ich kaum Zeit habe, die passenden Steps zu generieren - wird sich zeigen.

@Doc (2)
Die Ansteuerung des PIN-Register hatte ich damals in Assembler, allerdings auf einem ATtiny45, schon gemacht - hier wollte Diese mir nicht gelingen - wo ich gerade sehe - die Passage ist nicht mehr im Code drin - hatte Das per PORTD gemacht.
Sehe das gerade jetzt erst - die erwähnten 125kHz sollten 500:3=166kHz sein (CTC bei 2).
Von den vielen falschen Kommentaren sehe ich derzeit nicht so Viele - wo steht, was besser nicht So stehen sollte?
Davon ab: 'Funktioniert gar nicht' ist schon wenig - PullUPs vergessen?
Mein Encoder hier kann nur aktiv nach GND ziehen, daher fing ich mit INPUT_PULLUP an, was auch halbwegs klappte.
Auf dem Oszi dann schwer krumme Linien - kleinerer PullUP -> läuft.
Meine Hand-Drehencoder schalten ebenfalls nach GND durch.
Da ich externe PullUPs verbaut habe, habe ich die INPUT_PULLUP wieder in INPUT reduziert.

@Senerifly & Doc (3)
Die Seite kannte ich und war auch öfter dort zugegen.
Auch dachte ich, daß ich 'dicke schnell genug' über die Signale drüber husche - geplant doppelte Abtastrate, real sogar etwas mehr ... man muß auch Mal gewinnen können, wenn's mit dem Kopfrechnen nicht geklappt hat.
Trotzdem Danke für den Link, Der die Theorien zum Drehencoder schön zeigt.

MfG

*Edit*
'Funktioniert gar nicht' ergänzt

Doc_Arduino

Hallo,

ich hatte in der Headerdatei die Pinummern und in INPUT_PULLUP abgeändert. Kompilierte ohne Fehler und dann meinen Drehencoder betätigt. Es erschienen 2 Zeilen, mehr passierte nicht. Sonst keine weitere Ausgaben. Deswegen vermute ich das es auch mit dem Akkuschrauber nicht hinhaut.

166kHz statt 125kHz ist auch kein Problem, Formel stehen alle im Datenblatt, zubeachten gilt das jeder Mode eine etwas andere Formel hat. Ich hatte mir seinerzeit eine Exceltabelle erstellt, nur als Tipp. Ich gebe meine Zielfrequenz oder Zielcomparewert ein und erhalte die Timereinstellungen und restliche Werte als Info.
digitalWrite glückt hier natürlich nicht mehr wie schon vorhin kommentiert, da die ISR Periode nur 3µs beträgt.
Das bedeutet weiterhin das aller 48 Takte die ISR dran ist. Vielleicht allgemein zu viel des Guten?

Code: [Select]
// f Led 166kHz, Abweichung 666,667Hz
void set_Timer2()         // CTC, Mode 2
{
  cli();                  // Interrupts ausschalten
  TCCR2B = 0;             // Reset Register  
  TCCR2A = 0;
  TIMSK2 = 0;
  TCNT2 = 0;                      
  OCR2B = 0;                
  OCR2A = 5;              // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
  TCCR2A = (1<<WGM21);    // set Mode
  TCCR2B = (1<<CS21);     // Prescaler 8
  sei();              
}  
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

abgesehen vom Handrehencoderproblem, habe ich nochmal überlegt und bin der Meinung das es bei der Drehzahl und dem Encoder der 4 fache Impulse liefert nicht möglich ist. Man bekommt aller 16,667µs einen neuen Impuls. Davon benötigt man die dopppelte Abtastrate, also maximum aller 8,333µs.  >> 120,05kHz, die ISR ist aller 4µs, also aller 64 Takte dran. Ich glaube nicht das die Berechnungen inkl. ISR rein- und rausspringen mit 64 Takten erledigt ist. Ich denke hier ist zumindestens ein neuer Ansatz zur Pulserfassung notwendig.  ??

Zur Kontrolle müßtest du in die ISR und Encoderberechnungsfunktion ein Anfang-Ende Pintoggle einbauen und per Oszi / Datalogger anschauen ob da etwas verloren geht oder nicht.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

postmaster-ino

Hi

Da ich Teiler 32 nutze und OCR2A auf 5 sitzt, sind's 6*32 Takte, bis der nächste Interrupt dazwischen funkt - statt 48 Takte wären Das 192.

Warum Das bei Dir nicht läuft - kA.
Code: [Select]

21:35:32.520 ->
21:35:32.520 -> Good night and good luck!
21:35:32.520 -> 0 1 0
21:35:34.348 -> 1 1 0
....
23:01:28.013 -> 32060 1 -13
23:01:28.013 -> 32059 1 -13
23:01:28.060 -> 32058 1 -13
23:01:28.248 -> 32057 1 -13
23:01:28.341 -> 32056 1 -13
23:01:28.482 -> 32057 1 -13
23:01:28.529 -> 32058 1 -13
23:01:28.576 -> 32059 1 -13
23:01:28.623 -> 32058 1 -13
23:01:28.669 -> 32057 1 -13
23:01:28.716 -> 32056 1 -13
23:01:28.716 -> 32055 1 -13
23:01:28.763 -> 32054 1 -13
23:01:29.091 -> 32053 1 -9
23:01:29.185 -> 32054 1 -9
23:01:29.326 -> 32055 1 -9
...
23:05:39.732 -> -47202 1 -28935
23:05:39.779 -> -49876 1 -28935
23:05:39.826 -> -52459 1 -53182
23:05:39.919 -> -55184 1 -53182
23:05:39.966 -> -57798 1 -53182
23:05:40.013 -> -60802 1 -53182
23:05:40.060 -> -63405 1 -53182
23:05:40.107 -> -66466 1 -53182

Der erste Wert ist die aktuelle Step-Anzahl.
Der zweite Wert die Error-Anzahl - beim Reset stand der Encoder auf 1/1, was mit dem voreingestellten Alt-Wert 0/0 kein passendes Muster ergibt -> Error++.

MfG

*Edit*
Das Toggeln kann ich ja Mal einbauen ... ich sage Mal 'Moment' ...

Code: [Select]

ISR(TIMER2_COMPA_vect)  // handling of TIMER2 interrupts
{
  PINB=1<<PB5;
  static byte oldp = 0;     //Merker des alten Zustand
  byte newp = (PIND >> 2) & 0x3; //neuen Zustand einlesen - D2 und D3
  if (oldp != newp) {       //nur bei Änderung weiter Prüfen
    tic = true;             //Änderung nach Außen sichtbar machen
    oldp |= newp << 2; //oldp als Temp-Variable missbrauchen
    switch (oldp) {
      case 0b0100:    //von Muster  00 -> 01
      case 0b1101:    //            01 -> 11
      case 0b1011:    //            11 -> 10
      case 0b0010: steps++; break; // 10 -> 00
      case 0b0001:
      case 0b0111:
      case 0b1110:
      case 0b1000: steps--; break;
      default: error++; //        wenn die Alle nicht gepasst haben - Problem
    }
    oldp = newp; //neuen Wert übernehmen
  }
  PINB=1<<PB5;
}

*Edit* |= --> =, siehe combie @ #11
Der Graph auf dem Oszi bleibt davon aber eher unbeeindruckt - hatte's so auch erwartet.

combie

Quote
PINB|=1<<PB5;
ööm...
Wenn man in PINB rein schreibt will man Toggeln.
Sonst machts keinen Sinn.
Aber dann erst lesen und odern, das ist komisch.
Welcher Trick ist das?

Oder meinst du:
> PINB = 1<<PINB5;
Denn das macht Sinn
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

postmaster-ino

Hi

Wo Du Das sagst - somit bleiben wohl die anderen Pins am Port B nicht lange HIGH :/
Ok, umgeschustert in PINB=1<<PB5, der eingesparte Takt ist auf dem Oszi nicht zu sehen.
(Wohl aber auf den anderen Pins, wenn ich Diese benutzt hätte).

... daran hätte man dann auch länger suchen können ... danke Dir für's Korrigieren!

MfG

Doc_Arduino

Hallo,

Problem war warum es bei mir nicht funktionierte, dass noch der Einleseport in der ISR geändert werden musste.
Danach funktionierte es mit meinem Handdrehencoder.

Dein Oszibild. Interessant wäre die benötigte Rechenzeit der ISR.
Ist das die Dauer vom High- oder Lowpegel?

Thema Abtastung.
Compare 5? Ich dachte 2. Oder verhaust du nur die Werte. Weil im Eingangspost stimmt das im Text auch mit dem im Sketch nicht überein. Lange Rede kurzer Sinn. Deine Signale wären mit Prescaler 32 und Compare 5 unterabgetastet. Du erwartest max. 60kHz, müßte man mit mindestens 120kHz abtasten, mit Compare 5 sind aber nur 83,3kHz Abtastrate. Mit Compare 3 wäre man bei 125kHz Abtastrate. ISR aller 8µs.

Nochwas. Man kann doch die benötigten Takte im Asm Dump zählen.
Sind das immer die letzten Zahl nachdem Semikolon?
Wobei das auch nicht immer sein kann, weil Dezimal und Hex gemischt?
Was auch nicht sein kann das am Ende jeweils 255 Takte fürs Bit setzen vermehrt werden.
Kurzum, was sind die Taktangaben und was nicht?

Bsp. Timer 2 ISR
Code: [Select]

ISR(TIMER2_COMPA_vect)  // handling of TIMER2 interrupts
{
 732:    1f 92           push    r1
 734:    0f 92           push    r0
 736:    0f b6           in    r0, 0x3f    ; 63
 738:    0f 92           push    r0
 73a:    11 24           eor    r1, r1
 73c:    0b b6           in    r0, 0x3b    ; 59
 73e:    0f 92           push    r0
 740:    2f 93           push    r18
 742:    3f 93           push    r19
 744:    4f 93           push    r20
 746:    5f 93           push    r21
 748:    6f 93           push    r22
 74a:    7f 93           push    r23
 74c:    8f 93           push    r24
 74e:    9f 93           push    r25
 750:    ef 93           push    r30
 752:    ff 93           push    r31
  static byte oldp=0;       //Merker des alten Zustand
  byte newp=(PINC>>0)&0x3;  //neuen Zustand einlesen - D2 und D3
 754:    96 b1           in    r25, 0x06    ; 6
 756:    93 70           andi    r25, 0x03    ; 3
  if (oldp!=newp){          //nur bei Änderung weiter Prüfen
 758:    e0 91 30 02     lds    r30, 0x0230    ; 0x800230 <__data_end>
 75c:    e9 17           cp    r30, r25
 75e:    59 f1           breq    .+86         ; 0x7b6 <__vector_13+0x84>
    tic=true;               //Änderung nach Außen sichtbar machen
 760:    81 e0           ldi    r24, 0x01    ; 1
 762:    80 93 3a 02     sts    0x023A, r24    ; 0x80023a <tic>
    oldp|=newp<<2;  //oldp als Temp-Variable missbrauchen
 766:    84 e0           ldi    r24, 0x04    ; 4
 768:    98 9f           mul    r25, r24
 76a:    90 01           movw    r18, r0
 76c:    11 24           eor    r1, r1
 76e:    e2 2b           or    r30, r18
 770:    e0 93 30 02     sts    0x0230, r30    ; 0x800230 <__data_end>
    switch (oldp){
 774:    e1 50           subi    r30, 0x01    ; 1
 776:    ee 30           cpi    r30, 0x0E    ; 14
 778:    e0 f5           brcc    .+120        ; 0x7f2 <__vector_13+0xc0>
 77a:    0e 2e           mov    r0, r30
 77c:    00 0c           add    r0, r0
 77e:    ff 0b           sbc    r31, r31
 780:    88 27           eor    r24, r24
 782:    e6 53           subi    r30, 0x36    ; 54
 784:    fa 4f           sbci    r31, 0xFA    ; 250
 786:    8f 4f           sbci    r24, 0xFF    ; 255
 788:    fb c1           rjmp    .+1014       ; 0xb80 <__tablejump2__>
      case 0b0100:    //von Muster  00 -> 01
      case 0b1101:    //            01 -> 11
      case 0b1011:    //            11 -> 10
      case 0b0010:steps++;break; // 10 -> 00
 78a:    40 91 36 02     lds    r20, 0x0236    ; 0x800236 <steps>
 78e:    50 91 37 02     lds    r21, 0x0237    ; 0x800237 <steps+0x1>
 792:    60 91 38 02     lds    r22, 0x0238    ; 0x800238 <steps+0x2>
 796:    70 91 39 02     lds    r23, 0x0239    ; 0x800239 <steps+0x3>
 79a:    4f 5f           subi    r20, 0xFF    ; 255
 79c:    5f 4f           sbci    r21, 0xFF    ; 255
 79e:    6f 4f           sbci    r22, 0xFF    ; 255
 7a0:    7f 4f           sbci    r23, 0xFF    ; 255
      case 0b0001:
      case 0b0111:
      case 0b1110:
      case 0b1000:steps--;break;
 7a2:    40 93 36 02     sts    0x0236, r20    ; 0x800236 <steps>
 7a6:    50 93 37 02     sts    0x0237, r21    ; 0x800237 <steps+0x1>
 7aa:    60 93 38 02     sts    0x0238, r22    ; 0x800238 <steps+0x2>
 7ae:    70 93 39 02     sts    0x0239, r23    ; 0x800239 <steps+0x3>
      default:error++;  //        wenn die Alle nicht gepasst haben - Problem
    }
    oldp=newp;  //neuen Wert übernehmen
 7b2:    90 93 30 02     sts    0x0230, r25    ; 0x800230 <__data_end>
  }
 7b6:    ff 91           pop    r31
 7b8:    ef 91           pop    r30
 7ba:    9f 91           pop    r25
 7bc:    8f 91           pop    r24
 7be:    7f 91           pop    r23
 7c0:    6f 91           pop    r22
 7c2:    5f 91           pop    r21
 7c4:    4f 91           pop    r20
 7c6:    3f 91           pop    r19
 7c8:    2f 91           pop    r18
 7ca:    0f 90           pop    r0
 7cc:    0b be           out    0x3b, r0    ; 59
 7ce:    0f 90           pop    r0
 7d0:    0f be           out    0x3f, r0    ; 63
 7d2:    0f 90           pop    r0
 7d4:    1f 90           pop    r1
 7d6:    18 95           reti
      case 0b1000:steps--;break;
 7d8:    40 91 36 02     lds    r20, 0x0236    ; 0x800236 <steps>
 7dc:    50 91 37 02     lds    r21, 0x0237    ; 0x800237 <steps+0x1>
 7e0:    60 91 38 02     lds    r22, 0x0238    ; 0x800238 <steps+0x2>
 7e4:    70 91 39 02     lds    r23, 0x0239    ; 0x800239 <steps+0x3>
 7e8:    41 50           subi    r20, 0x01    ; 1
 7ea:    51 09           sbc    r21, r1
 7ec:    61 09           sbc    r22, r1
 7ee:    71 09           sbc    r23, r1
 7f0:    d8 cf           rjmp    .-80         ; 0x7a2 <__vector_13+0x70>
      default:error++;  //        wenn die Alle nicht gepasst haben - Problem
 7f2:    40 91 3b 02     lds    r20, 0x023B    ; 0x80023b <error>
 7f6:    50 91 3c 02     lds    r21, 0x023C    ; 0x80023c <error+0x1>
 7fa:    60 91 3d 02     lds    r22, 0x023D    ; 0x80023d <error+0x2>
 7fe:    70 91 3e 02     lds    r23, 0x023E    ; 0x80023e <error+0x3>
 802:    4f 5f           subi    r20, 0xFF    ; 255
 804:    5f 4f           sbci    r21, 0xFF    ; 255
 806:    6f 4f           sbci    r22, 0xFF    ; 255
 808:    7f 4f           sbci    r23, 0xFF    ; 255
 80a:    40 93 3b 02     sts    0x023B, r20    ; 0x80023b <error>
 80e:    50 93 3c 02     sts    0x023C, r21    ; 0x80023c <error+0x1>
 812:    60 93 3d 02     sts    0x023D, r22    ; 0x80023d <error+0x2>
 816:    70 93 3e 02     sts    0x023E, r23    ; 0x80023e <error+0x3>
 81a:    cb cf           rjmp    .-106        ; 0x7b2 <__vector_13+0x80>


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Quote
Sind das immer die letzten Zahl nachdem Semikolon?
0x3f    == 63
0x3b   == 59


Quote
Man kann doch die benötigten Takte im Asm Dump zählen.
Nur wenn man weiß, wie viel Takte jedes einzelne Statement benötigt.
Und das findest du in der Atmel Doku.





Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Go Up