Hallo,
weil mich das interessiert und man ohne Quarz 2 Pins mehr hat am ATtiny,
gehe ich das mal an. Nun liest man ja darüber, dass man mittels 0x55
übertragen "einen Takt" auf der seriellen erzeugt und beim sich zu
syncronisierenden µC die Zeiten ausmisst und damit am Ende den OSCCAL
Wert korrigiert.
Das bin ich gedanklich durchgegangen. Mich stört daran, dass man vom
idealen Quarztakt beim Sender ausgeht. Sonst stimmt die gesamte Rechnung
im Empfänger nicht mehr. Ich möchte aber eine universelle Syncronierung
programmieren. Egal welcher Takt der Sender hat. Wenn man zum Bsp. 2
ATtinys mit internen RC aufeinander loslässt und die sollen sich erstmal
im Takt syncronisieren bevor sie serielle Daten austauschen.
Jetzt dachte ich mir, ich sende eine Weile mit kurzer Pause immer 10x
0x55 hintereinander. Dabei testet der Empfänger selbstständig mit - und
+ seines OSCCCAL Wertes beide Extreme aus, bis er das 10x 0x55 nicht
mehr fehlerfrei empfängt. Dann bilde ich den Mittelwert von beiden
extremen OSCCAL Werten und habe den perfekten "Korrektor"-Wert
ermittelt. Unabhängig vom Takt.
Wäre doch einfach und perfekt. Nur warum macht das so niemand?
Du übersiehst dabei zwei Dinge:
1. Die Frequenzen bis zu denen der UART die Daten noch fehlerfrei
empfangen kann, liegen nicht unbedingt symmetrisch um die ideale
Frequenz.
2. Der Zusammenhang zwischen dem OSCCAL-Wert und der resultierenden
Frequenz ist nicht linear und bei manchen AVRs noch nicht einmal stetig.
Übrigens geht die "herkömmliche" Methode keineswegs von einer idealen
externen Taktquelle aus, sondern nähert sich immer dem gegebenen Takt
soweit als möglich an. Der OSCCAL-Wert wird ja nicht aus dem Timer-Wert
errechnet, sondern so lange verändert, bis der Wert gefunden ist, bei
dem der lokale Takt der gegebenen Taktquelle am nächsten kommt.
Hallo,
das die serielle Baudrate zum µC Takt passen muß, ist mir bewußt.
Ich möchte nur sicherstellen, um beim Bsp. mit 2 ATtinys zu bleiben,
dass eben dann der Empfänger auch mit 8,2MHz taktet wenn der Sender mit
8,2MHz taktet. Und nicht mit angenommenen 8MHz.
Weil zum Bsp. die Spannung statt 3,3V eben 4,5V beträgt oder was auch
immer.
Aber eines habe ich wohl übersehen. Die Nichtlinearität zwischen OSCCAL
und µC Takt.
Also muß man vorher den Sender µC Takt ausmessen und dann wie üblich
beschrieben im Empfänger die Taktzeiten ermitteln und rechnen? Weil wenn
ich im Empfänger µC mit idealen 8MHz rechne aber der Sender mit 8,2MHz
taktet nützt mir das ja auch nichts.
Ich dachte ich hätte die übliche Methode verstanden. Scheinbar doch
nicht.
Wenn ich im Empfänger mittels Timer die eingehenden Takte ermittel, dann
rechne ich ja mit idealen Werten. Weil ich meinen eigenen Takt ja nicht
genau kenne. Ich gehe davon aus, dass so und soviel Timercounts der und
der Zeit entsprechen. Irgendeine genaue Taktangabe zum rechnen benötige
ich doch? Am besten den µC Takt vom Sender. Mit ganz im dunkeln stochern
und darauf syncronisieren möchte mir nicht in den Kopf. Irgendeine Größe
muß doch vorher bekannt sein.
Veit D. schrieb:> Weil wenn> ich im Empfänger µC mit idealen 8MHz rechne aber der Sender mit 8,2MHz> taktet nützt mir das ja auch nichts.
Das verstehe ich nicht ganz. Genau das willst Du doch. Wenn der Sender
200khz schneller läuft, muss der Empfänger doch auch entsprechend
schneller laufen.
Selbst wenn der Sender nur mit 4Mhz laufen würde, hättest Du mit dieser
Methode eine funktionierende Kommunikation.
Gruß, Stefan
Ich wuerd den Osccal in die Mitte Setzen undvon dort aus zu
synchronisieren versuchen. Der Empfaenger synchronisiert auf den Sender.
Eine Referenz braucht man nicht, aber ein Protokoll.
Veit D. schrieb:> Das bin ich gedanklich durchgegangen. Mich stört daran, dass man vom> idealen Quarztakt beim Sender ausgeht.
Wie kommst du auf diesen Unsinn? Natürlich geht niemand in diesem Fall
von einem idealen Quarztakt des Senders aus. Schlicht und einfach schon
deshalb, weil das für das Ziel der erfolgreichen Kommunikation keine
Rolle spielt. Dafür muss nur der Takt von Sender und Empfänger genau
genug übereinstimmen, die absolute Größe dieses Taktes ist völlig
irrelavant.
> Egal welcher Takt der Sender hat. Wenn man zum Bsp. 2> ATtinys mit internen RC aufeinander loslässt und die sollen sich erstmal> im Takt syncronisieren bevor sie serielle Daten austauschen.
Ist doch kein Problem. Es darf eben nur einer der beiden
nachkalibrieren. Nun muss man sich nur noch ein kleines Protokoll
ausdenken, mit dem ausgehandelt wird, wer der "Master" sein soll, der
seinen Takt konstant hält. Das Protokoll muss natürlich so gestaltet
sein, dass es keine bereits funktionierende serielle Verbindung
voraussetzt.
> Jetzt dachte ich mir, ich sende eine Weile mit kurzer Pause immer 10x> 0x55 hintereinander. Dabei testet der Empfänger selbstständig mit - und> + seines OSCCCAL Wertes beide Extreme aus, bis er das 10x 0x55 nicht> mehr fehlerfrei empfängt. Dann bilde ich den Mittelwert von beiden> extremen OSCCAL Werten und habe den perfekten "Korrektor"-Wert> ermittelt. Unabhängig vom Takt.
Da solltest du nochmal ernsthaft drüber nachdenken...
Normales Autobaud funktioniert über die Länge des Startbit, denn die
Autobaud Routine sollte nicht von einem bestimmten Zeichen abhängen.
Die Länge wird einmalig mit einem Timer oder so gemessen und dann in die
richtige UART Baudrate umgeschnurzelt.
Hallo,
irgendwie verstehen wir uns noch nicht.
Wie soll ich den mit dem Timer irgendwas vermessen, wenn mein Takt nicht
stimmt bzw. ich den Takt nicht kenne? Mit welchen bekannten Werten wird
denn gerechnet wenn nicht mit dem µC Takt?
Der Punkt ist, Du mußt weder Deinen eigenen Takt kennen, noch den des
Masters. Du mußt nur feststellen können, ob Du schneller oder langsamer
bist, als der Master.
Lassen wir den UART mal für einen Moment bei Seite und nehmen an, der
Master sendet ein Rechtecksignal, dessen Periode dem 128. Teil seiner
Taktfrequenz entspricht. Dieses Signal mißt Du mit einem Counter im
Capture-Mode der mit Deiner eigenen Taktfrequenz getaktet wird.
Hat der Counter am Ende der Periode einen Wert größer als 128, weißt Du
daß Deine CPU schneller läuft als die des Masters und mußt entsprechend
den OSCCAL-Wert verringern. Ist das Ergebnis kleiner als 128 läufst Du
zu langsam und mußt OSCCAL erhöhen. Das Ganze wird so lange wiederholt,
bis Du die 128 triffst oder zwei benachbarte OSCCAL-Werte gefunden hast,
die um die 128 herumtanzen.
Nun kennst Du zwar weder die absolute Frequenz des Masters noch Deine
eigene, aber Du weißt, daß die Frequenzen der beiden AVRs im Rahmen der
Möglichkeiten des RC-Oszillators übereinstimmen und sie damit bei
gleicher Baudraten-Einstellung problemlos miteinander kommunizieren
können.
Dabei kann es durchaus sein, daß Deine tatsächliche Baudrate so weit
neben dem nominellen Wert liegt, so daß eine Kommunikation mit einem
"bequarzten" UART, der die offiziellen Toleranzen einhält, nicht möglich
wäre. Dadurch, daß aber beide Kommunikationsparter sich auf einen
gemeinsamen Takt geeinigt haben, interessiert die Abweichung nicht.
Wird die Sache damit klarer?
Die Einfachheit der UART wird eben erkauft mit der Veinbarung in etwa im
gleichen Zeitraster zu arbeiten, das ist der (virtuelle) Takt.
Du könntest auch ne Taktleitung mitführen, will man oft nicht, manchmal
geht es auch nicht.
Alternative wäre z.B. der Manchestercode, da ist der Takt im Signal
enthalten, eigene Taktfrequenz spielt keine Rolle (solange genug Zeit
zum Codieren und Dekodieren bleibt). Nachteil doppelte Signalfrequenz.
Einen Tod muss man immer sterben :-)
Jaja, bei solchen Problemstellungen melden sich immer viele
hauptamtliche Bedenkenträger, die nur in starren Rastern
denken können...
MÖGLICH ist das - und hat auch den Reiz eine "lebendige"
Kommunikation zu programmieren, die sich auf ihre
Kommunikationspartner einstellt, anstatt sich darauf zu
verlassen, dass jeder Teilnehmer Quarz-genau funktioniert.
Eine zusätzliche Taktleitung ist überflüssig, wenn man
etwas Zeit im Programm-Ablauf für die Synchronisation übrig
hat/lässt.
Vielleicht nicht für den Büro-Alltag, aber für's wahre Leben!
Vereinfachend kommt dazu, dass man sich nur auf Abweichungen
von vielleicht +/-10% einstellen muss.
Dein Ansatz ist auch garnicht sooo verkehrt, aber du solltest
dir eine idiotensichere (fehlertolerante) STRATEGIE ausdenken,
wie du 2, oder auch mehrere µCs aufeinander synchronisierst!
1a: Soll ein bestimmter µC der Chef sein (einfacher zu
programmieren), oder
1b: Soll das der erste µC sein, der eingeschaltet wird?
(Aufwändiger zu programmieren, aber flexibler.)
2: Ein Einwurf kam schon: Die OSCCAL-Geschichte ist nicht ganz
einfach (dazu noch AVR-Typ-abhängig), aber mit Sachkenntnis
durchaus beherrschbar.
Dafür gibt es auch eine Anleitung im Netz!
Ich habe mir danach schon mal eine Synchronisation auf die
50 Hz Netzfrequenz programmiert, um Blind-/Wirk/Schein-Leistung
mit recht exakt N Samples/Netzperiode zu erfassen.
Die Einstellgenauigkeit erreichte < 0,5%, was bei serieller
Kommmunikation vollkommen ausreichend sein sollte.
Die Erfassungung des abschließenden Stopp-Bits (8N1) erfolgt nicht bei
halber Bitweite (50%), sondern bei 55% - da schaudert es nur Dummköpfen!
Mal sehen, ob ich den Link zur Anleitung wiederfinde...
Das es geht stand ja schon fest.
Was hat Alternativen aufzeigen mit Bedenkenträger zu tun?
Auf Netzfrequenz synchronisieren ist erstens weder neu und zweitens nur
noch in Ausnahmefällen realisierbar. Der klassische Trafo ist so gut wie
ausgestorben, das Netz selbst will man nicht im Gerät haben.
@ H.Joachim Seifert (crazyhorse)
Der TO will nun mal Port-Pins sparen, da ist es doch eher
zielführend, ihn darauf hinzuweisen, dass er zum Zeitverlust
für die Synchronisierung, den er ja schon eingeplant hat,
auch noch eine Strategie für den Clock-Master braucht.
Deine Taktleitung kostet dagegen je einen Port-Pin.
Die Netzsynchronisierung war ein BEISPIEL für die erreichbare
Genauigkeit, kein Vorschlag für die Takt-Referenz.
Taktleitung? Hatte ich doch geschrieben, das man das meist nicht will
und oft auch gar nicht kann...
Eigentlich gings um Manchester, funktioniert auch mit nur einer Leitung
und ist eben nicht drauf angewiesen, einen rel. genauen lokalen Takt zu
haben. Andere Gründe können durchaus dagegen sprechen, sowas zu
benutzen. Aber eine Alternative zum Takt kalibrieren/nachführen ist es
schon.
H.Joachim S. schrieb:> Taktleitung? [...] Eigentlich gings um Manchester
Es ging weder um Taktleitungen noch um Manchester, sondern darum, daß
der TO ein Verständnisproblem mit der Taktsynchronisation über OSCCAL
hatte und sich nicht erklären konnte, wie man einen Slave mit einem
Master synchronisieren kann, ohne den genauen Takt des Masters zu
kennen.
Die letzte On-Topic-Antwort dazu war meine von gestern 20:59. Seitdem
hat der TO sich nicht mehr gemeldet und alle weiteren Beiträge gingen am
Thema vorbei.
Ist ja auch egal. Ich hatte es so verstanden, dass es primär um den
Austausch serieller Daten geht und das nur mit dem internen Oszillator.
Die OSCCAL-Geschichte nur mittel zum Zweck.
Veit D. schrieb:> Wenn man zum Bsp. 2> ATtinys mit internen RC aufeinander loslässt und die sollen sich erstmal> im Takt syncronisieren bevor sie serielle Daten austauschen.
Hallo,
sorry, aber ich kann nicht ständig online sein. :-)
ja genau, ohne Takt oder sonstwas.
Die Erklärung von rmax 20:59 ist schon gut. Muß sie nur noch
nachvollziehen können. Das schwankt z.Z. zwischen verstanden und doch
wieder nicht. Ich muß mir das aufmalen und etwas rechnen.
Danke erstmal bis hierher.
Hallo,
ich denke ich habs in der Theorie durchdrungen. :-)
Jetzt programmiere ich mir erstmal einen Frequenzzähler, die Vorstufe
dessen und dann möchte ich darauf aufbauen um letztlich den OSCCAL
nachzustellen.
Manuelle OSCCAL Änderungen ergaben, dass ich später bei einem Wert von
36 landen müßte. Default sind 41. Bei Ub 5V. ATTiny841. Hatte einen
Timer im CTC Mode programmiert mit Prescaler 1 und Top 1, sodass der Pin
mit 2MHz taktete. Das habe ich am Oszi gemessen. Für ideale 8MHz µC Takt
natürlich nur.
Danke soweit.
Hallo,
muß doch nochmal darauf zurückkommen. Folgende Überlegung steckt noch in
mir.
Master: 8MHz (nominell)
Taktausgabe zum syncronisieren: 1kHz
macht einen positive Flanke zum zählen aller 1ms
Zählt der Slave eine Sekunde lang, muß er 1000 Counts haben damit er
weis das er syncron läuft. Damit ich als Programmierer aber weis das ich
auf 1000 Counts achten muß, muß ich vorher wissen das der Master mit
8MHz bzw. der Syncronisierungstakt mit 1kHz taktet. Ohne diese Angabe
geht das nicht.
Und wenn der Master mit ungenauen 8,5MHz läuft und damit der
Syncronisierungstakt mit 1062,5Hz, dann dauert es zwischen den zählbaren
Flanken 0,9411ms. Dann muß ich beim zählen auf 1062 Counts achten und
nicht nur auf 1000. Das weis ich aber vorher nicht.
Das syncronisieren mit dieser Methode funktioniert laut meiner Meinung
nach nur mit einem Master mit Quarz und bekannten Takt. Mit internen RC
Oscills funktioniert das nicht. Wenn es wie bei modernen ATtinys ein
Temperatur kompensierter Takt ist, wo man sagen kann der bleibt
ausreichend stabil, dann kann man den ausmessen und damit rechnen.
Ansonsten sehe ich da noch schwarz.
Versteht ihr jetzt mein Gedankenproblem besser?
Wenn die Nichtlinearität zwischen OSCCAL und Takt nicht wäre, dann wäre
meine obige Methode das Mittel der Wahl. Weil das ist wirklich
unabhängig vom Takt. Nur die Baudraten müssen auf beiden Seiten gleich
eingestellt sein.
Moment:
Das muß ich jetzt mit dem Baudratentakt machen. Nicht mit dem µC Takt.
Wenn ich zum Bsp. 250kBit/s einstelle, dann dauert ein Bit 4µs, heißt
aller 8µs eine positive Flanke zum zählen. Wenn ich nun soviele "0x55"
hintereinander für 1ms Dauer ohne Pause rausschicken würde, dann müßte
ich innerhalb der 1ms auf 125 Counts abgleichen im Empfänger.
Jetzt muß es stimmen, meine Denkweise. Ja / Nein?
Fuer den Baudraten Slave musst du eigentlich nur wissen wie viele Clock
counts du pro Bit, oder pro 10 bit zaehlen musst. Welcher Baudrate das
entspricht ist weniger wichtig.
Veit D. schrieb:> Jetzt muß es stimmen, meine Denkweise.
Das war ja schon oben mein Vorschlag. 1/(gemessene Länge des Startbit) =
Baudrate. Wenn du eine vorher vereinbarte Baudrate kennst, dann lässt
sich daraus der MC Takt regenerieren.
Hallo,
du meinst sicherlich:
"wie viele Clock counts du pro Byte, oder pro 10 bit zählen mußt ..."
"Welcher Baudrate das entspricht ist weniger wichtig."
Nur ich muß doch vorher wissen auf wieviele Takte hin ich
zählen/ablgeichen muß. Und das ist abhängig von der Baudrate wieviele µC
Takte während dessen vergehen. Egal ist ist die Baudrate laut meiner
Meinung nicht.
okay, sorry wenn ich das dann doch nicht verstanden hatte und schon
erklärt wurde. So langsam komme ich dahinter. Die Baudrate muß ja auf
allen beteiligten µC gleich eingestellt sein, sonst wird das ja nichts.
Das ist meine einzigste bekannte konstante Größe.
Danke und erstmal schönes Wochenende.
Veit D. schrieb:> Master: 8MHz (nominell)> Taktausgabe zum syncronisieren: 1kHz> macht einen positive Flanke zum zählen aller 1ms>> Zählt der Slave eine Sekunde lang, muß er 1000 Counts haben damit er> weis das er syncron läuft.
Soweit richtig.
> Damit ich als Programmierer aber weis das ich> auf 1000 Counts achten muß, muß ich vorher wissen das der Master mit> 8MHz bzw. der Syncronisierungstakt mit 1kHz taktet. Ohne diese Angabe> geht das nicht.
Falsch. Du musst wissen, dass Dein Slave so schnell laufen soll, dass
der Puls 1000 Counts dauert.
> Und wenn der Master mit ungenauen 8,5MHz läuft und damit der> Syncronisierungstakt mit 1062,5Hz, dann dauert es zwischen den zählbaren> Flanken 0,9411ms.
Und wenn Du derer 1000 nimmst, läuft Dein Slave exakt so schnell wie der
Master. Ziel erreicht.
> Das syncronisieren mit dieser Methode funktioniert laut meiner Meinung> nach nur mit einem Master mit Quarz und bekannten Takt. Mit internen RC> Oscills funktioniert das nicht.
Warum soll das nicht funktionieren? Das Ziel der Synchronisation ist,
dass der Slave genauso schnell läuft wie der Master. Wenn der Master
heute mit 7,9 und morgen mit 8,1 MHz läuft, hat der Slave das auch zu
tun.
> Moment:> Das muß ich jetzt mit dem Baudratentakt machen. Nicht mit dem µC Takt.
Läuft auf das gleiche hinaus. Du stellst Deinen Slave so ein, dass
dessen Startbit genauso lange dauert wie das vom Master. Dann laufen
beide gleich schnell und können Daten austauschen.
Veit Devil (devil-elec) schrieb:
> Das muß ich jetzt mit dem Baudratentakt machen. Nicht mit dem µC Takt.> ... Ja / Nein?
Da würde ich (gerade bei 250 kBd) NEIN sagen.
Beim Tiny2313, bei 8 MHz muss UBRR = 1 für 250 kBd sein.
Das Verändern um +/-1 halbiert/verdoppelt die Baudrate.
Selbst mit U2X = 1 ist jeder UBRR-Step ein Vielfaches der
Clockabweichung der RC-Oszillatoren. GEHT NICHT!
Verlier mal die Scheu vorm OSCCAL!
Falls du den 2313 hast, (mir fällt grad kein anderer Tiny mit
USART ein,) ist die OSCCAL-Einstellung sogar recht einfach, weil
es dort NICHT den Frequenzsprung bei OSCCAL von 127 auf 128 gibt.
Hallo,
@ soul:
"Falsch. Du musst wissen, dass Dein Slave so schnell laufen soll, dass
der Puls 1000 Counts dauert."
hmm, irgendwie denke ich wohl immer noch von der anderen Seite "des
Problems".
Aber stimmt du/ihr habt recht, man kann und sollte es von der anderen
Seite betrachten.
Also in meiner bisherigen Denkweise andersherum. Ihr lagt ja schon immer
richtig.
Ich schiebe den OSCCAL solange hin und her bis ich den Count vom
nominellen Takt gefunden habe.
In dem 1kHz Bsp. eben 1000 und mit dem 250k Baudratentakt eben 125.
@ Jakob:
ich verstelle nicht die Baudrate. Ich bleibe schon beim OSCCAL. Nur mit
dem erzeugten Takt auf der seriellen (permanent 0x55 ausgeben)
kalibriere ich den Slave mittels OSCCAL nach. Die Baudrate lasse ich
unverändert bzw. immer ein ganzes vielfaches von 8MHz. Ist übrigens ein
ATtiny841.
Wenn ihr vom Startbit redet, meint ihr dann wirklich, dass ihr nur die
Zeit dieses einen Bits vermessen tut? Das wäre mir ehrlich gesagt zu
kurz und zu ungenau. Ich wollte 1sec. lang einen Takt ausgeben worauf
sich der Slave syncronisieren kann. Danach abfragen ob es geklappt hat.
Wenn keine Antwort kommt oder ein nein, dann wiederholen. Und das alles
auch nur einmalig beim einschalten. In der Annahme das der temperatur
kompensierte RC im ATtiny841 stabil genug bleibt.
Ich freue mich auch darüber das ihr am Ball bleibt und mich nicht dumm
sterben lasst. Schriftlicher Austausch ist öfters nicht einfach.
Veit D. schrieb:> Wenn ihr vom Startbit redet, meint ihr dann wirklich, dass ihr nur die> Zeit dieses einen Bits vermessen tut? Das wäre mir ehrlich gesagt zu> kurz und zu ungenau.
Das ist einfach genau genug. Du darfst nicht vergessen, dass auch eine
noch so genaue Messung dir keinerlei Vorteile mehr bringt, sobald sie
deutlich genauer ist, als du die eigene Frequenz über dein Steuerglied
(also das OSCCAL-Register) überhaupt einstellen kannst. Jeglicher
Mehraufwand für die Messung ist also völlig huppse, für'n Arsch, oder
wie immer man das gepflegter ausdrücken mag...
Worüber du dir also viel mehr Gedanken machen solltest, als über die
Messgenauigkeit, ist die Sache, wenn zwei potentiell adaptive Teilnehmer
aufeinander treffen. Das erfordert viel mehr geistigen Aufwand und ist
der eigentliche Knackpunkt für eine wirklich universelle
Auto-Kalibrierung. Vor allem dann, wenn man das auf eine Kette oder gar
einen Ring solcher Teilnehmer erweitert...
Darauf solltest du deine geistigen Potenzen konzentrieren. Das, woran du
rumpfriemelst, ist doch dagegen absolut trivial...
Neee, davon haben wir ihn ja gerade abgebracht. Da sollen nicht zwei
Teilnehmer miteinander in Regelschwingung geraten, sondern einer ist der
Master und der hat immer Recht. Auch wenn dessen 8 MHz in Wahrheit nur
7,9 MHz sind.
soul e. schrieb:> Neee, davon haben wir ihn ja gerade abgebracht. Da sollen nicht zwei> Teilnehmer miteinander in Regelschwingung geraten, sondern einer ist der> Master und der hat immer Recht.
Das ist aber eben gerade nicht universell. Universell wird es erst, wenn
es ein Protokoll gibt, über den die Partner aushandeln, wer der Master
sein soll. Das habe ich schon gefühlte 1000 Postings vorher erklärt.
Hallo,
mit der universellen Syncronisierung meinte ich ganz zu Anfang bezogen
meinen Unverständnis der Methode bzw. dessen Ablauf. Weil ich immer
davon ausging man muß den Takt vorher kennen. Das ist aber nun geklärt.
Zum Glück. :-)
In meinen Aufbau bleibe ich aber dabei das ein bestimmter µC der Chef im
Ring ist und alle anderen müssen sich danach richten. Fertig. Ist für
mich einfacher und logischer.
Wenn die sich jetzt noch untereinander aushandeln sollen wer sich nach
wen richten soll, dann werde ich nie fertig und sprengt vielleicht auch
mein derzeitiges Rechenzentrum zwischen den Ohren. Ich mach das alles
rein Hobby mäßig.
Wegen dem nur einen Bit vermessen. Ich versuche das zu erfassen ... im
Moment sehe ich viele neue Fragen ... ich komme nochmal darauf zurück.
Veit D. schrieb:> In meinen Aufbau bleibe ich aber dabei das ein bestimmter µC der Chef im> Ring ist und alle anderen müssen sich danach richten. Fertig. Ist für> mich einfacher und logischer.
Das zeigt eigentlich nur eins: Du hast die Sache wirklich noch nicht
durchdacht, dich von trivialen Nebensächlichkeiten von den eigentlichen
Problemen abhalten lassen. Z.B. diesem: willst du es in den Griff
bekommen, dass nach n Ringgliedern am Ende des Ringes für den "Master"
der den den Anfang füttert, immer noch was verständliches ankommt...
DAS sind die eigentlichen Probleme einer solchen Architektur. Da
solltest du drüber nachdenken...
Veit D. schrieb:> Master: 8MHz (nominell)> Taktausgabe zum syncronisieren: 1kHz> macht einen positive Flanke zum zählen aller 1ms>> Zählt der Slave eine Sekunde lang, muß er 1000 Counts haben damit er> weis das er syncron läuft. Damit ich als Programmierer aber weis das ich> auf 1000 Counts achten muß, muß ich vorher wissen das der Master mit> 8MHz bzw. der Syncronisierungstakt mit 1kHz taktet. Ohne diese Angabe> geht das nicht.
Nein. Denn dein Ziel ist nicht, den Slave auf eine bestimmte absolute
Frequenz einzustellen, sondern auf eine Frequenz, die möglichst genau
mit der des Masters übereinstimmt. Das ist ein viel einfacheres Ziel.
Löse dich mal von absoluten Frequenzen. Wenn der Master mit nominal 8MHz
läuft und ein 1kHz Synchronisierungssignal sendet, dann dauert eine
Periode dieses Signals 8000 Taktzyklen.
Der Slave zählt jetzt auch die Länge der Periode des Synchronisierungs-
signals, aber mit seiner Taktfrequenz. Wenn er mehr als 8000 Takte
herausbekommt, dann läuft sein lokaler Takt offensichtlich schneller als
der des Masters. Sind es weniger, dann läuft er zu langsam. Jetzt kann
der Slave sein OSCCAL Register passend verändern und die Messung
wiederholen. So oft, bis er zwei benachbarte OSCCAL-Werte gefunden hat
die jeweils knapp mehr oder weniger als 8000 Takte ergeben. Den Wert der
näher liegt, stellt er dann ein.
> Und wenn der Master mit ungenauen 8,5MHz läuft
Dann hat eben der
> Syncronisierungstakt 1062,5Hz
Aber trotzdem immer noch 8000 Takte pro Periode. Der Slave stellt sich
dann auch auf 8.5MHz ein.
Hallo,
@ Axel:
das ist schon geklärt wurden und ich habs gerafft, Danke dennoch fürs
mitdenken.
@ der C freundliche:
darüber mußte dir in dem Thread keine Sorgen machen. Die serielle
Verbindung erfolgt am Ende mittels RS485. Tests mit MAX485 ICs erfolgten
schon. Zudem möchte ich keine Kilometer überbrücken sondern nur paar
wenige Meter. Mich interessiert hier die Funktionsweise der
automatischen Syncronisierung und ob ich das hinbekomme. Ich denke nun
ja. Das darf ich doch mal ausprobieren. Meinste nicht auch? Jeder fängt
mal mit irgendwas neuen an. Lass mich mal machen. Wenn was nicht klappt,
frage ich und du darfst mich gern korrigieren. Auch deinen Rat weiß ich
immer zu schätzen, auch wenn er manchmal für mich nicht sofort
ersichtlich ist. :-)
Hallo,
ich stecke noch in der Umsetzung fest.
Laut Atmel Application Note 2563 bzw. AVR054 muß man neben den UART Pins
noch einen zusätzlichen Interrupt Pin verschwenden. Wäre für mich später
dann etwas sinnlos, wenn ich von 2 gewonnenen Pins (ohne Quarz) einen
wieder abgeben müßte.
Jetzt bin ich am überlegen die UART vorrübergehend abzuschalten, also
die UART Pins als normale Pins zuverwenden, auf beiden Seiten und nach
hoffentlich erfolgreicher OSCCAL Korrektur wieder als UART umzuschalten.
Ist das ein gangbarer Weg?
Knut B. schrieb:> Controller mit PinChange-Interrupt-Möglichkeit können denselben Pin für> USART und Startbitzeitmessung benutzen.
Das kann jeder AVR, weil dazu schlicht kein Interrupt nötig ist. Der
RxD-Pin ist natürlich jederzeit auch als stinknormaler Input abfragbar.
Bist du schon EINEN Schritt weiter gekommen?
Sollte mich bei den bisherigen Beiträgen wundern...
Mittlerweile ist dir wohl klar, dass du zu Beginn über eine
Ableichroutine die Slave-CPU-Frequenz an die Master-CPU-Frequenz
angleichen musst. Ob 7,x MHz, oder 8,x MHz sind, ist WURSCHT.
Beim Tiny2/4/861 hast du aber keine USART, sondern eine USI.
Mit der kann man seriell kommunizieren. Aber nicht so ohne
Weiteres nach RS232-Norm...
Willst du den 2-Wire-, oder den 3-Wire-Mode nutzen?
Also DI/SDA und SCL, oder DI/SDA, DO und SCL?
Mit der Quarz-Einsparung hast du im 3-Wire-Mode gerade mal EINEN
Pin gewonnen...
Jedenfalls hast du damit nicht so einfach das RS232-Protokoll:
Startbit - n Datenbits - Stoppbit
Also kannst du auch kein Startbit ausmessen.
Schon garnicht genau genug, um bei 250 kBd mit der Messung
der Dauer eines Bits die CPU-Frequenz auf die erforderliche
Genauigkeit von 1..2% nachzustellen.
Zahlenbeispiel für 8 MHz:
T(250 kBd) = 4 µs = 32 Takte. Auflösung = 1/32 > 3%
Beim Tiny2/4/861 hast du die Möglichkeit, den DI/SDA-Pin
des Slaves in der Abgleichphase als INT1-Pin zu nutzen.
Sendet der Master auf seinem Out-Pin ein Abgleich-Bitmuster,
wie 0b00000001 (ohne Pause dazwischen!), könntest du über die
Messung des Abstands der positiven, oder negativen Flanke am
INT1-Pin des Slaves die Messung schon 8 mal genauer machen.
Für die Messung erfasst der Slave im INT1-Interrupt die Differenz
des Zählerstands eines ohne Vorteiler laufenden Timer-Counters
mit dem Wert beim vorigen INT1-Interrupt.
8 * 32 Takte = 256 Takte: Messauflösung = 0,4%
Mit OSCCAL regelst du den Systemtakt des Slaves möglichst nah
an den Takt des Masters. Dies ist erreicht, wenn über mehrere
Interrupt-Perioden möglichst genau 256 +/- 1..2 Takte für
dieses Abgleich-Bitmuster zu messen sind.
Anschließend stellst du den Slave auf USI-Mode um und sendest
eine gut erkennbare "Ich-Bin-Bereit-Meldung" über USI an den
Master.
Wenn der Master diese Meldung erkennen kann, antwortet er mit
einer gut erkennbaren "Legen-Wir-Los"-Meldung.
Dann kann's logehen. :-)
(Sonst sendet der Master weiter das Testmuster.)
Ojeh, da habe ich mich auf die ganze Clock-Synchronisierungs-
Debatte eingelassen... Aber:
Das ganze Takt-Abgleich-Problem ist überhaupt nicht vorhanden!
Da du beim Tiny2/4/861 keine USART, sondern eine USI hast, wird
das RS232-Protokoll mit Start / n * Data / evtl. Parity / Stop
bei vorgegebener Baudrate mitsamt erforderlicher Taktübereinstimmung
etc. p.p. überhaupt nicht unterstützt!
Da wirst du wohl den USI-2-wire-Mode (TWI) nutzen müssen.
Und dabei taket der jeweils sendende µC mit seinem SCL-Signal
seine Daten beim Empfänger ein.
Egal, ob der Master, oder der Slave am Senden/Empfangen ist.
Egal, ob der Master, oder der Slave mit dem Systemtakt
+/-10...??% daneben liegt.
Vergiss den Frequenzabgleich, sondern kümmere dich um das
TWI-Protokoll!
Die Vorgehensweise bei mehr als 2 Kommunikationspartnern ist
damit auch schon (fast) erledigt.
Wenn du unbedingt Frequenz-Abgleichen willst:
Benutze µCs mit USART.
Hallo,
ich hatte weder von einer USART noch von I2C geschrieben. Bringe das
nicht unnötig durcheinander. Außerdem mache ich das in meiner Freizeit.
Reines Hobby. Da dauert das nun einmal länger. Nur kein Stress.
Jakob schrieb:> Mittlerweile ist dir wohl klar, dass du zu Beginn über eine> Ableichroutine die Slave-CPU-Frequenz an die Master-CPU-Frequenz> angleichen musst.>> Beim Tiny2/4/861 hast du aber keine USART, sondern eine USI.> Mit der kann man seriell kommunizieren. Aber nicht so ohne> Weiteres nach RS232-Norm...
Stimmt. Direkt nicht. Mit Tricks schon (Appnote AVR307)
> Willst du den 2-Wire-, oder den 3-Wire-Mode nutzen?
Wenn er das wöllte, dann müßte er die Taktfrequenzen der beiden µC nicht
angleichen. Denn beide Protokolle führen den Takt mit. Die einzige
Einschränkung, die bei asynchronem Systemtakt bleibt, ist daß er nicht
die maximal mögliche Geschwindigkeit ausnutzen kann. Das dürfte in der
Praxis irrelevant sein, weil beide synchronen Modi viel schneller sein
können als ein UART. Wenn man also lediglich einen UART ersetzen will
...
> Also kannst du auch kein Startbit ausmessen.
Das eine folgt nicht aus dem anderen. Es ist kein Naturgesetz, daß er
das letztendliche Kommunikationsprotokoll für die Taktsynchronisierung
nutzen muß. Er kann genauso gut die entsprechenden Pins erst rein in
Software zur Synchronisation nutzen und erst wenn die Taktfrequenzen
abgeglichen sind, auf das USI/USART umschalten.
> Schon garnicht genau genug, um bei 250 kBd mit der Messung> der Dauer eines Bits die CPU-Frequenz auf die erforderliche> Genauigkeit von 1..2% nachzustellen.>> Zahlenbeispiel für 8 MHz:> T(250 kBd) = 4 µs = 32 Takte. Auflösung = 1/32 > 3%
Genau deswegen macht man das ja auch nicht so.
Hallo,
sorry, um eine UART bzw. USART gehts es schon. Nur nicht um I2C oder
andere. War gestern Abend etwas forsch.
Es geht mir hierbei nicht in erster Linie darum womit ich schneller
Daten übertragen kann, sondern darum ob ich es schaffe den einen µC mit
dem anderen zu syncronisieren. Bin gerade bei der Codeumsetzung. USART
könnten übrigens beide. ATmega2560 und ATtiny841.
Jakob schrieb:> Mittlerweile ist dir wohl klar, dass du zu Beginn über eine> Ableichroutine die Slave-CPU-Frequenz an die Master-CPU-Frequenz> angleichen musst. Ob 7,x MHz, oder 8,x MHz sind, ist WURSCHT.
Vorher muss er erstmal klarkriegen, wer der Master sein soll...
DAS wurde bereits als das ultimative Kriterium für eine wirklich
universelle Sache herausgearbeitet...
> Beim Tiny2/4/861 hast du aber keine USART, sondern eine USI.> Mit der kann man seriell kommunizieren. Aber nicht so ohne> Weiteres nach RS232-Norm...
Natürlich muss man die mit einem USI als Hardwareunterstützung selber
sachgerecht umsetzen. Genauso dann, wenn es um eine reine Soft-UART
geht. Bezüglich der Kalbrierung auf den Takt eines Masters gibt es aber
absolut keinen Unterschied. In ALLEN Fällen muß man man zuerst mal
aushandeln, wer der Clock-Master sein soll, und in ALLEN Fällen muß
man dan den eigenen Takt an den des Masters so gut wie möglich
angleichen, wenn man bei der Aushandlung die Client-Rolle erwischt hat.
Es spielt hierfür absolut KEINE Geige, ob man die eigentliche
Kommunikation ganz, teilweise oder garnicht mittels
Hardwareunterstützung abwickelt.
Es geht hier in diesem Thread eigentlich auch nur um genau den Teil der
Sache, der VOR der eigentlichen Kommunikation passieren muss. Das hast
du wohl nicht ganz gerafft...
> Also kannst du auch kein Startbit ausmessen.
Kann man zwar, ist aber bei hohen Bitraten und relativ dazu geringem
Takt tatsächlich nicht hinreichend genau (und obendrein sehr anfällig
gegen Störungen). Deswegen würde das natürlich auch niemand mit gesundem
Menschenverstand und grundlegenden mathematischen Fähigkeit so machen...
> Beim Tiny2/4/861 hast du die Möglichkeit, den DI/SDA-Pin> des Slaves in der Abgleichphase als INT1-Pin zu nutzen.> Sendet der Master auf seinem Out-Pin ein Abgleich-Bitmuster,> wie 0b00000001 (ohne Pause dazwischen!), könntest du über die> Messung des Abstands der positiven, oder negativen Flanke am> INT1-Pin des Slaves die Messung schon 8 mal genauer machen.
Das ist nur eine Möglichkeit von sehr vielen. Letztlich beruhen alle
vernünftigen Lösungen darauf, dass man bei im Vergleich zum Takt hohen
Bitraten mehr als nur ein Bit vermessen muss, um eine hinreichende
Genauigkeit zu erzielen. Das ist trivial. Man muss wirklich kein
Mathematiker sein, um das erkennen zu können...
Der eigentliche Trick steckt halt im Protokoll. Nachdem ausgehandelt
ist, wer Master und wer Slave sein soll, muss halt der Master dem Slave
hinreichend lange ein hinreichend gut zur Messung geeignetes Muster
senden. Das war's.
Der eigentlichen Knackpunkt ist und bleibt: Der Aushandlung der Rollen.
Wie soll das Protokoll unter der Bedingung eine nicht funktionsfähigen
seriellen Verbindung ablaufen und wie genau wird bestimmt, wer Master
und wer Slave sein soll. Und letztlich: wie minimiert man die Zeit für
dieses Protokoll. Denn es ist ja nur ein Helper für die eigentliche
Aufgabe der Installation.
Die Minimierung der Zeit für den Ablauf des Protokolls wird vor allem
dann wichtig, wenn man auch zur Laufzeit ständig damit rechnen muss, das
Kommunikationsteilnehmer "aus dem Takt geraten". Dann muss man nämlich
diese Protokoll erneut starten.
Das ist z.B. immer dann der Fall, wenn die Teilnehmer
RC-Oszillor-getrieben sind und ihre Temperatur sich nennenswert ändern
kann...
Hallo,
der Master ist bei mir immer der Gleiche.
Spätere Wiederholung wegen Temperaturschwankungen sollten beim ATtiny841
eigentlich keine Rolle spielen. Das macht es für mich erstmal einfacher.
Kann man später vielleicht noch einbauen. Jetzt erstmal nicht.
Der Code auf dem Master für erstmal einmalige Sync-Protokol Übertragung
ist fertig. 1ms High, 1ms Low zur Erkennung das es jetzt los geht, dann
folgen 20 Takte mit 100kHz. Wenn der Slave dann wie gewünscht darauf
reagiert, wird es mehrfach wiederholt.
Jetzt muß ich den Slave ATtiny841 programmieren.
Dazu muß ich nun doch zwischendurch eine Frage stellen.
Gehe ich richtig mit der Annahme das ich folgende Register setzen muß,
wenn ich den RxD0 Pin auf steigende Flanke zählen einstellen möchte?
1
PCMSK0=(1<<PCINT2);// pin change mask für RxD0 Pin
Hallo,
das mit dem rising edge trifft wohl nur für "External Interrupt Request
0" INT0 zu. ATtiny841
Ich kann für RxD0 nur setzen
1
PCMSK0=(1<<PCINT2);// RxD0 Pin Interrupt enable
2
GIMSK=(1<<PCIE0);// pin change interrupt group enable
und Interrupt Handler PCINT0_ISR auswerten.
In dem Fall kann ich einfach alle Flankenänderungen zählen.
Wie könnte ich die steigende/fallende Flanken detektieren?
Ich wiederhole mich: mit Manchester wärst du schon lange fertig mit der
ganzen Kacke. Gibts als fertigen Code und funktioniert. Aber ne,
theoretisch ist es ja möglich mit Oszillator nachziehen. Naja - nicht so
einfach, aber muss ja gehen...
Kommt drauf an, ob du den DEFAULT-, oder den ALTERNATIVE-
RXD0-Eingang benutzen willst.
PA2 = Default-RXD0 kann auf PCINT2 konfiguriert werden,
PB2 = Alternative-RXD0 kann auf PCINT10 konfiguriert werden.
Mit dem Tiny841 hab ich noch nix gemacht, aber bei den mir bekannten
Tinys führt JEDE Flanke zum PCINT-Interrupt. Die Richtung muss man
in der ISR durch Abfrage des nun vorhandenen Logik-Pegels bestimmen.
Jetzt Hi: Es war eine positive Flanke.
Übrigens:
Wenn man per PCINTx Manchester-Code auwerten will, hat man das
gleiche Problem. ;-)
Hallo,
@Joachim:
meinst du das aus Application Node 9164?
Sieht sehr sehr umfangreich aus der ganze Code und überblicke ich eh
erstmal nicht. Müßte mich auch da wieder reindenken usw. und lenkt mich
aktuell von meinem ab. Aber gute Idee, zugegeben.
Selbst den Ansatz den ich verfolge hättet ihr in paar Stunden fertig,
denke ich. Ich muß viel im Datenblatt lesen, Register und Bits
raussuchen usw. Am Ende generiere ich auch einen Takt zum auswerten.
Wichtig für mich ist, dass ich meinen eigenen Code verstehe. Wenn etwas
nicht klappt oder angepaßt werden muß kenne ich den Code. Würde ich als
wichtig betrachten.
@ Jakob:
Pegelauswertung in der ISR ist ein gutes Stichwort. Danke. Merke ich
mir.
Wegen der Alternative. Alle PCINTx Pins reagieren auf alle
Pegeländerungen. Nur die INTx Pins kann man genauer konfigurieren. Der
ATtiny841 hat nur einen davon, INT0 an PB1. Aber gut, benötige ich jetzt
nicht unbedingt wie ich das aktuell sehe.
Ich mach heute mal weiter ...
INT0 an PB1 wäre ein verschwendeter Pin, wenn der Serial In
PA2 (PB2), oder PA4 ist.
Dass die Manchester-Codierung/Decodierung auch nicht ganz ohne
Aufwand zu machen ist, hast du richtig gesehen.
Die AN 9164 geht dabei von bekanntem "data rate clock" aus,
was du ja gerade nicht hast...
Eine Software-UART ist nur WENIG aufwändiger.
So sehr ich viele schlaue Beiträge vom c-hater schätze -
hier hat er sich nach meiner (nicht maßgeblichen) Meinung
etwas festgebissen.
LANGSAM möchte man aber Erfolgsmeldungen hören!
Es ist machbar!
Veit D. schrieb:> seines OSCCCAL ...
Warum eigentlich OSCCCAL? Man kann doch auch das Baudrateregister
passend setzen und OSCCCAL lassen, wie es ist.
MfG Klaus
Hallo,
die Slave Erkennungssequence hatte ich erstmal auf dem ATmega2560
geschrieben. Master und Slave vertauscht. Funktioniert. Fiel mir
irgendwie leichter, weil ich den schon länger habe. Jetzt sollte es
möglich sein das auf den ATtiny zu übertragen. Das zum Thema halbe
"Erfolgsmeldung". :-)
Hallo,
es läuft erstmal halbwegs auf dem ATtiny841.
Eine böse Falle waren die Namen der Interrupt Vectoren.
Im Datenblatt stehen die falsch drin. Das dazu.
Bsp. "TIM2_COMPA" statt "TIMER2_COMPA", Seite 49, 50
Die gesamte Erkennungs Sequence funktioniert damit einmalig.
Jetzt muß ich eine Wiederholung einbauen.
Was mich aber jetzt schon wundert ist, wenn ich den Timer 2 nicht stoppe
(im ISR(PCINT0_vect) Interrupt Handler), dann müßte doch der Compare
Match ISR zuschlagen und meine 3. Led leuchten. Die leuchtet aber nicht.
Warum weiß ich noch nicht. Vielleicht ihr?
Ablauf:
Vom Master steht TxD0 auf High nach Reset, dann für 1,5ms auf LOW und
dann für 1,5ms wieder auf HIGH, danach folgen 20 Takte mit am Ende
wieder auf HIGH.
Nach Low/High Wechel-Längenerkennung leuchtet LED_0.
Wenn die 20 Takte erkannt wurden leuchtet LED_1.
LED_2 soll nur leuchten wenn etwas schief ging, zu lange dauert und
damit der Overflow ISR zuschlägt.
Veit D. schrieb:> Eine böse Falle waren die Namen der Interrupt Vectoren.> Im Datenblatt stehen die falsch drin. Das dazu.> Bsp. "TIM2_COMPA" statt "TIMER2_COMPA", Seite 49, 50
Vorsicht, du musst hier das Datenblatt genau lesen. Das Codebeispiel auf
Seite 50 definiert ja die Labels entsprechend sodass es wieder passt ;)
Als Hobby sollte man sich den naechst Groesseren goennen, der eine
richtige UART, hinreichend Pins und Quarz besizt goennen. Ein Mega 644
kostet weniger als 5 euro. Wegen den paar Euros den Aufstand ?
Hallo,
auf Seite 50 stehen Code Bsp., okay.
Aber auf Seite 49 in der Tabelle "Interrupt Vectors" sollten doch die
Namen so stehen wie man sie schreiben muß. Plus den Zusatz _vect.
Im Datenblatt vom ATmega2560 steht z.Bsp. in der Tabelle "TIMER2_COMPA".
Deswegen war ich verwirrt und mußte in der Definitionsdatei nachschauen.
Ich dachte wenn ich das Datenblatt von Atmel habe und die Software von
Atmel, dann muß man das so schreiben wie im Datenblatt angegeben?
Und das Code Bsp. von Seite 50 sollte ja das wiedergeben was in der
Definitionsdatei drin steht. Meine ich. Wo hättest du nachgeschaut, wenn
du merkst, dass "TIM2_COMPA_vect" falsch ist. Beim ATtiny841.
Wir müssen aber nicht unbedingt wegen der Kleinigkeit diskutieren. :-)
@ oh doch:
Du hast leider nicht gelesen worum es geht.
Hallo,
seit zwei Wochen bin ich wieder am Thema.
Der ATtiny bekommt von einem anderen 16MHz µC mit jeden Tastendruck 100
Takte über die serielle geliefert. Das wird mittels einer for Schleife
und 20x 'U' gemacht mit einer Baudrate von 50k. Was 25kHz entspricht.
Der ATtiny wertet die Low Pegel aus. Wenn er das erste Low erkennt, wird
der Timer 2 gestartet. Nach 100 erkannten Low Pegeln stoppt der Timer.
Der TCNT2 Count wird ausgewertet. Idealerweise müsste er bis 32000
zählen.
Ich habe eine Toleranz von +/- 60 eingebaut.
Ist der Zählerstand größer 32060 taktet der ATtiny zu schnell, OSCCAL--.
Ist der Zählerstand kleiner 31940, taktet der ATtiny zu langsam,
OSCCAL++.
Obwohl die Sache erstmal funktioniert, bin ich noch nicht zufrieden.
Er kalibriert mir immer etwas daneben.
Auf beiden µC lasse ich einen Kontrolltakt von 10kHz erzeugen mittels
Timer. Am Oszi messe ich vom Taktgeber perfekte 10kHz.
Der ATtiny stellt sich am Ende auf 10,1kHz ein.
Sein OSCCAL steht dann auf 37.
1
T[µs] TCNT2 OSCCAL
2
102,4 30946 30
3
101,8 31130 31
4
101,4 31259 32
5
101,0 31306 33
6
100,4 31524 34
7
100,0 31667 35
8
99,6 31797 36
9
99,2 31927 37
10
98,8 32074 38
11
99,2 31936 37
12
98,8 32088 38
13
99,2 31950 37
Eigentlich müsste er einen OSCCAL von 35 finden. Allerdings ist da der
TCNT2 Wert weit weg.
Den Takt mit manuell vergebenen OSCCAL hatte ich vorher einmal
ausgemessen.
1
Cal MHz kHz % TCNT2 diff
2
41 8,20 10,20 2,50 32800
3
40 8,16 10,20 2,00 32640 160
4
39 8,12 10,20 1,50 32480 160
5
38 8,10 10,10 1,25 32400 80
6
37 8,06 10,10 0,75 32240 160
7
36 8,02 10,00 0,25 32080 160
8
35 8,00 9,98 0,00 32000 80
9
34 7,96 9,94 0,50 31840 160
10
33 7,94 9,90 -0,75 31760 80
11
32 7,90 9,86 -1,25 31600 160
TCNT2 sind berechnet: xMHz / 25kHz * 100 = TCNT2
(die 100 sind meine gezählten Low-Pegel.
Warum findet er sich bei 10kHz nicht wieder?
Warum liegt der TCNT2 daneben?
Liegt das am Code oder habe ich das falsch umgesetzt?
1
#define F_CPU 8000000UL // Systemtakt in Hz
2
3
#include<avr/io.h>
4
#include<stdio.h>
5
#include<stdlib.h>
6
#include<avr/interrupt.h>
7
#include<util/atomic.h> // für cli() und sei() mit SREG Sicherung
8
#include<util/delay.h>
9
10
#ifndef sbi
11
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // setzt das angegebene Bit auf 1
12
#endif
13
#ifndef cbi
14
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // setzt (löscht) das angegebene Bit auf 0
15
#endif
16
17
/*
18
UART Berechnungen des Wertes für das Baudratenregister aus Taktrate und gewünschter Baudrate
Edit:
den Takt der Baudrate habe ich soeben kontrolliert, sind exakt 25kHz.
Hätte mich auch gewundert bei dem glatten Teilerfaktor wenn das anders
wäre.
Veit D. schrieb:> Er kalibriert mir immer etwas daneben.
Das ist völlig normal. Die Auflösung des Stellgliedes (OSCCAL) ist
einfach nicht sehr hoch. Es wäre reiner Zufall, wenn sich ein exakter
Treffer ergäben würde.
> Der ATtiny stellt sich am Ende auf 10,1kHz ein.
Das sind 1%. Viel besser geht's eben wegen der begrenzten Auflösung von
OSCCAL sowieso nicht.
> Ich habe eine Toleranz von +/- 60 eingebaut.
Das allein sind schon 0,2%.
Der Rest dürfte in den Latenzen deines Programms stecken und der
Nichtberücksichtigung der dynamischen Eigenschaften von OSCCAL. Es ist
nämlich nicht so, dass eine Änderung des Wertes darin quasi instantan
die Frequenz des Oszillators ändert. Das dauert eine gewisse Zeit.
Hallo,
mich wundert eben dass ich bei meinen statischen Messungen andere Werte
bekommen habe wie jetzt mit der automatischen Kalibrierung. Wieviel ms
benötigt denn der µC nach Änderung am OSCCAL um stabil zu laufen? Ich
meine wenn ich messe bleiben zum Bsp. die 10,1kHz absolut stabil. Da
ändert sich auch Sekunden später nichts. Wenn ich dich richtig verstehe
geht etwas schief sobald er zum nächsten OSCCAL umschaltet, weil er
quasi sofort wieder den Takt messen tut. Ich müsste demzufolge ein delay
einbauen nach OSCCAL Änderung?
Würde aktuell betrachtet bedeuten, wenn ich nach der ersten
Kalibrierrunde noch eine starte, müßte sich nochmal was ändern?
Im Datenblatt lese ich nur das man den OSCCAL nicht um mehr als 2%
verstellen darf von Änderung zu Änderung. Also ich darf nicht von
default 41 direkt auf 35 gehen.
Was kann ich wegen den Latenzen im Code verbessern?
Paar Statusvariablen kommen noch raus, sind nur zum testen und debuggen
soviele drin. Im Grund geht es doch nur darum den Timer exakt zu starten
und exakt zu stoppen. Der Rest sollte nebensächlich sein.
Die Ausgabefrequenz ist in der Frequenzschrittweite durch die
Koernigkeit der Ansteuerung begrenzt.
Allenfalls kann man laenger messen, und allenfalls kann man das
Nachstellen als langsamer Prozess nebenbei mitlaufen lassen. zB einmal
alle Minute.
Hallo,
Moment. Derzeit gebe noch manuell eine neue Taktsequence raus per
Tastendruck vom Taktgeber (Master). Das heißt, der ATtiny hat nach
OSCCAL Änderung genügend Zeit sich zu stabilisieren.
Der Ablauf ist wie folgt.
- der ATtiny empfängt die 100 Takte
- wertet diese an Hand vom TCNT Counter aus und ändert darauf sofort
den OSCCAL und wartet wieder auf neue 100 Takte, Zeit zum
stabilisieren
- außer die Auswertung vom TCNT Counter liegt im Limit,
dann wartet er nicht mehr und meldet "fertig".
Scheinbar drehen sich meine Gedanken im Kreis. Jedoch hatte ich den
ATtiny vorher wie gesagt mit verschiedenen OSCCAL ausgemessen.
Demzufolge sollte er doch einen Wert von 35 oder 36 finden und nicht 37
oder 38.
Wo liegt mein Denkfehler?
Hallo,
während ich tippte kam deine Antwort. Ich hatte vor das sich beim
einschalten aller µC die ATtinys am Bus kalibrieren der Reihe nach. Da
diese keine Temperaturschwankungen ausgesetzt sind, wollte ich es
erstmal bei der einen Einschalt-Kalibrierung belassen. Zwischendurch
wäre nur erstmal eine Option.
Wegen der Genaugikeit. Das ist ja gerade das verrückte. Ich weiß ja das
er mit 35 oder 36 genauer takten könnte, aber er bekommt das alleine
nicht hin.
Ich könnte den Zählumfang erhöhen, also größer 32000.
Mit Ansteuerung meinst du den PCINT oder den OSCCAL?
Edit:
Wieviel % Taktabweichung der UARTs sind denn überhaupt tolerierbar?
Ziel ist es mit 250k zu kommunizieren.
Hallo,
Zählumfang erhöhen brachte keine Besserung.
Mit dem Code von oben und ohne künstliche Vorabverstellung des OSCCAL,
ist der OSCCAL default nach Reset erstmal zu hoch und muss runter.
Ergibt:
1
TCNT2 OSCCAL
2
32453 41
3
32284 40
4
32142 39
5
32014 38
Jetzt habe ich den ISR Code geändert auf (gekürzt):
1
ISR(PCINT0_vect)// Interrupt Handler PCINT0
2
{
3
staticunsignedintCounter=0;
4
5
if(state_Cal==READY){
6
TCCR2B|=(1<<CS20);// Timer 2 starten mit Prescaler 1
7
state_Cal=RUNNING;
8
}
9
10
Counter++;
11
12
if(Counter>199){// 200 Pegelwechsel
13
TCCR2B&=~(1<<CS20);// Timer stoppen
14
state_Cal=OKAY;
15
Counter=0;
16
}
17
}
ergibt:
1
TCNT2 OSCCAL
2
32620 41
3
32475 40 145
4
32330 39 145
5
32185 38 145
6
32061 37 124
7
32188 38 -127
8
32052 37 136
9
32192 38 -140
10
32046 37 146
11
32193 38 -147
12
32038 37 155
Der Timer zählt plötzlich ca. 200 Counts höher wie vorher. Was mir nicht
klar ist, warum zählt er dadurch höher und nicht niedriger, wenn er
schneller durch die ISR kommt?
Kostet der Vergleich wirklich 200 Takte?
1
if((~reg&0b00000100)&(1<<PINA2)){// prüft ob Pin Bit.2 Low
2
Counter++;
3
PulsCounter=Counter;
4
}
Danach habe ich die Verzögerung zum Timer stoppen verkürzt.
1
ISR(PCINT0_vect)// Interrupt Handler PCINT0
2
{
3
staticunsignedintCounter=0;
4
5
if(state_Cal==READY){
6
TCCR2B|=(1<<CS20);// Timer 2 starten mit Prescaler 1
Hier ein paar weitere mögliche Fehlerquellen:
1. Du erzeugst den Takt per UART. Die Bits innerhalb eines Bytes sind da
immer gleich lang, aber ist auch sichergestellt, daß zwischen dem
Stop-Bit eines und dem Start-Bit des nächsten Bytes nicht etwas mehr
Zeit vergeht, als die Länge eines Bits?
2. Du startest und stoppst den Timer in Software. Das ist mit
systematischen Ungenauigkeiten verbunden. Besser wäre es, nur einen
einzigen Takt zu senden (z.B. ein Nullbyte) und dessen Länge per
Input-Capture in Hardware auszumessen.
3. Ich würde die 60 Takte Toleranz weglassen. Kalibriere auf den Wert,
der die geringste Abweichung vom Sollwert hat.
Veit D. schrieb:> Zählumfang erhöhen brachte keine Besserung.
Array of uint16_t [99] anlegen oder malloc(100 * sizeof(uint16_t)).
TCNT2 in Normal Mode.
In PCINT0_ISR nur TCNT2 ins Array reinschreiben und Pointer ++
Wenn Pointer > 99 Auswerteroutine aufrufen.
Erst in der Auswerteroutine werden die Überläufe berücksichtigt und
die Abstände berechnet.
Wert in Array[0] wird nur als Anfangswert benutzt, deswegen wird in
der ISR auch nur auf Pointer > 99 geprüft und sonst nichts.
Fehler ist damit max. +/- 1 Takt.
P.S.
Selbstverständlich ist das alles unnötig. Die Tinys sind vom Werk
schon ausreichend genau. Die Temperatur- und Spannungsabweichungen
sind dein eigentliches Problem.
Marc V. schrieb:> Die Temperatur- und Spannungsabweichungen> sind dein eigentliches Problem.
sehe ich auch so und es ist ein Unterschied ob es eine echter Kaltstart
nach Power ON ist oder ein Warmstart nach Reset!
Das könnte ja noch in der Selbstkalibration eingebaut werden.
Hallo,
ganz ehrlich, ich kann zwar lesen was ihr mir sagen wollt, aber warum
verstehe ich nicht wirklich.
Momentan inkrementiere ich in der PCINT0 ISR nur einen Counter. Der
zählt die Pegelwechsel. Und nun soll ich statt dessen jedesmal den
Timercounter in ein Array schreiben? Dauert doch viel länger als jetzt.
Was soll ich mit 100 Timercounterwerten anfangen?
Genauigkeit +/- ein einzigen Takt? Wirklich?
Da würde es doch ausreichen die Überläufe zu zählen und dazu den letzten
Stand des Timercounters zur Gesamtberechnung. Nur wie lange soll den
gemessen werden wenn du von Überläufen redest?
Bei 100 Überläufen würde das alles ca. 800ms dauern für eine Messung.
Aktuell messe ich die Zeit in Timercounts, die vergeht bis 100 Low-Pegel
bzw. 200 Pegelwechsel vorbei sind. Alles innerhalb von 8ms, also
innerhalb eines möglichen Überlaufs.
Die Spannung ist stabil und es ist Zimmertemperatur. Der Effekt tritt
auch auf wenn der ATtiny schon paar Stunden unter Spannung steht. Das
ein absoluter Kaltstart und ein erwärmter ATTiny Unterschiede machen ist
mir bewusst, kann ich später einbauen mit Nachkalibrierung. Nur erstmal
sollte ich verstehen was jetzt falsch läuft.
Die PCINT0 ISR wird doch im Grunde sofort aufgerufen, der Counter++ und
später unmittelbar der Timer gestoppt.
Oder wollt ihr mir sagen das meine Messung um Größenordnungen viel zu
kurz ist? Nur dann wären ja solche Aussagen wie, ich messe einen Frame
während der Übertragung aus um Größenordnungen zu kurz und zu ungenau.
Manche wollen nur das Startbit ausmessen. Wäre noch ungenauer. Deswegen
dachte ich meine ca. 4ms wären schon übertrieben lang.
R.Max.:
ob die Stopbits gleich lang sind kann ich mal ausmessen bzw. mir
anschauen.
Ein einziger Takt? Ist das nicht zu ungenau? Die Toleranz kann ich nicht
weglassen. Den Zielwert trifft man nie genau, ich kann 1000 Messungen
mit unveränderten OSCCAL machen, es gibt immer Schwankungen.
Hallo,
habe die High und Low Pegel zeitlich angeschaut. Liegt zwischen 20µs und
19,96µs. Mal die eine mal die andere, wird an der Messungenauigkeit vom
Oszi liegen, nehme ich. Also von daher würde ich sagen, dass alle Bits
gleich lang sind.
Wegen der Werkskalibrierung. Ja die ist genau. Aber nur gültig für 3,3V.
Ich betreibe den mit 5V, weshalb er mit 8,2MHz taktet.
Hallo,
nach x-mal lesen ...
Kann es sein das du Marc, mit der mehrfachen und längeren Messung die
Messschwankungen der einzelnen TCNT Messungen ausgleichst?
Ich weis zwar noch immer nicht was du mit den gespeicherten TCNT
Einzelwerten machst, klingt aber für mich so, also könnte ich den
Gesamtwert des TCNT inkl. Überläufen durch die Anzahl der Messungen
teilen und eleminiere damit zu einem Großteil dessen Einzelschwankungen.
Meinst du sowas in der Art?
Veit D. schrieb:> Kann es sein das du Marc, mit der mehrfachen und längeren Messung die> Messschwankungen der einzelnen TCNT Messungen ausgleichst?
Unter anderem.
> Ich weis zwar noch immer nicht was du mit den gespeicherten TCNT> Einzelwerten machst, klingt aber für mich so, also könnte ich den> Gesamtwert des TCNT inkl. Überläufen durch die Anzahl der Messungen> teilen und eleminiere damit zu einem Großteil dessen Einzelschwankungen.> Meinst du sowas in der Art?
Ja, ausserdem hast du eine Routine mit ausreichend Zeit um alles
genau zu vergleichen und zu prüfen, ev. Glitches zu eliminieren,
Min. und Max Dauer zu finden, usw.
Das alles kann man in Echtzeit nicht oder nicht ausreichend genau
machen.
Timer2 kann beliebig schnell bzw. langsam laufen, solange der nicht
in einer Halbperiode überläuft.
Timer2 Overflow ISR wird natürlich nicht benutzt, ev. wird die
Gesamtdauer oder die Zeitüberschreitung der Messung mit einem anderen
Timer kontrolliert.
P.S.
Veit D. schrieb:> Momentan inkrementiere ich in der PCINT0 ISR nur einen Counter. Der> zählt die Pegelwechsel. Und nun soll ich statt dessen jedesmal den> Timercounter in ein Array schreiben? Dauert doch viel länger als jetzt.
Uninteressant, solange es immer die selbe Dauer ist.
> Was soll ich mit 100 Timercounterwerten anfangen?
Prüfen, addieren, teilen, vergleichen...
> Genauigkeit +/- ein einzigen Takt? Wirklich?
Ja.
Hängt nur vom Befehl ab, in welchem der Interrupt zugeschlagen hat.
Hallo,
ich habe die Methode erstmal gelassen und die Anzahl der Messungen
verzehnfacht. Danach berechne ich die Gesamt Timercounts und teile durch
10.
Damit erhalte ich schon, aus meiner Sicht, sehr genaue und wiederholbare
Werte. Wenn ich das umstelle und runterbreche auf die Timercounts eines
UART Frames, dann wird es bestimmt noch genauer.
1
OSCCAL TCNT2 OSCCAL TCNT2 OSCCAL TCNT2
2
41 32822 41 32819 41 32820
3
40 32664 40 32673 40 32669
4
39 32522 39 32529 39 32527
5
38 32375 38 32372 38 32373
6
37 32231 37 32228 37 32230
7
36 32082 36 32081 36 32089
8
35 31941 35 31944 35 31947
9
36 32077 36 32087 36 32081
10
35 31943 35 31944 35 31938
11
36 32088 36 32080 36 32081
12
35 31949 35 31943 35 31943
13
36 32079 36 32083 36 32085
14
35 31945 35 31948 35 31945
15
36 32088 36 32090 36 32084
16
35 31942 35 31940 35 31939
17
36 32102 36 32109 36 32079
18
35 31943 35 31968 35 31946
19
36 32084 36 32081
20
35 31949 35 31945
21
36 32079 36 32082
1
OSCCAL min max delta mittel
2
36 32077 32109 32 32085
3
35 31938 31968 30 31945
Den Timer OVF nutze ich zur Zeit nach der derzeitigen Messmethode um ein
eventuelles Zählproblem abzufangen. Nach deiner Methode nicht notwendig.
Aktuell nutze ich den um die Überläufe zu zählen.
Wenn du die einzelnen Messwerte speicherst, kann es sein, dass du dann
irgendwelche Statistiken anwendest? Zum Bsp. die 5 größten und 5
kleinsten Werte verwirfst und nur mit dem Rest letztlich den Mittelwert
bildest? Das wäre aktuell meine Idee das umzusetzen.
Veit D. schrieb:> Wenn du die einzelnen Messwerte speicherst, kann es sein, dass du dann> irgendwelche Statistiken anwendest? Zum Bsp. die 5 größten und 5> kleinsten Werte verwirfst und nur mit dem Rest letztlich den Mittelwert> bildest? Das wäre aktuell meine Idee das umzusetzen.
ich würde auch eine Toleranzgrenze festlegen +-1% oder +-5% also nur den
Mittelwert der Werte nehmen die innerhalb der 95(99)% bis (101)105%
liegen und den Rest ignorieren.
Hallo,
Hab die Messung und Teilung umgestellt, sodass ich den Durchschnittswert
vom Timercounter eines UART-Frames bekomme über die Messzeit.
Punktlandung wäre 3200.
1
OSCCAL TCNT2
2
41 3280
3
40 3264
4
39 3251
5
38 3236
6
37 3221
7
36 3207
8
35 3192
9
36 3207
10
35 3192
11
36 3207
12
35 3193
13
36 3206
14
35 3192
15
36 3207
16
35 3193
17
36 3207
18
35 3193
19
36 3207
20
35 3193
21
36 3207
22
23
OSCCAL TCNT2
24
41 3280
25
40 3265
26
39 3250
27
38 3235
28
37 3221
29
36 3207
30
35 3193
31
36 3206
32
35 3192
33
36 3206
34
35 3192
35
36 3206
36
35 3192
37
36 3206
38
35 3191
39
36 3206
40
35 3192
41
36 3206
42
35 3192
43
36 3206
1
OSCCAL min max delta mittel
2
36 3206 3207 1 3207
3
35 3191 3193 2 3192
Das sieht schon alles perfekt aus. Wenn ich nun wie du alle Einzelwerte
aufaddiere und teile und dann korrekt runde, dann wäre das der krönende
Abschluss. Und man bräuchte wirklich keine Hysterese, welch ein Wunder.
Manches muss man erst probieren um es zu verstehen. :-)
Veit D. schrieb:> Das sieht schon alles perfekt aus. Wenn ich nun wie du alle Einzelwerte> aufaddiere und teile und dann korrekt runde, dann wäre das der krönende> Abschluss. Und man bräuchte wirklich keine Hysterese,
und wenn man das für den kalten Chip, kurz nach power on und für den
warmen Chip nach einiger Laufzeit macht ist man noch besser
Hallo,
genau. Das werde ich so machen. Dann gibts aller halben Stunde oder so
"eine Runde" Kalibrierung spendiert. :-)
Dann werde ich das mal weiter umsetzen. Ich hatte am Anfang nicht daran
geglaubt diese Meßgenaugikeit zu erhalten.
Ich danke euch allen erstmal an der Stelle für die sehr informative
Unterhaltung und den sehr guten Hinweisen zur Umsetzung. Prinzipielle
Ablaufpläne sind das eine, die Umsetzung mit höherer Genauigkeit das
andere. Bin einfach nur glücklich. :-)
Hallo,
nachdem das nun schon geschmeidig läuft mit Wiederholungsanforderung
senden, dann neue Takte zum einmessen empfangen usw. muss ich nochmal
fragen wie man das Kaltstartproblem angeht? Also wenn Master und ATtiny
frisch eingschalten werden. Dann kann der ATtiny keine Befehle senden,
würden eh nur verstümmelt ankommen ohne Wirkung. Jetzt fällt mir nur
ein, dann ich den ATtiny pauschal in den Empfangsmodus setze und der
Master leicht verzögert erstmal paar Salven Takte rausfeuert. Lieber
mehr als zu wenig, sodass der ATtiny die Chance sich zu kalibrieren.
Danach wird angenommen das er sich wenigstens soweit selbst kalibrieren
konnte, dass eine Kommunikation möglich ist, die der Master versteht,
eben weil der ATtiny µC Takt schon im brauchbaren Toleranzfenster der
UART liegt.
Geht man so ran?
Bis jetzt habe ich mir beholfen indem ich den OSCCAL zum Start um einen
Wert von Hand nach unten korrigiert habe, der Rest folgt automatisch.
Veit D. schrieb:> Geht man so ran?
Aha, jetzt bist du also doch schon bei dem Problem angelangt, auf das
ich dich bereits im 21. September letzten Jahres in diesem Thread
hingewiesen hatte.
Hättest du man gleich auf die Erwachsenen gehört...
Ich könn't mich totlachen, wenn's nicht so traurig wäre.
Hallo,
@ c Liebhaber:
Ich weiß nicht was es da zu lachen gibt. Das Problem war von Anfang an
klar. Jetzt ist die Kalibrierung selbst fertig. Und jetzt gehts nur noch
darum den Kaltstart sicher zugestalten. Ein Idee hatte ich geäußert.
Eine andere Idee kam als Antwort. Ich sehe jetzt nicht das Problem der
Unlösbarkeit.
Danke R.Max, ich überlege mir das mal in Ruhe. Weil ich habe später nur
noch eine einzige UART am ATtiny die ich umschalten muss zwischen
Zeichen senden/empfangen und der Kalibrierung.
Veit D. schrieb:> Danke R.Max, ich überlege mir das mal in Ruhe. Weil ich habe später nur> noch eine einzige UART am ATtiny die ich umschalten muss zwischen> Zeichen senden/empfangen und der Kalibrierung.
Um den Break auszulösen, mußt Du am Slave den UART nur kurzzeitig auf
eine deutlich langsamere Baudrate setzen und ein Nullbyte senden. Es
reicht ja, wenn Du das beim Kaltstart machst, solange der UART ohnehin
potentiell nicht für die Kommunikation zu gebrauchen ist. Für die
Anforderung einer Rekalibrierung im laufenden Betrieb kannst Du ja dann
dir reguläre Kommunikation verwenden.
Hallo,
mit Frame Error abfragen geht das für einen einzelnen.
Später sollen mehrere ATtiny an den seriellen RS485 Bus mit Max485.
Dabei dürfen die ATtinys nicht ungefragt senden.
Nur auf Anforderung vom Master.
Das heißt ich muss im Master die Logik einbauen mit Antwort Timeout.
Und der ATtiny muss im Notfall auf Modus "Kalibrierungsempfang"
zurückschalten.
Mein Plan ist aktuell folgender.
Beim Kaltstart werden mehrere Runden Kalibrierungstakte auf den Bus
gesendet, vom Master.
Danach fragt der Master alle ATtinys der Reihe nach ab auf "Finish"
Antwort. Ist eine "Repeat" Antwort dabei, gibt es einzelne
Kalibrierungstaktsequencen als Bonus auf den Bus, solange bis alle
Finish gemeldet haben.
Resetet man einen einzelnen ATtiny oder was auch immer, dann muss das
der Master in einem Antwort Timeout erkennen, weil nur Datenmüll
gesendet werden kann wenn der Takt nicht stimmt. Dann sendet der Master
wieder Kalibrierungstakte und alle sind wieder im Rennen.
Die ATtiny reagieren im Normalfall nur auf Anfragen wenn ihre Adresse im
Protokol enthalten ist.
Die ATtinys können ihre Temperatur messen und eine Kalibrierung
anfordern.
Der Master muss ständig aller Zeit x alle ATtinys abfragen ob sie noch
da sind.
Übersehe ich irgendwas?
Man lernt wegen 2 Pins mehr ganz schön viel dazu. :-)
Solange es der Ram/Flash hergibt für die Kalibrierung.