Hallo Zusammen...
Ich benuzte für ein kleines Projekt den im 2ten Beitrag vorgestellten
Code um einen Drehgeber auszulesen... Nun habe ich die Frage, wie ich
die Zahl in enc_delta begrenzen kann? Ich will diese auf meinen PWM
Ausgang geben. die enc_delta variable soll nur von 0 bis 1000 zählen
können. Wenn ich das ganze mit einer if abfrage im Hauptprogramm (nicht
in der Interrupt Routine) mache...
1
if(enc_delta>=1000)
2
{
3
enc_delta=1000;
4
}
funktioniert es jedoch wenn ich...
1
if(enc_delta<=0)
2
{
3
enc_delta=0;
4
}
habe ich das Problem, dass meine Variable nie kleiner als 0 wird. Diese
geht danach wieder auf 65536 (16Bit Zahl) weil diese Zahl grösser als
1000 ist geht er mir in die erste if abfrage was kann ich dagegen tun?
mittels abspeichern der Zahl in einen OLD_Value hatte ich auch keine
erfolge, da ich ja den Timerinterrupt verwende kann es aber irgendwie
vorkommen, dass er mir einzelne punkte überspringt... von 1 gerade auf 3
und nicht auf 2...
Hoffe es kann mir jemand helfen... Chrislight
Ich denke, dass es am besten ist wenn du diese Abfrage auch in der ISR
machst. Dort ändert sich der Wert immer nur um +/- 1 und deswegen kannst
du auf x==1000+1 und x==0-1 abfragen.
Wenn du die Abfrage in der main machst, kann es sein, dass du auf 1000
stehst, um 2 erhöhst, diesen Wert (1002) für deine PWM verwendest und
anschließend erst die Abfrage (x>1000) und ggf. Korrektur erfolgt.
Oder du lässt die Abfrage in der main, "denkst dir eine Grenze" und
fragst auf diese ab, z.B. 65535-1000=64535; 64535/2=32267;
32267+1000=33267.
Dann die Abfrage ob
x>1000 && x<33267 => 1000
und
x>=33267 => 0
Wobei: x=enc_delta
Auf die letzte Weise kann allerdings der im 2. Absatz beschriebene Fall
eintreten.
Ey Super! Die oben erwähnte Antwort von Michael K. hat mir sehr
geholfen! So funktionietrt es Bestens und ich habe auch keine grösseren
Probleme, da ich die Variable enc_delta immer auf den höchswert (1000)
oder auf null setze bei der jeweiligen abfrage. Besten Dank Chrislight
Ich habs so gelöst bei meinem optischen Drehgeber:
(PEC11 von Bourns)
1
while(1)
2
{
3
if(((PINA&0x01)==0)&&((PINA&0x02)==0)){j=1;}
4
if(((PINA&0x01)==0)&&((PINA&0x02)!=0)){j=2;}
5
if(((PINA&0x01)!=0)&&((PINA&0x02)!=0)){j=3;}
6
if(((PINA&0x01)!=0)&&((PINA&0x02)==0)){j=0;}
7
8
if(j!=last)
9
{
10
if((j+1)%4==last)i--;
11
if((last+1)%4==j)i++;
12
last=j;
13
}
14
15
if(i>=5)
16
{
17
i=i-5;
18
//Drehrichtung 1
19
}
20
if(i<=-5)
21
{
22
i=i+5;
23
//Drehrichtung 2
24
}
25
}
/Edit:
Bevor jemand meckert... Natürlich kann man die Pin-Abfrage auch
kompakter gestalten, aber so denke ich sieht selbst ein Anfänger recht
gut was passiert :)
Hallo,
ich scheine irgendwie auf dem Schlauch zu stehen. Ich habe den Code aus
dem 2. Posting in die Timer0 Interrupt Routine eingefügt und verwende
folgenden Drehencoder
http://www3.alps.com/WebObjects/catalog.woa/E/HTML/Switch/Encoder/EC11/EC11E18244AU.html
Es scheint das der Encoder nur jede 2. Rastung zählt.
Jetzt die Frage ... ich habe das so verstanden, das in der variable
enc_delta der Wert +1 oder -1 steht richtig? Ich habe dann in meinem
Hauptprogramm einfach die Variable die ich hoch oder runterzählen will
mit der Variable enc_delta addiert (Y += enc_delta;). Doch leider
funktioniert das nicht. Es wird nicht gezählt. Habe ich da was falsch
verstanden?
Gruss
Nils
> Habe ich da was falsch verstanden?
Ja hast du. In enc_delta steht dein Wert (-128 ... 127). Du musst nichts
mehr rechnen, sondern kannst enc_delta so verwenden.
Lass doch mal das Beispiel-Programm so laufen wie es ist. Dann wird dir
auf Port B der aktuelle Wert ausgegeben. Und dieser sollte erniedrigt
oder erhöht werden, je nachdem in welche Richtung du drehst.
Vielen Dank, das war der entscheidende Hinweis. Jetzt zählt er auf und
ab. Das Problem ist jetzt noch das er mit jeder Rastung 2 hoch oder
runterzählt. Gibts da auch noch einen kleinen Tipp?
Ach so ... ein Problem war auch noch das ich die internen Pullups
benutzt hatte. Erst als ich extern Pullups angeschlossen hatte und die
internen deaktiviert habe funktionierte es. Den Common habe ich auf GND
gelegt. Funktioniert das bei euch mit den internen Pullups und dem Code
von Peter Danegger?
Es sollte egtl. auch mit den internen funktionieren. Wobei ich den Code
allerdings noch nicht auf einem AVR laufen hatte.
Bei meinen derzeitigen Encodern werden 2,2k-Pullups empfohlen und damit
klappt es. Vielleicht sind die internen zu hochohmig...
Hallo,
die manuelle Eingabe von größeren Werten ist mit groben Encodern ja
etwas mühselig. Hat sich da schonmal jemand Gedanken zu einer
"Beschleunigung" gemacht? Also z.B. dass die Schrittweite proportional
zur Zeit zwischen zwei Impulsen ist?
Ich habs mal mittels dem (im Drehgeber integrierten) Taster zwischen 1,
10 und 100 umschaltbar gemacht. Klappt ganz gut und lässt sich auch gut
bedienen, finde ich.
Ich hatte das mal ganz einfach mit einer Potenzierung gemacht...das
klappte sehr gut:
Beim langsamen Drehen konnte man die Werte genau einstellen, wenn man
schnell drehte, kam man schnell in die richtige Region...
Das war aber vom Programmierstil her eine ziemlich unschöne Lösung.
Hab da auch mal ne Frage:
enc_delta gibt mir Zahlen zwischen -128 ... 127 aus. Wenn ich mir diese
Variable über itoa(); umwandle und am LCD ausgebe, bekomme ich Werte von
0..127. Negative Zahlen kann die Funktion wahrscheinlich nicht - egal.
Ich bräuchte jetzt aber inkrementale Werte.
Habs zum Testen so versucht
unsigned char Zaehler;
Zaehler = 100;
for(;;)
{
cli();
Zaehler = Zaehler + enc_delta/2;
enc_delta = 0;
sei();
Zaehler ausgeben();
}
Problem: Beim Hochzaehler wird manchmal eine Rasterung ausgelassen und
beim Runterzaehler werden Werte um ca. 128 Werte nach unten gesprungen.
Der Compiler kann doch mit negativen Zahlen umgehen...
Ich befürchte, dass ich einen ganz dummen Fehler eingebaut habe.
Kann mir jemand weiter helfen?
@ Igor Metwet (bastel-wastel)
>Variable über itoa(); umwandle und am LCD ausgebe, bekomme ich Werte von>0..127. Negative Zahlen kann die Funktion wahrscheinlich nicht - egal.
Doch, eigentlich schon, heisst ja I (wie Integer) to ASCII.
>for(;;)>{>cli();>Zaehler = Zaehler + enc_delta/2;
Kein gute Idee, damit werden Pulse verschluckt
>enc_delta = 0;>sei();>Zaehler ausgeben();>}
Besser so.
1
uint16_t;Zaehler=100
2
3
for(;;)
4
{
5
cli();
6
Zaehler=Zaehler+enc_delta;
7
enc_delta=0;
8
sei();
9
ausgeben(Zaehler/2);
10
}
>beim Runterzaehler werden Werte um ca. 128 Werte nach unten gesprungen.>Der Compiler kann doch mit negativen Zahlen umgehen...
Ja, aber möglicherweise hast du Variablen falsch deklariert. Poste
VOLLSTÄNDIGEN Quelltext als ANHANG.
MfG
Falk
> Kein gute Idee, damit werden Pulse verschluckt
Danke! Jetzt kann ich hoch- und runterzählen ;-)
>>Variable über itoa(); umwandle und am LCD ausgebe, bekomme ich Werte von>>0..127. Negative Zahlen kann die Funktion wahrscheinlich nicht - egal.>> Doch, eigentlich schon, heisst ja I (wie Integer) to ASCII.
Wenn ich runterdrehe bis auf null und dann noch einen Puls Richtung
negative gebe, werden am Display "127" ausgegeben.
Ich habe aber allerdings die Variable "Zaehler" als char und nichts als
int deklariert. Da wären wir schon beim nächsten Effekt: Wird "Zaehler"
als int deklariert, dann zählt er hoch aber anstatt runter zu zählen,
zählt er pro Schritt 127 oder 255 hoch.
while (1){
cli();
encoder += enc_delta;
enc_delta = 0;
sei();
uint8_t s[3];
sprintf (s, "encoder: %3d", encoder);
vfd_cstring(2,s);
}
Hi!
Ich benutze auch den Drehgeber-Code von Peter Dannegger ( Code ganz
oben, die zweite!)
wie in dem letzten Beispiel wird auch die enc_delta benutzt um den
zähler ("uint8_t encoder = 0;") hoch bzw. runter zu zählen.
leider springt der wert aber nur zw. 0 und 255 bei linksdrehung und
zwischen 0 und 1 bei rechtsdrehung.
ich habe mir nun schon einige beispiele hier angesehen und beiträge
gelesen, stehe aber leider auf dem schlauch. kann mir jemand helfen bzw.
einen tip geben?? (ps. ich benutze einen drehgeber OHNE rastung)
Danke, Christoph
-> das gibt nur das enc_delta auf die LED's aus (angenommen die sitzen
hier wie beim STK500 an Port B)
enc_delta sollte eigentlich die Anzahl an schritten enthalten die der
Interrupt vom Drehgeber eingelesen hat. (Sehe ich doch richtig?!)
Sieh doch mal weiter oben, da steht eigentlich alles was man braucht.
mein Problem besteht übrigens noch immer...
siehe Beitrag "Problem mit Drehgeber"
> mein Problem besteht übrigens noch immer...> siehe Beitrag "Problem mit Drehgeber"
Richtig angeschlossen ist alles? Bleibt das Problem wenn du enc_delta
auf einen Port ausgibst?
So verkehrt sieht das nicht aus - die Werte würden passen. Falsch ist
halt dass es nur 1 Schritt tut...
Micha wrote:
> Richtig angeschlossen ist alles?
Ja. siehe auch im anderen Forum, habe den Beitrag mal da rein gestellt,
gehört ja hier eig. nicht hin!
>Bleibt das Problem wenn du enc_delta auf einen Port ausgibst?
hm, wie genau meinst du das ?
> So verkehrt sieht das nicht aus - die Werte würden passen. Falsch ist> halt dass es nur 1 Schritt tut...
eben. denke ich bin ganz nah dran (oder meilenweit entfernt...)
habe grade nochwas interessantes festgestellt: wenn ich GANZ schnell
drehe (so schnell wie normalerweise niemand an dem ding drehen würde)
dann kommen auch vernünftige schritte raus. nur halt zu schnell. ist mir
irgendwie rätselhaft...
naja, ich warte noch ne weile, vielleicht kann mir jemand den
entscheidenden Tip geben. ansonsten besorg ich mir (leider) nen neuen
Geber...
> hm, wie genau meinst du das ?
Naja du schreibst deine Werte jetzt ja auf ein Display, oder? Ich meine
du sollst mal enc_delta direkt auf einen Port ausgeben.
Und poste wenn möglich mal deinen gesamten Source-Code.
Ich habe die Drehencoder Funktionen benutzt die hier beschrieben sind:
http://www.mikrocontroller.net/articles/Drehgeber
Nachdem ich ewig rumgemacht habe und nichts funktioniert hat, aber
eigentlich funktionieren hätte sollen hab ich festgestellt dass die
enc_delta außerhalb der ISR nicht vorhanden ist, obwohl es eine globale
Variable ist.
Bin leider nicht sehr erfahren mit C und µC, hatte aber was von volatile
im Hinterkopf. Nachdem ich die Variable volatil deklariert hab hat alles
funktioniert.
Jetzt frag ich mich: Was ist beim Author anders dass es bei ihm ohne
volatile funktioniert und bei mir nicht? So wie ich das verstanden habe
muss man als volatile deklarieren wenn eine Variable nicht vom
angetastet werden darf weil sie z.B. von Ports oder ISRs verändert
werden kann, was ja bei dem Code der Fall ist.
Ja verlinkt ist dieser Thread, aber hier kann ich keine Infos finden zu
den Funktionen von dem Artikel.
Und wo ich schon dabei bin: Hat jemand eine Lösung wie man verhindern
kann dass das erste mal Drehen nicht funktioniert? Beim 4-fach Schalter
sollte das doch möglich sein eine eindeutige Aussage zu treffen in
welche Richtung es geht weil man ja auch ohne bekannte Vorbedingung
davon ausgehen kann dass die Vorbedingung so aussieht dass bei beiden
Phasen eine Null war. Ich denke das ist vielleicht auch der Grund warum
es solche Schalter überhaupt gibt.
Stephan S. wrote:
> Jetzt frag ich mich: Was ist beim Author anders dass es bei ihm ohne> volatile funktioniert und bei mir nicht?
Ja, das sind so die kleinen Gemeinheiten des GCC.
Er will unbedingt auch Funktionen inlinen, die nicht static sind und
dadurch ergeben sich unschöne Seiteneffekte:
Einer Funktion, die eine Variable nur einmal benötigt, ist es egal, ob
sie volatile ist oder nicht, sie muß sie einlesen. Volatile und der
damit verbundene größere Code ist dann unnötig.
Wird nun allerdings diese Funktion im gleichen Modul aufgerufen, kann es
sein, daß der Compiler sie inlined und damit optimiert er sie weg, wenn
die Variable nicht volatile ist.
Hier im Listing sieht man schön, daß die Funktion komplett fehlt:
1
int8_tencode_read1(void)
2
{
3
int8_tval;
4
5
cli();
6
118:f894cli
7
val=enc_delta;
8
enc_delta=0;
9
sei();
10
11a:7894sei
Diese unschöne Disoptimierung kann man aber abschalten mit folgender
Compileroption:
-fno-inline-small-functions
Peter
Wow, das ist mal echt eine gute Antwort... Wenn ich das aber nicht
wüsste und die Variable doch als volatile deklariere, handle ich mir
damit irgendwelche nennenswerten Nachteile ein?
Und was ist mit dem Problem dass der erste Schritt beim Drehen nicht
richtig erkannt wird?
> Wenn ich das aber nicht wüsste und die Variable doch als volatile> deklariere, handle ich mir damit irgendwelche nennenswerten Nachteile ein?
Würde mich auch interessieren.
> Und was ist mit dem Problem dass der erste Schritt beim Drehen nicht> richtig erkannt wird?
Ich habe das so gelöst:
1
staticcharenc_last=0;
2
3
SIGNAL(SIG_OVERFLOW0)
4
{
5
chari=0;
6
7
if...(sieheoben,2.Beitrag)
8
}
9
10
voidinit_rot_enc(void)
11
{
12
if(PHASE_A)
13
enc_last=1;
14
15
if(PHASE_B)
16
enc_last^=3;
17
}
Während der Initialisierung einmal init_rot_enc aufrufen und es sollte
funktionieren.
Michael K. wrote:
> @ Peter> Hat es einen bestimmten Grund dass du> ...= 3; und ...= 1; getauscht hast?
Ja, hat es.
Der AVR-GCC erzeugt äußerst umständlichen Code, wenn ein Bit abhängig
von einem anderen gesetzt wird.
Er expandiert erstmal zu 16Bit und schiebt dann entsprechend oft bis an
die richtige Bitposition.
Peter
Hallo,
bin Quereinsteiger mit meinem optischen encoder GP1A038 von Sharp.
Ich beziehe mich auf den Code der unten noch einmal kurz aufgeführt ist:
An PortD,3 schließe ich Kanal A an und an PortD,4 Kanal B, oder? Ich
verstehe nicht diese 4 ".set directiven". Sind die Werte 4,3 und 2 die
Binärwerte, die von Kanal A und B generiert werden? uND WAS IST DER
bUTTONß
Bitte mal jemand um eine Hilfestellung. Ich werfe sehr wahrscheinlich
noch etwas durcheinander.
Gruß
Udo
Autor: avusgalaxy (Gast)
Datum: 02.02.2005 20:33
An PORT D,0 und PORT D, eins kommt jeweils eine Led.
Ab PORT D... 4 und 3 den Drehgeber.. Ah ja, so solls ausehen:
.include "2313def.inc"
.set DIPGPin=PinB ;Port mit Drehimpulsgeber
.set DIPGChA=4 ;Pin mit Channel A
.set DIPGChB=3 ;Pin mit Channel B
.set DIPGBT=2 ;Pin mit Button
.def DIPGAlt=r4 ;Vorriger Zustand von Channel A
.def DIPG=r5 ;Drehimpulsgeber-Aktion. Nach Abfrage löschen
.def ButtonAlt=r6 ;Vorriger Zustand des Buttons
Hallo!
Ich möchte gerne einen Drehgeber mit einem Atmega 8 auswerten und auf
eine LED Zeile ausgeben.
Leider kann ich peter dannegger "C" Code nicht nachvollziehen. Gibt es
diesen Code auch in Assembler und somit auch für mich nachvollziebar?
Danke für eure Hilfe Otto.
Steffen H schrieb:
> Ich hab die hier noch. Läuft auf einen ATtiny2313.
Ooch nöö, das ist ja ein Monstercode.
In Assembler kann man Register für Interrupts reservieren bzw. auch
Variablen in Registern halten. Spart ne Menge Code.
Hier mal mein Code in Assembler (enc_delta = 16-bittig):
1
.include "tn261def.inc"
2
3
.def save_SREG = r14 ; for general interrupt usage
Hallo Peter!
Ich habe mal eine Lösung für das vieldiskutierte Thema Dein
Peda-Drehgeber-Code aus dem Wiki (
http://www.mikrocontroller.net/articles/Drehgeber ) und der Pollin
Drehencoder (Panasonic) ausgetüftelt.
Bekanntlich läuft der Pollin Encoder asymmetrisch. Nur Signal A ist bei
jeder Raste stabil. Signal B kann in jeder zweiten Raste zwei Zustände
einnehmen. (siehe Bild)
(1) Da bei dem Pollin "two step encoder" der Ausgabewert halbiert wird,
muss bei der Initialisierung von enc_delta berücksichtigt werden, dass
die instabilen Zwischenstufen bei (2*n) und (2*n+1) liegen, damit beim
rechts shiften das letzte Bit keinen Übertrag erzeugt und das Ergebnis
flattert.
(2) Falls mit internen Pullups gearbeitet wird, muss nach der
Portinitialisierung und dem Einlesen der Port-Pegel in der Funktion
encode_init() eine kleine Pause eingelegt werden, damit ggf. offene
Leitungen auf High gezogen werden (Leitungskapazitäten)
(3) Der Pollin Encoder dreht gegenüber dem PeDa-Code falsch herum. Ich
habe die Anschlüsse von A und B vertauscht.
Das ergibt dann folgende minimale Codeanpassung und der Pollin Drehgeber
arbeitet absolut bullet proof.
1
voidencode_init(void)
2
{
3
int8_tnew;
4
_delay_ms(1);//Verzögerung nach Initial. interner Pullups erforderlich
5
new=0;
6
if(PHASE_A)
7
new=3;
8
if(PHASE_B)
9
new^=1;// convert gray to binary
10
last=new;// power on state
11
12
//enc_delta = 0;
13
enc_delta=(new&1?0:1);//Pollin Encoder-Zählwerk auf stabile Startposition 0/1 setzen
Hallo,
hat jemand von euch sein Programm bei einem Motor mit ca. 1500 U/min
oder auch mehr zum laufen bekommen???
Habe erst Peters genommen und danach eins mit Interrupt
Flankenauswertung geschrieben, klappen jedoch beide bei dieser Drehzahl
nicht :-(
Ich wäre für Programmbeispiele sehr dankbar.
Gruß Klaus
Hallo Klaus,
es sind doch bei 1500 U/min nur 25 U/sec.
Da würde ich mit 250 Interrupts anfangen.
Welche Art Geber hast Du angeschlossen?
Möglich, dass es bei Gebern mit normalen Kontakten zu Schwierigkeiten
kommt.
Willst Du damit eine Maschine positionieren?
Gruß Thomas
thomas55 schrieb:> Hallo Klaus,>> es sind doch bei 1500 U/min nur 25 U/sec.>> Da würde ich mit 250 Interrupts anfangen.>> Welche Art Geber hast Du angeschlossen?> Möglich, dass es bei Gebern mit normalen Kontakten zu Schwierigkeiten> kommt.>> Willst Du damit eine Maschine positionieren?>> Gruß Thomas
??? Wirklich??
Wie viele Impulse / Schritte gibt der Geber denn pro Umdrehung? 16?
Dann sind es 4000 pro Sekunde, ein ordentliches Oversampling von 10
eribt schon 40000 Timeraufrufe pro Sekunde oder ein Timerinterrupt alle
25 mikrosekunden. Das ist sportlich....
Bernhard M. schrieb:> Wie viele Impulse / Schritte gibt der Geber denn pro Umdrehung? 16?> Dann sind es 4000 pro Sekunde, ein ordentliches Oversampling von 10> eribt schon 40000 Timeraufrufe pro Sekunde oder ein Timerinterrupt alle> 25 mikrosekunden. Das ist sportlich....
Ob da ein mechanischer Encoder überhaupt mitmacht?
Bei hohen Impulsraten würde ich die Zählung in nen extra ATtiny oder
CPLD machen und den per SPI oder I2C vom Master auslesen.
Peter
> Wie viele Impulse / Schritte gibt der Geber denn pro Umdrehung? 16?> Dann sind es 4000 pro Sekunde, ein ordentliches Oversampling von 10> eribt schon 40000 Timeraufrufe pro Sekunde oder ein Timerinterrupt alle> 25 mikrosekunden. Das ist sportlich....
ich habe das mit einem Arduino und 20usec Timerrate brauchbar
hingekriegt, ohne Assembler, und optional mit Peter's Entprellung der
A/B/Indexsignale ; da bleibt noch Luft für serielle I/O und einen
einfachen Kommandointerpreter
siehe
http://mah.priv.at/cgi-bin/viewvc.cgi/arduino-rotary/rotary-v6.pde?revision=1.1&root=CVS&sortby=date&view=markup
- das war ein Debug-Vehikel von mir und ist daher kein als solches
brauchbares Projekt
hatte folgendes Problem: CNC-Fräse mit EMC2; selbstgebauter Drehgeber
mit 360 Impulsen/Umdrehung und Indexpuls auf einer Spindel mit bis zu
5000 U/min zu erfassen und so runterzuteilen, so dass EMC2 mit einem
Parallelport-Input "mitkommt"
habe das schlussendlich aber mit einer FPGA-basierten Lösung gemacht
(Mesatech 5i20) und einem Heidenhain-Drehgeber mit 3600 Pulse/U; Grund
war meine mangelhafte mechanische Präzision beim Drehgeber, und
Störungen des Signals - manche Sachen kauft man besser und ein
Drehstromumrichter müllt ganz schön
falls jemand dazu Anregungen braucht - der VHDL-Code und EMC2 selbst
sind Open Source
-Michael
Hallo zusammen,
ich habe gerade ihre Kommentare alle gelesen.Ich bion ganz neu hier.Ich
mach gerade meine Technikerarbeit und ich soll auch einen Encoder (
inkremental)von der Firma Wachendorff verwenden.kann ich dafür auch den
LS7366 Decoder nehmen? Und woher weiß ich welches Modell ich nehmen
sollte,bezüglich der Anzahl der Impulse des Drehgebers????Ich soll
nämlich die geschwindigkeit ermitteln eines Förderbands.Auch bei
Geschwindigkeitänderungen. damit ich immer die perfekte position für ein
Bauteil berechnen kann, um ein Foto mit ner Camera auszulösen.Die
Position des Bauteils darf maximal 1mm +/- unter der Camera vom
optimalen Punkt versetzt sein.Wisst ihr was ich meine????
Ich würde mich über eine Antwort sehr freuen.
Mfg Maurice
ein sogenannter triggersensor ist selbstverständlich vorhanden dieser
kann aber aufgrund von baulichen gegebenheiten nicht direkt an der
kamera positioniert werden desweiteren ist die geschwindigkeit des
förderbandes nicht immer 100 prozent konstant.
Ist denn das Förderband an einer Steuerung angeschlossen, wenn ja kann
man den Encoder mit der verbinden. Je langsamer das Band läuft desto
mehr Impulse müssen es sein. D.h. läuft das Band mit einer sehr hohen
Drehzahl, brauchst du ja nicht soviele Impulse. Wie schnell läuft denn
das Band so im Minimum und Maximum?
heyhey,
hier mal mein Mockup, was auf der 2. Version von oben aufbaut. Ich
verwende externe Interrupts, um die Auslastung so gering wie möglich zu
halten. Der hohen Sensitivität was das bouncing angeht begegne ich mit
einem kleinen Kniff: Das Bouniving ist ja im Prizp nichts anderes als
das Hin- und Herpendeln zwischen zwei Zahlen. Wenn man jetzt nur
weiterzählen lässt, wenn der aktuelle Schritt in die selbe Richtung
gegangen ist, wie der vorherige, wir das Pendeln quasi ausgeblendet. Das
ganze funktioniert, weil der erste Kontakt mit der neuen Stufe eines
Schrittes in die selbe Richtung geht wie der letzte beim Bouncing. Die
Richtung des vorherigen Schrittes wird durch die Variable Rtg_pos
angegeben.
Beim Testen läufts bei mir in der Praxis sehr stabil, bin gespannt auf
eure Meinungen.
VG, Dawn
@ Dawn (Gast)
>Beim Testen läufts bei mir in der Praxis sehr stabil, bin gespannt auf>eure Meinungen.
Wirklich? OK!
Du bist ebenso auf dem Holzweg wie Tausende vor dir. Ein funktionierndes
Einzelexemplar ist kein Beweis. Das könnte bestenfalls ein Stresstest
bringen. Wird er aber nicht. Warum? Siehe Artikel Drehgeber.
MfG
Falk
P S Kein "Aber . . ."
...das schöne an so einem Forum ist doch, dass man abers bringen kann so
viel wie man möchte :)
Wer bin ich denn, dass ich hier einen Beweis erbringen möchte, ich sage
blos,dass das ganze für interupts sehr stabil läuft. Für meine
Anwendung, wo die Drehgeber nur selten verwendet werden ist pollen
ziemlich überzogen. Einer Überlastung beuge ich durch Ausschalten der
Interruots während der Routine vor. Zudem, was tun, wenn die Timer
anderweitig gebraucht werden?
Hi,
ich habe im Rahmen eines Projekts in der Uni die Aufgabe mit Hilfe eines
Heidenhain Inkrementaldrehgebers und einem ATmega2561 den Drehwinkel
bzw. die Winkelgeschwindigkeit eines Motors zu messen. Der Motor läuft
mit maximal 2000 U/min und der Drehgeber hat 3000 Striche, das wäre also
eine maximale Signalfrequenz von 100 KHz. Zu welcher Methode würdet ihr
mir da raten? Eigentlich wollte ich das mit den externen Interrupts
machen, aber ich habe jetzt hier öfter gelesen, dass es mit
Timerinterrupts sicherer ist. Kommt der Mikrocontroller überhaupt mit
dieser hohen Frequenz klar?
Vielen Dank!
Hallo BMJ!
Du musst einfach die Eingänge schnell genug abfragen. Um mit einem AVR
100kHz noch sicher handeln zu können sollte die entsprechende Routine
aber in Assembler geschrieben werden und beim Aufruf aus einem Timer
möglichst wenig auf dem Stack zwischengelagert werden.
Mit freundlichen Grüßen
Thorsten Ostermann
ATmega2561 klingt so, als ob dieser Bolide noch vieles andere machen
soll.
Daher würde ich nen extra ATtiny25 nehmen und per SPI oder I2C auslesen.
Es gibt zwar noch alte Encoder-ICs, aber die sind exorbitant teuer
(Museumszuschlag).
Peter
Hallo,
danke schon mal für die Antworten. Also ich möchte eigentlich keine
zusätzlichen IC's benutzen. Ich habe von der Uni diesen fertigen
Sensorknoten mit dem ATmega2561 bekommen und der muss dann auch nichts
anderes mehr machen als die Daten aufzunehmen und auf dem PC in LabView
darzustellen.
Wie groß müsste den die Abtastfrequenz sein, wenn ich das mit
Timerinterrupts mache? (Die maximale Signalfrequenz sind doch "nur" 75
kHz, da der Motor mit max 1500 U/min läuft) Der ATmega läuft mit etwas
weniger als 8 MHz, ich habe da etwas bedenken, dass ich nicht mehr genug
Rechenzyklen zur Verfügung habe, weil ich auch nur im Notfall auf
Assembler zurückgreifen möchte. Der Drehgeber hat außerdem auch ein
Referenzsignal bei jeder Umdrehung. Vielleicht würde es ausreichen, wenn
ich bei jeder vollen Umdrehung eine Korrektur durchführe (Zähler auf
Null setzen) und es doch mit den externen Interrupts mache. Wenn bei
3000 Strichen bei einer Umdrehung ein Paar nicht erkannt werden, wäre
das nicht so schlimm denke ich. Was meint ihr?
Viele Grüße!
BMJ
peter dannegger schrieb:> Bei einer Änderung über einen Schritt, ergeben sich je nach> Drehrichtung folgende Werte (in Klammern der 2-Bit Wert als> Dezimalzahl):>> Vorwärts:> 00 - 11 = 01 (1)> 01 - 00 = 01 (1)> 10 - 01 = 01 (1)> 11 - 10 = 01 (1)>> Rückwärts:> 00 - 01 = 11 (3)> 01 - 10 = 11 (3)> 10 - 11 = 11 (3)
Hallo, ich verstehe nicht, wie diese Tabelle zu Stande kommt. Kann mir
das einer bitte erklären?
LG
Die Tabelle ist meiner Meinung nach falsch. Encoder geben einen Graycode
aus, d.h. es ändert sich pro Schritt immer nur eine der beiden
Leitungen:
00 -> 01
01 -> 11
11 -> 10
10 -> 00
In Pfeilrichtung wäre dann vorwärts, gegen die Pfeilrichtung rückwärts.
Bei den anderen 8 möglichen Zustandsänderungen hätten sich beide Signale
geändert, was auf einen Fehler hindeutet (Zustandswechsel verpasst da
Encoder zu schnell dreht oder Auswertung zu langsam ist).
Mit freundlichen Grüßen
Thorsten Ostermann
Hallo,
ich bin auch relativ neu auf diesem Gebiet und soll mithilfe eines
magnetischen Drehgebers einen Schrittmotor regeln.
Soweit habe ich mich in das Programm von Herrn Dannegger eingelesen und
vieles verstanden ;)
Was ich z.B. nicht verstehe ist die Diskussion um die Rastpunkte. Blöd
gesagt was ist das?
Mein magnetischer Encoder bietet eine Auflösung von 1024
Impulsen/Umdrehung und arbeitet eben mit den Kanälen A & B (& Z, aber
das scheint ja egal zu sein). Das dieser in irgendeiner Einstellung
"spürbar" einrastet kann ich nicht bestätigten....
Vielen Dank schon einmal!
Frank
Hallo Frank,
die 'Rastpunkte' sind für die mechanischen Drehgeber. Die haben auch nur
8-32 Flanken. Für magnetische Drehgeber spielt das Ganze keine Rolle.
Und bei 1024 Pulsen wird wohl auch niemand von Hand an der Achse drehen
:-)
Gruß
Ralf
Ach cool, danke Ralf für die schnelle Antwort!
Ich kann also blöd gesagt, einfach das (erste) Programm von Herrn
Dannegger verwenden (http://www.mikrocontroller.net/articles/Drehgeber)?
Denn bei meinen bisherigen Versuch (lasse mir die Gesamtzahl an
Schritten an einem angeschlossenen LCD anzeigen) habe ich folgende 2
Probleme:
1. Ich brauch für die bisher manuelle Betätigung des Drehgebers (--> ca.
2 Umdrehungen/s :D ) schon eine Auslesefrequenz von 100kHz was ja schon
enorm ist
2.Ich denke es ist ein Variablenspeicherproblem: Sobald ich a) einen
Overflow habe (Also bei ca. 32k Schritten) oder b) erst in die eine
Richtung drehe (z.B. bis 11000) und dann in die andere bis es <10000
Schritte sind, bleibt die letzte Ziffer "einfach" stehen, also z.B.
99994 statt 9999... und ab dann springen die Schritte auf dem LCD
absolut zufällig....
Erneut, vielen Dank schon einmal :)
Frank
Hallo,
bei der Pulsfrequenz die dein Drehgeber liefert wirst Du wahrscheinlich
nicht glücklich mit einer Software Lösung.
Kommt auf ein MC System an ob der das schafft.
Da wirst Du mit spez. IC's oder nem CPLD arbeiten müssen.
Von den spez. IC's fällt mir aber grade nicht mehr die Bezeichnung ein.
gruß,
Bjoern
>2.Ich denke es ist ein Variablenspeicherproblem: Sobald ich a) einen>Overflow habe (Also bei ca. 32k Schritten) oder b) erst in die eine>Richtung drehe (z.B. bis 11000) und dann in die andere bis es <10000>Schritte sind, bleibt die letzte Ziffer "einfach" stehen, also z.B.>99994 statt 9999... und ab dann springen die Schritte auf dem LCD>absolut zufällig....
Versuch mal den Datentyp zu erweitern, z.b. auf int32_t.
Gruß Jonas
Frank schrieb:> 1. Ich brauch für die bisher manuelle Betätigung des Drehgebers (--> ca.> 2 Umdrehungen/s :D ) schon eine Auslesefrequenz von 100kHz was ja schon> enorm ist
Bei 2 Umdrehungen/s reichen 5kHz.
Frank schrieb:> 2.Ich denke es ist ein Variablenspeicherproblem: Sobald ich a) einen> Overflow habe (Also bei ca. 32k Schritten) oder b) erst in die eine> Richtung drehe (z.B. bis 11000) und dann in die andere bis es <10000> Schritte sind, bleibt die letzte Ziffer "einfach" stehen, also z.B.> 99994 statt 9999... und ab dann springen die Schritte auf dem LCD> absolut zufällig....
Nö, ein Darstellungsproblem. Vermutlich erweiterst Du nicht mit
Leerzeichen und alte Ziffern bleiben bei kürzeren Zahlen stehen.
Peter
Peter Dannegger schrieb:> Nö, ein Darstellungsproblem. Vermutlich erweiterst Du nicht mit> Leerzeichen und alte Ziffern bleiben bei kürzeren Zahlen stehen.
Danke für die schnelle Antwort. Das stimmt, das macht Sinn :). Weiß zwar
noch nicht ganz wie das zu bewerkstelligen ist, da ich bisher auf eine
vorgefertigte Header Datei für das LCD zurückgreife aber wird schon
irgendwie :).
Kommst du auf die 5 kHz über: 2 Umdrehungen/s *1024*2= 4100 Hz? Bei der
Frequenz funktionierts aber leider nicht zuverlässig... Hab glaub auf
rn-wissen mal gelesen dass es das 20-fache der Grundfrequenz sein
soll...
Noch eine Verständnisfrage:
Soweit ich das Programm verstanden habe ist in enc_delta je nach
Richtung entweder 10 oder 01 gespeichert oder? Warum ist es denn
enc_delta += und nicht nur =? Denn angenommen ich würde es in der
Abtastfrequenz wirklich schaffen 2 Impulse weiterzudrehen, also 01+01=
10, dann interpretiert es doch der µC als 1 Schritt in die andere
Richtung..
Wenn ich das richtig verstanden habe ist die Auswertung eines Drehgebers
mit Interrupts die durch Flanken ausgelöst worden sind nur wegen den
prellenden (mechanischen) Tastern ungeeignet/schlechter. Wäre es aber
nicht für meinen magnetischen bzw. später optischen Drehgeber nicht
sogar besser? Oder tritt auch hier Prellen auf?
Ich hoffe es ist ok dass ich soviele Fragen gestellt habe. Freu mich auf
jeden Fall über eure Antworten. Danke!
Frank
@ Frank (Gast)
>Frequenz funktionierts aber leider nicht zuverlässig... Hab glaub auf>rn-wissen mal gelesen dass es das 20-fache der Grundfrequenz sein>soll...
Ist hier falsch.
>Richtung entweder 10 oder 01 gespeichert oder? Warum ist es denn>enc_delta += und nicht nur =?
Weil die Differenz (delta) addiert werden muss.
>Wenn ich das richtig verstanden habe ist die Auswertung eines Drehgebers>mit Interrupts die durch Flanken ausgelöst worden sind nur wegen den>prellenden (mechanischen) Tastern ungeeignet/schlechter.
u.a.
> Wäre es aber>nicht für meinen magnetischen bzw. später optischen Drehgeber nicht>sogar besser? Oder tritt auch hier Prellen auf?
Kann sein, muss nicht. Ist aber für dein Problem egal.
Dein Ansatz ist falsch. Für eine einfach Drehzahlmessung braucht man die
echte Dekodierung nicht. Man nutzt einfach eine Spur, A oder B, und
macht einen stinknormalen Frequenzzähler. Das macht der AVR mit links
und gähnt dabei. Ein Timer zählt die Pulse am Eingang, ein zweiter
generiert die Messzeit. Das passiert alles in Hardware. Die CPU muss nur
ab und an die Zähler auslesen und daraus die Drehzahl berechnen.
MFG
Falk
Falk Brunner schrieb:> für eine einfach Drehzahlmessung braucht man die> echte Dekodierung nicht.
Hey danke Falk für deine Antwort.
Da habe ich mich wohl missverständlich ausgedrückt. Ich brauche im
Endeffekt eigentlich keine Drehzahlmessung, sondern soll einen Schlitten
der über einen Schrittmotor angetrieben wird regeln. Also eine
Positionsbestimmung / -regelung. Deshalb benötige ich schon die Anzahl
zurückgelegter Schritte. Welches Verfahren ist denn dann deiner Meinung
nach am Sinnvollsten?
Viele Grüße
Frank
P.S: Warum Ist die Abtastfrequenz als 20-faches der Grundfrequenz
falsch?
Weil du hier kein sinusförmiges Signal hast, was noch rekonstruierbar
sein soll, sondern ein einfaches Rechtecksignal.
Mit freundlichen Grüßen
Thorsten Ostermann
Ich bin es nochmal :)
Es wäre schön wenn mir jemand weiterhelfen würde und mir sagt, welches
Verfahren (zur Debatte stehen ja wohl nur Timer und Flankeninterrupts,
oder?) für die Auswertung eines optischen Drehgebers mit 350 Impulsen/U
in Bezug auf Zuverlässigkeit und Belastung des µC geeigneter ist. Wie in
einem vorigen Beitrag erwähnt handelt es sich bei der Auswertung um die
Positionsbestimmung, ich muss also schon die Schritte mitzählen,
insofern sollte es schon sehr genau sein.
Vielen Dank,
Grüße,
Frank
Albert ... schrieb:> Frank schrieb:>> rehgebers mit 350 Impulsen/U> Eine Umdrehung pro Minute/Sekunde/Millisekunde? Da musst du schon etwas> genauer werden.
Stimmt da fehlt n halber Satz. Der Drehgeber gibt 350 Impulse / U aus,
der Schrittmotor dreht mit max. 300U/min
Die neueren AVRs haben ja nen Pin-Change-Interrupt. Da kann man diesen
nehmen anstelle eines Timerinterrupts. Also für beide Eingänge den
Pin-Change-Interrupt aktivieren.
Damit ist die max CPU-Last für hohe Drehzahlen geringer.
Peter
Vielleicht habe ich ja was nicht mitbekommen,
aber in der Überschrift steht Drehgeber
und im Beitrag von Frank erwähnt er magnetische Drehgeber,
ich geh also mal davon aus, daß es um Drehgeber geht.
Und da empfiehlt ein Peter Dannegger auf die Frage
"zur Debatte stehen ja wohl nur Timer und Flankeninterrupts"
allen Ernstes die komplett untauglichen Flankeninterrupts,
auch nicht mit der vollkommen falschen Begründung
"Damit ist die max CPU-Last für hohe Drehzahlen geringer."
(es wäre natürlich umgeklehrt).
Wahnsinn, das kann ja wohl nicht sein, Drehgeber liest man NIE
mit Flankeninterrupts aus, das wäre als ob man Tastendrücke
per pin change Interrupt zählen wollte (egal ob es jetzt um
Inkrementposition, Drehzahl oder Positionsbestimmung geht)
Gerade ein Peter Dannegger sollte das nach seine Entprellroutine
für Tasteneingabe verstanden haben.
Zu Drehgebern ist eigentlich alles gesagt:
http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29
Auch magnetische Drehgeber prellen, elektrische Störungen im
Übergang können das bewirken.
Die Probleme (100kHz, falsche Ausgabe) sind ja schon versucht
worden zu erklären und beantworten, leider ohne Rückmeldung.
Du hast schon richtig gelesen.
Der Pin-Change-Interrupt funktioniert sehr gut. Besonders, wenn einem
Leute mit schnellem Drehen beweisen wollen, daß die Software sich
verzählt.
Man muß also nicht ständig eine hohe Interruptlast erzeugen, sondern
nur, wenn wirklich schnell gedreht wird.
Es gibt natürlich bei Positionsgebern an vibrierenden Maschinen die
seltene Möglichkeit, daß eine hohe Impulszahl entsteht und die CPU
verlangsamt (nur ein Main-Loop Befehl zwischen den Interrupts).
Aber dagegen kann man einfach in dem Pin-Change-Interrupt einen Zähler
einbauen, der bei einem Maximalwert den Interrupt disabled und einen
Fehler meldet. Ansonsten setzt ein Timerinterrupt diesen Zähler zyklisch
zurück.
Auch eine Möglickeit wäre, der Pin-change-Interrupt disabled sich, setzt
einen Timer-Compare-Interrupt auf 10µs und dieser enabled ihn wieder.
Man hat dann max 100kHz Abtastrate, aber nur bei Bedarf.
Peter
Puh, jetzt bin ich leicht verwirrt. Ist also für (letztendlich) optische
Drehgeber der Flankeninterrupt das sinnvollere?
Ich denke mal in Verbindung mit einem Zustandsvergleich durch eine Gray
Code Tabelle oder?
Die Idee mit der Fehlermeldung bzw. dem switchen auf Timer-interrupt
hört sich gut an (ich hoff ich schaff es gscheit zu implementieren),
danke Peter!
Frank
MaWin schrieb:> Die Probleme (100kHz, falsche Ausgabe) sind ja schon versucht> worden zu erklären und beantworten, leider ohne Rückmeldung.
Hab erst beim zweiten Mal erkannt, dass das an mich gerichtet war.
100 kHz sind bei mir "komischerweise" tasächlich noch notwendig und
sogar da kommt es zu Fehlern wenn man sehr schnell mit der Hand dreht.
Da ich aber letztendlich einen optischen Drehgeber mit 360 Impulsen/U
verwenden werde statt den magnetischen mit 1000 Imp/U hoffe ich dass
sich das Problem von "allein löst", ich melde mich ggf. nochmal :)
Die falsche Ausgabe lag tatsächlich am LCD und wurde von mir "behoben"
indem ich die Werte per RS232 an den Computer ausgebe.
Möchte mir vllt noch jemand verraten ob denn nun Flanken oder doch Timer
ISRs für meine Auswertung von optischen Drehgebern sinnvoll ist?
Grüße,
Frank
Hallo,
ich muß demnächst einen optischen Incrementalgeber (5000 Impulse pro
Drehung) Auslesen und würde gerne die ENCODE.C variante wählen, nun muß
ich um die Hardware anpassung vorzubehmen eine parametriebare
Drehreichtungsumkehr mit einbauen, dazu kann ich ja entweder PHASE A mit
PHASE B Vertauschen oder woanders ansetzen, nur sehe ich nicht genau wo
ich das am besten im Code bewerkstellige, kann mit jemand da mal einen
Denkanstoß geben, hab leider die Hardware noch nicht fertig um damit
rumzuspielen, aber dieses Problem geistert mir die ganze Zeit durch den
Kopf.
Was ich möchte das die Drehrichtung durch einen Port PIN umschaltbar
ist, dies muß ich machen der der Incremantalgeber entweder von links
oder von rechts ans Band geschraubt wird.
mfg,
Bjoern
Hallo,
nach dem x mal ansehen des codes, fällt mir grade etwas auf.
langt es einfach von der varibale i bit 1 zu invertieren um das zu
erreichen was ich möchte ?
mfg,
Bjoern
Hallo an alle,
ich versuche schon seit Tagen den zweiten Code zu entschlüsseln. Für
meinen optischen Impulsgeber brauche ich die Richtung. Also ob er Rechts
oder Links herum dreht.
Kann mir vielleicht jemand erklären, wie sich die Variable enc_delta für
die beiden Richtungen verhält? Damit kann ich dann schauen, welche
Ausgänge am PortB freigeschaltet werden.
Momentan habe ich für einen Richtungssinn den Code : 1111 -> 1110 ->
1101 -> 1100. Dieser Code müsste nacheinander dann am Ausgang PB0 und
PB1 zu erkennen sein. Oder sehe ich hier irgendetwas falsch.
#include <io.h>
#include <interrupt.h>
#include <signal.h>
#define PHASE_A (PINC & 1<<PINC0) // PINC.0
#define PHASE_B (PINC & 1<<PINC1) // PINC.1
volatile char enc_delta; // -128 ... 127
int main( void )
{
TCCR0 = 1<<CS01; //divide by 8 * 256
TIMSK = 1<<TOIE0; //enable timer interrupt
DDRB = 0xFF;
sei();
for(;;) // main loop
PORTB = enc_delta;
}
SIGNAL (SIG_OVERFLOW0)
{
static char enc_last = 0x01;
char i = 0;
if( PHASE_A )
i = 1;
if( PHASE_B )
i ^= 3; // convert gray to binary
i -= enc_last; // difference new - last
if( i & 1 ){ // bit 0 = value (1)
enc_last += i; // store new as next last
enc_delta += (i & 2) - 1; // bit 1 = direction (+/-)
}
}
Kann mir jemand erklären, wie ich aus der variable enc_delta eine
Drehrichtungserkennung machen kann? Mich interessieren ja nur die ersten
beiden Bits?, oder nicht?
Momentan zerbreche ich mir den Kopf darüber.
Weiterhin, möchte ich gerne wissen, wann der Drehgeber eine volle
Umdrehung gemacht hat. Der Geber hat 500 Impulse.
Vielleicht kann ich das ja über die For Schleife in der mainloop
realisieren? Aber irgendwie komme ich da nicht weiter....
obbedaja schrieb:> Kann mir jemand erklären, wie ich aus der variable enc_delta eine> Drehrichtungserkennung machen kann? Mich interessieren ja nur die ersten> beiden Bits?, oder nicht?> Momentan zerbreche ich mir den Kopf darüber.>> Weiterhin, möchte ich gerne wissen, wann der Drehgeber eine volle> Umdrehung gemacht hat. Der Geber hat 500 Impulse.> Vielleicht kann ich das ja über die For Schleife in der mainloop> realisieren? Aber irgendwie komme ich da nicht weiter....
Die Drehrichtung erkennst Du daran, ob enc_delta positiv oder negativ
ist. Für die volle Umdrehung must Du oft genug enc_delta in Deiner
mainloop auslesen und aufaddieren, wenn die Summe 500 ist hat er eine
volle Rechtsdrehung gemacht, bei -500 eine volle Linksdrehung (oder
umgekehrt...)
Hallo,
ich habe es jetzt geschafft den Drehgeber und die Drehrichtung
auszugeben. Weiterhin zählt mir ein Zähler die Inkremente und gibt pro
voller Umdrehung ein digitales Signal aus.
Dies klappt perfekt bis zu einer bestimmten Drehzahl (ca. 500U/min), ab
dieser werden plötzlich rechts und links Drehungen erkannt und ich kann
damit nicht mehr weiter arbeiten.
Kann mir jemand sagen, ob dies am Inkrementalgeber liegt? Oder eher an
der Abtastung mittels Timer. Ich lasse den Timer ohne Vorteiler laufen,
denn mit Vorteiler kann ich auch die kleinen Drehzahlen nicht auswerten.
Ich freue mich auf eine Antwort.
obbedaja schrieb:> Kann mir jemand sagen, ob dies am Inkrementalgeber liegt?
Das liegt wohl eher am Abtast-Theorem. Vermutlich verpaßt du Phasen des
Gebers. Guck' dir auf 'nem Oszi mal deine Gebersignale und den
Abtasttakt an.
Danke für die schnelle Antwort. Habe soeben die Spuren A und B mit einem
Messrechner aufgenommmen, hatte kei Oszi zur Hand.
Im unteren Drehzahlbereich laufen die Rechtecksignale (mit leichter
Rampenbildung) sehr genau und 90° verschoben. Erhöhe ich die Drehzahl,
werden aus den Rechtecksignalen -> spitze Dreiecksignale und ca. jeder
fünfte Strich wird noch als Rechteck erkannt.
Dabei hatte ich den Geber beim Drehen festgehalten und bemerkt, dass er
eine leichte Unwucht aufweist. Ich hoffe, dass der Fehler daher kommt
und meine Messergebnisse verfälscht.
Neuer Inkrementalgeber ist bestellt und werde sobald er da ist, neues
berichten.
Aber eine allgemeine Frage zu dem ablaufenden Timer0 (8-bit) habe ich
noch.
Ich benutze einen neuen Inkrementalgeber mit 1024 Impulsen. Meine
Drehzahl ist 1333U/min.
Der Geber hat somit eine Frequenz von 22749Hz=23KHz.
Nach dem Abtasttheorem müsste ich mit 46KHz das Signal abtasten.
Wie kann ich meinen Timer einstellen, damit er dies auch so macht? D.h.
evtl einen Vorteiler einbauen?
zur Info: Der Micrcontroller hat einen externen Quarz mit 3,6864MHz.
Hallo,
bin echt beeindruckt von dieser Routine. Es funktioniert super. Wie
würdet ihr den Taster des Inkrementalgebers mit einbinden? Auch in der
ISR vom Timer? Wie würdet ihr den am besten Entprellen?
Marcel schrieb:> Wie> würdet ihr den Taster des Inkrementalgebers mit einbinden? Auch in der> ISR vom Timer? Wie würdet ihr den am besten Entprellen?
Ich würde dafür Peters Entprellroutine benutzen und diese ebenfalls in
der Timer-ISR aufrufen.