Kompilieren ist o.k. Aber keine Anzeige. Denke ich habe einen 2 step
encoder. Wollte mit dem Drehgeber später einmal einfach ein Register
hoch und runterzählen.
Wo liegt der Fehler?
Vielen Dank im voraus
Hi!
Pullups habe ich fest verdrahtet auf dem Lochraster. Mit 10k an 5V. Habe
alternativ auch schon mal mit den Tastern vom STK 500 probiert. doch es
wurde überhaupt nichts angezeigt. alle Leds sind an, also Speicherinhalt
= 0.
Dacht erst ich hätte den Counter falsch initialisiert, aber das müsste
eigentlich passen......
Jupp, das funktioniert. Led links rechts bzw rechts links sind am
blinken. Aber das Programm scheint irgendwie keine Eingänge zu bekommen
oder zählt einfacch nichts. Hab leider kein Dragon Modul zum debuggen.
Sind denn meine Änderungen am Counter für den Atmega 88 richtig?
Tom St. schrieb:> Jupp, das funktioniert. Led links rechts bzw rechts links sind am> blinken.
Ja, aber auch richtig?
D.h. alle 4 Phasen sind zu sehen?
Der Code sieht o.k. aus, häng mal Dein .lss File ran.
Peter
Also ich habe 2 LEDs die ich ansteuer. Wenn ich links herum drehe, kommt
erst die linke und dann kurz darauf die rechte LED (ähnlich
Wechselblinker). Wenn ich rechts herum drehe, kommt erst die rechte LED
und kurz darauf die linke. Hab gerade noch gesehen, das mir AVR beim
übersetzen eine Warnung auspuckt:
../Drehgeber.c:28: warning: 'TIM1_COMPB_vect' appears to be a misspelled
signal handler
Macht vielleicht der Compiler probleme?
Tom St. schrieb:> Also ich habe 2 LEDs die ich ansteuer. Wenn ich links herum drehe, kommt> erst die linke und dann kurz darauf die rechte LED (ähnlich> Wechselblinker). Wenn ich rechts herum drehe, kommt erst die rechte LED> und kurz darauf die linke. Hab gerade noch gesehen, das mir AVR beim> übersetzen eine Warnung auspuckt:>> ../Drehgeber.c:28: warning: 'TIM1_COMPB_vect' appears to be a misspelled> signal handler>> Macht vielleicht der Compiler probleme?
TIMER1_COMPB_vect
Habe ich geändert. War auf TIM weilch das so im Handbuch für Atmega88
stand. Jetzt ist zumindest die Warnung weg, aber immernoch kein zählen.
Wenn ich anstelle der Pins 1 & 3 nun 4 & 3 ändern möchte, dann mach ich
das zum einem oben beim `define´ und auch unten bei ´neu´ ,oder?
LED bekomme ich in der ISR nicht zum leuchten. Er scheint eine Abfrage
der Eingänge zu machen, im encode_init. Dann geht er in main und
arbeitet die for-Schleife ab. Fragt wohl die Eingänge nicht mehr ab. Der
Vergleich in der ISR findet wohl nicht statt. Komm irgendwie nicht
weiter..... bitte um weitere Vorschläge DANKE!
Tom St. schrieb:> TCCR1B = 1<<WGM12^1<<CS11^1<<CS10; // CTC, XTAL / 64> OCR1BL = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5); // 1ms
Sicher, daß diese Zeile auch das macht und daß CTC bei Compare-B
erfolgt?
Peter
So, habe jetzt beide Handbücher (dauert etwas zu laden), Atmega16
http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf
und das vom Atmega88
http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf
genau verglichen. Damit ich die gleichen Funktionen wie auf dem 16er
nutzen kann, muss ich beim 88er den Timer/Counter1B benutzen.
Entsprechende Änderungen habe ich im Programm vorgenommen.
TCCR1B = 1<<WGM12^1<<CS11^1<<CS10; // CTC, XTAL / 64
OCR1B = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5); // 1ms
TIMSK1 |= 1<<OCIE1B;
}
ISR(TIMER1_COMPB_vect) // 1ms for manual movement
{
int8_t neu, diff;
;
neu = 0;
.....
Aber, wie sollte es anders sein, immernoch keine Zählung.
Bin jetzt am Ende meiner Ideen. Wieso kann ich den 88er nicht zum laufen
bekommen?
Tom St. schrieb:> genau verglichen. Damit ich die gleichen Funktionen wie auf dem 16er> nutzen kann, muss ich beim 88er den Timer/Counter1B benutzen.
ALso ich les da was anderes aus dem 88-er Datenblatt
Tabelle 15.4
Modus 4, CTC
Der Top Wert ist OCR1A
A nicht B
Das ...
OCR1BL = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5); // 1ms
nur dann eben mit A und nicht B, würde ich auch nicht so machen.
Wer sagt dir, dass da kein Wert größer 255 rauskommt
OCRA1 = XTAL / 64.0 * 1e-3 - 0.5;
SUPER! Das wars!
Nur jetzt muss ich das erstmal verstehen. Ihr sagtet das ich OCRA1A
nehmen soll. Mit dem gehts auch. Nur laut Handbuch hat das
TCCR1A-Register keine Möglichkeit das WGM12 - Bit zu setzen, welches ja
laut Tabelle 15-4 erfordelich ist um CTC zu setzen. Deswegen bin ich auf
das TCCR1B gegangen. Hier kann ich das Register auf CTC setzen, sowie
auch den erfordelichen Teiler (64) einstellen. Wo war mein Denkfehler?
Vielen Dank für Eure Hilfe !!!
Tom
Tom St. schrieb:> Nur jetzt muss ich das erstmal verstehen. Ihr sagtet das ich OCRA1A> nehmen soll. Mit dem gehts auch.
Gut
> Nur laut Handbuch hat das> TCCR1A-Register keine Möglichkeit das WGM12 - Bit zu setzen,
richtig
> welches ja> laut Tabelle 15-4 erfordelich ist um CTC zu setzen.
Das Bit ist im TCCR1B Register
> Deswegen bin ich auf> das TCCR1B gegangen. Hier kann ich das Register auf CTC setzen, sowie> auch den erfordelichen Teiler (64) einstellen. Wo war mein Denkfehler?
TCCR1A ist nicht gleich OCRA1
Das eine ist das KOnfigurationsregister und das andere ist das
Vergleichsregister.
Und auch ja: TCCR1A hat nicht deswegen ein A am Ende, weil es das
Konfigurationsregister für den A Kanal ist. Es gibt einfach 2 Stück
Konfigurationsregister, TCCR1A und TCCR1B die beide zusammen Dinge am
Timer 1 einstellen.
Das hat aber nichts mit einem A Kanal oder einem B Kanal zu tun, so wie
beim OCRA1. Da steht ja auch das A vor der Zahl (die den Timer
symbolisiert) und nicht dahinter :-)
Sorgfältig arbeiten und nicht übereilt Schussfolgern. Im Zweifel nicht
raten, sondern im Datenblatt nachsehen.
O.k. das macht Sinn.
zitat:
Das hat aber nichts mit einem A Kanal oder einem B Kanal zu tun, so wie
beim OCRA1. Da steht ja auch das A vor der Zahl und nicht dahinter?
Nur in meinem Handbuch steht überall OCR1A und wenn ich das mal anders
in den Compiler tippe, dann gibts auch einen error:
../Drehgeber.c:24: error: 'OCRA1' undeclared (first use in this
function)
Trotzdem schon mal vielen Dank für die Erklärung, Karl Heinz !
Tom St. schrieb:> O.k. das macht Sinn.>> zitat:> Das hat aber nichts mit einem A Kanal oder einem B Kanal zu tun, so wie> beim OCRA1. Da steht ja auch das A vor der Zahl und nicht dahinter?>>> Nur in meinem Handbuch steht überall OCR1A und wenn ich das mal anders> in den Compiler tippe, dann gibts auch einen error:
Erwischt.
Nehm mich schon selber an der Nase und schau demnächst wieder mehr ins
Datenblatt für die Bezeichnungen :-)
Hallo Ihr,
ich stehe gerade am Anfang der Programmierung und versuche mit ein Bild
zu machen und die Programme nachzuvollziehen.
Gibt es irgendwo eine detailierte Doku, was die Befehle im einzelnen
bedeuten, gerade die C-Befehle? Z.B. "+=", "^=" oder "&".
Wahrscheinlich werden die meisten von Euch jetzt lachen, aber jeder hat
doch mal angefangen.
Ich habe es mittlerweile geschafft den Drehgebercode auf einen Attiny
2313 zu portieren und alles läuft bestens.
Mein Ziel ist es den Code soweit zu verändern, dass ich zwei Drehgeber
anschliesse und die Ausgabe für jeden Drehgeber nur angibt ob links oder
rechts gedreht wurde. Für jeden Detent/Raste ein kurzes Signal am
Ausgang (ca. 2ms).
Kann mir jemand helfen?
Gruß Marc
Marc Höner schrieb:> Gibt es irgendwo eine detailierte Doku, was die Befehle im einzelnen> bedeuten, gerade die C-Befehle? Z.B. "+=", "^=" oder "&".>AVR-GCC-Tutorial> Mein Ziel ist es den Code soweit zu verändern, dass ich zwei Drehgeber> anschliesse und die Ausgabe für jeden Drehgeber nur angibt ob links oder> rechts gedreht wurde. Für jeden Detent/Raste ein kurzes Signal am> Ausgang (ca. 2ms).> Kann mir jemand helfen?
Da brauchst Du das obige Programm nicht, da reicht eine einfache
Flankenbildung
Marc Höner schrieb:> Gibt es irgendwo eine detailierte Doku, was die Befehle im einzelnen> bedeuten, gerade die C-Befehle? Z.B. "+=", "^=" oder "&".
Das steht in jedem C-Buch.
Das AVR-GCC-Tutorial ist da weniger hilfreich, da es bereits von
gewissen Grundkenntnissen in C ausgeht.
Du brauchst ein C-Buch!
> Wahrscheinlich werden die meisten von Euch jetzt lachen, aber jeder hat> doch mal angefangen.
Schon. Haben wir. Auch uns ist das alles nicht in die Wiege gelegt
worden.
Wir haben Bücher durchgearbeitet. Denn da steht erst mal alles drinn,
was C ausmacht. Wir haben auf dem PC geübt. Bis die Finger gekracht
haben. Bis wir in C geträumt haben. Und nachdem der Grundstock in C da
war, haben wir noch den µC-spezifischen Teil durchgearbeitet. Zb mit dem
AVR-GCC-Tutorial.
Mir ist ja mittlerweile viel klar geworden, habe eine Menge im net
gelesen.
Eine Frage aber bleibt noch.
Was bedeutet: "return val >> 1;" am Ende der Funktion? Wird die Variable
"val" mit um ein Bit nach rechts verschobenen werten ausgegeben, oder
wie?
Mein Ziel ist es immer noch den Code so anzupassen, dass die Ausgabe nur
anzeigt, ob rechts oder links gedreht wurde.
@Axel: Mir ist klar, dass das auch einfacher geht, aber ich möchte üben
und verstehen.
Vielleicht kann mir ja doch jemand helfen.
Wenn ich es richtig verstehe der der Wert von "encode_read2()" die
Anzahl der counts seit dem letzten Aufruf an und das ganze mit
Vorzeichen.
Wenn ich jetzt die Schleife wie folgt ändere:
for(;;){
val = encode_read2();
LEDS = val;
}
müsste ich doch eigentlich die Anzahl der counts mit Vorzeichen
angezeigt bekommen? Leider passiert bei mir nichts.
Gruß Marc
Marc Höner schrieb:> Mir ist ja mittlerweile viel klar geworden, habe eine Menge im net> gelesen.> Eine Frage aber bleibt noch.> Was bedeutet: "return val >> 1;" am Ende der Funktion? Wird die Variable> "val" mit um ein Bit nach rechts verschobenen werten ausgegeben, oder> wie?
Ganz genau.
Ist eine Division konzeptionell eine Division durch 2.
> Mein Ziel ist es immer noch den Code so anzupassen, dass die Ausgabe nur> anzeigt, ob rechts oder links gedreht wurde.
Ja, dann mach das doch.
Wenn das was du aus encode_read2() bekommst positiv ist, dann wurde nach
rechts gedreht. Ist es negativ, dann nach links.
> Wenn ich es richtig verstehe der der Wert von "encode_read2()" die> Anzahl der counts seit dem letzten Aufruf an und das ganze mit> Vorzeichen.
ganz genau
> Wenn ich jetzt die Schleife wie folgt ändere:> for(;;){> val = encode_read2();> LEDS = val;> }> müsste ich doch eigentlich die Anzahl der counts mit Vorzeichen> angezeigt bekommen? Leider passiert bei mir nichts.
So schnell wirst du nicht schauen können.
Denn im Vergleich dazu, wie schnell der µC feststellt dass der Encoder
nicht gedreht wurde und daher alle LED wieder abschaltet, ist das Drehen
des Encoders ein seltenes/wahnsinnig schnell vorbeigehendes Ereignis.
Dein encode_read2 wird dir 99.9999% der Zeit melden, dass sich nichts
getan hat. Und genau das siehst du auch an den LED - nämlich nichts.
Warum lässt du dir denn nicht die Encoderpulse aufsummieren, wie Falk
das in seiner Vorlage gezeigt hat? Dann zählen die LED mit jedem Drehen
binär entsprechend hoch/runter.
Hallo,
ohne mir jetzt deinen Code oder den Threadverlauf genau durchgelesen zu
haben wollte ich nur kurz anmerken, dass der Drehgeber, für den ich vor
kurzer Zeit eine Auswertungsroutine geschrieben habe (Bourns PEC12)
anders als hier im entsprechenden Wiki-Eintrag auf dem ersten Diagramm
zu erkennen bei "Raststellungen" jeweils keinen Durchgang hat. Es ist
also nur jeder zweite der im Diagramm zu sehenden Rastpunkte auch
tatsächlich vorhanden.
Ich vermute, dass sich dies von Encoder zu Encoder unterscheidet.
MfG
Steven
Jetzt habe ich meinen gedanklichen Fehler gefunden. Danke dafür Karl
Heinz.
Der Änderungsimpuls (+/-) ist natürlich sehr kurz und kann optisch nicht
erkannt werden.
Wieder etwas mehr Verständniss erlangt.
Die Vorlage von Falk läuft ausgezeichnet, das war mein erstes
Erfolgserlebnis.
Jetzt geht es mir darum die Drehung des Enkoders an einen
Tastaturemulator anzuschliessen, dafür brauche ich nur die Signale ob
links oder rechts gedreht wird und dann für jeden klick ein Signal.
Hallo Ihr,
ich bin immer noch am grübeln und probieren komme aber nicht richtig
weiter.
Die Funktion encoder_read2() gibt die Anzahl der counts mit Vorzeichen
an, das Karl Heinz bestätigt. Daraus folgt: ein detent nach rechts = +1,
ein detent nach links = -1.
Wesentlich für die Ausgabe ist die "for Schleife" am Ende des
main-Programms.
Diese habe ich mal zu Testzwecken wie folgt geändert:
for(;;){
LEDS = encode_read2();
if (LEDS != 0)
_delay_ms(100);
val += encode_read2(); // read a two step encoder
}
Nach meinem Verständnis wird jetzt bei einem drehen um eine Raste nach
links oder rechts die if-Bedingung erfüllt und das Programm für 100ms
angehalten und die Anzeige zeigt +/-1 an, je nach Drerichtung.
Das funktioniert aber leider nicht zuverlässig, mal kommt die Anzeige,
mal nicht. Kann jemand helfen?
Mir ist klar, das die delay-Funktion nicht sehr elegant ist oder stört
sie sogar hier? Eigentlich möchte ich die Anzeige über eine
timer-function steuern , damit das Programm nicht angehalten wird. Aber
soweit bin ich noch nicht.
Gruß Marc
Marc Höner schrieb:> for(;;){> LEDS = encode_read2();> if (LEDS != 0)> _delay_ms(100);> val += encode_read2(); // read a two step encoder>> }
du darfst encode_read2 nur EINMAL aufrufen!
> Das funktioniert aber leider nicht zuverlässig, mal kommt die Anzeige,> mal nicht. Kann jemand helfen?
Logisch. Weil beim 2.ten Aufruf von encode_read2 unter Umständen genau
die Drehung zurückgegeben würde, mit der du dann aber nichts machst!
Besten Dank. Jetzt funktioniert dieser Teil schon einmal.
Aber meine Fragen gehen weiter. Ich habe eine zusätzliche Variable
eingeführt, es sieht jetzt so aus:
int main( void )
{
int8_t richt;
PORTD = 0xFF;
DDRD = 0x00;
LEDS_DDR = 0xFF;
encode_init();
sei();
for(;;){
richt = encode_read2();
if (richt != 0){
_delay_ms(50);
}
}
}
Nichts geht mehr, was habe ich jetzt schon wieder falsch gemacht?
Nur noch eine kurze Erläterung:
Ziel ist es den Wert von encode_read2 einer Variablen zuzuweisen. Diese
Variable soll dann geprüft werden. Ist der Wert > 0, dann LEDS = 0x01,
ist der Wert < 0 dann LEDS = 0x02.
Hallo Falk,
besten Dank nochmal, der Code funktioniert ausgezeichnet.
Hallo Alle,
Da ich ja mittlerweile gelernt habe, das delays nicht besonders elegant
sind, würde ich das ganze gerne über den timer steuern.
Wie genau muss ich das realisieren?
Im Prinzip müsste ich eine globale Variable (mit volatile) definieren,
die bei jedem Aufruf der ISR inkrementiert wird. Abfrage in der
for-Schleife im main-Programm. Wenn die gewünschte Zeit (x ms)
überschritten ist, ausschalten der Ausgänge. Jetzt geht es noch um das
zurücksetzen, damit bei einer erneuten Eingabe die Ausgänge wieder
geschalten werden. Wo muss das geschehen, in "encoder_read"?
Gruß Marc