Der interrupt ist mehr oder weniger deterministisch. Auf jedenfall im vergleich zu einem 21Hz signal. Er kommt dann, wenn er getriggert wird. Spaetestens nachdem ein anderer laufender interrupt abgearbeitet worden ist, also etwas spaeter als gedacht. In deinem fall soltle das dann 2 identische speed werte liefern. Ist dein encoder signal deterministisch?

Mir faellt es sehr schwer zu glauben, dass ein 16MHz microcontroller nicht in der lage sein sollte ein quasi DC signal von 21Hz zu verarbeiten. Das sind von flanke zu flanke ca. 24ms, oder in anderen worten 384000 clock cycles, also eine halbe ewigkeit.
Wenn schon das kurzzeitige abschalten (µs bereich) der interrupts dein ergebnis bei so niedrigen zaehlraten significant veraendert... wie wahrscheinlich ist es, dass immer gerade dann, wenn der interrupt kaeme dieser abgeschaltet ist? Das will mir nicht einleuchten.
Wenn ein verwenden von micros() im vergleich zu millis() eine verbesserung bringt, dann kann das 2 gruende haben:
a) micros() ist schneller abgearbeitet als millis()
b) die zeitaufloesung von millis() is zu grob
zu a):
00000160 <millis>:
160: 8f b7 in r24, 0x3f ; 63
162: f8 94 cli
164: 20 91 04 01 lds r18, 0x0104
168: 30 91 05 01 lds r19, 0x0105
16c: 40 91 06 01 lds r20, 0x0106
170: 50 91 07 01 lds r21, 0x0107
174: 8f bf out 0x3f, r24 ; 63
176: b9 01 movw r22, r18
178: ca 01 movw r24, r20
17a: 08 95 ret
0000017c <micros>:
17c: 9f b7 in r25, 0x3f ; 63
17e: f8 94 cli
180: 20 91 00 01 lds r18, 0x0100
184: 30 91 01 01 lds r19, 0x0101
188: 40 91 02 01 lds r20, 0x0102
18c: 50 91 03 01 lds r21, 0x0103
190: 86 b5 in r24, 0x26 ; 38
192: a8 9b sbis 0x15, 0 ; 21
194: 06 c0 rjmp .+12 ; 0x1a2 <micros+0x26>
196: 8f 3f cpi r24, 0xFF ; 255
198: 21 f0 breq .+8 ; 0x1a2 <micros+0x26>
19a: 2f 5f subi r18, 0xFF ; 255
19c: 3f 4f sbci r19, 0xFF ; 255
19e: 4f 4f sbci r20, 0xFF ; 255
1a0: 5f 4f sbci r21, 0xFF ; 255
1a2: 9f bf out 0x3f, r25 ; 63
1a4: 54 2f mov r21, r20
1a6: 43 2f mov r20, r19
1a8: 32 2f mov r19, r18
1aa: 22 27 eor r18, r18
1ac: 28 0f add r18, r24
1ae: 31 1d adc r19, r1
1b0: 41 1d adc r20, r1
1b2: 51 1d adc r21, r1
1b4: 82 e0 ldi r24, 0x02 ; 2
1b6: 22 0f add r18, r18
1b8: 33 1f adc r19, r19
1ba: 44 1f adc r20, r20
1bc: 55 1f adc r21, r21
1be: 8a 95 dec r24
1c0: d1 f7 brne .-12 ; 0x1b6 <micros+0x3a>
1c2: b9 01 movw r22, r18
1c4: ca 01 movw r24, r20
1c6: 08 95 ret
Alleine das bloße abzaehlen der anzahl von opcodes macht klar, dass micros() im mittel nicht schneller abgearbeitet wird als millis(). Es bleibt also punkt b).
zu b):
ist die zeitaufloesung von millis() also ungenuegend, so heisst das doch auch, dass deine pulse viel viel schneller auftreten als nur mit 21Hz. Oder zumindest, dass der interrupt oefter feuert (dreckiges signal).
Bitte ueberpruefe:
a) ob dein encoder signal wirklich sauber ist (bounce free, keine oszillationen an den flanken)
b) Liefert der encoder kurze _pulse_ konstanter laenge pro tick, oder ein echtes rechtecksignal
c)
Bitte nutze einen I/O pin, setze diesen innerhalb und zu begin des interrupts und loesche ihn gegen ende wieder. Mit dem oszilloskop kann so _sehr leicht_ festgestellt werden, wie lange der interrupt benoetigt und v.a. wie oft er feuert im vergleich zum encoder signal. Das ist essenziell zu wissen, alles andere ist mehr oder weniger nur zeitverschwendung.
Screenshots vom osci waeren nett ;-)
d)
vielleicht lohnt es sich zu ueberpruefen, ob die serielle kommunikation stoerend ist. Ich habe mir bis jetzt nicht die muehe gemacht nachzusehen, ob das andere interrupts blockiert. Sollte das der fall sein, dann am besten von 9600 auf einen wesentlich hoeheren wert gehen.