Hallo zusammen,
ich habe in einem Projekt, bei dem eine asynchrone Datenübertragung in
Software implementiert wurde, bislang den MEGA168-20MU mit dem internen
RC - Oscillator verwendet. Dass dies nicht die beste Kombination ist,
ist mir bewusst: Der Oscillator wurde aber beim Hochfahren der Software
kalibriert und die Ergebnisse waren passabel: ca. 4% der Datenpakete
waren beschädigt.
Jetzt wurde der MEGA168 durch den MEGA328 - MU ersetzt und plötzlich hat
sich die Fehlerrate ca. verfünffacht. Bis zu 20% der Datenpakete gehen
verloren. Ich habe auch den Kalibrierungscode modifiziert, um andere
OSCCAL Werte zu erhalten und das Ergebnis wurde noch schlechter.
Es handelt sich auch nicht um einen Einzelfall, sondern zu einer
massiven Tendenz.
Hat jemand Ideen?
P.S.:
"warum nimmste keinen Quartz?" -> "Ist aus Platzgründen nicht möglich!
War außerdem bislang auch nicht notwendig"
"Bemüh mal die Suchfunktion!" -> "Habe ich: Kein vergleichbares Problem
gefunden"
"RTFM" -> "Habe ich auch, inkl. Migration Note: Hier gibt es
Unterschiede in den Quartzpin - Kapazitäten; sollte beim internen RC -
Osci nicht relevant sein.
Ist es ein 328 oder ein 328p? Wenn es ein 328 ist, probiere mal einen
328p (neuerer Fertigungsprozess) aus.
Welche Betriebsspannung?
PS: Dass für einen 3mm*2.5mm SMD Quarz plus zwei 0402 Kondensatoren
nicht noch irgendwo Platz ist, kann mir niemand erzählen.
fchk
Frank K. schrieb:> Welche Betriebsspannung?
Da würde ich auch das Problem vermuten.
Für die Spannung, für die die Kalibrierungsdaten ab Werk vorgesehen
sind, lässt sich eine asynchrone serielle Übertragung (die ja schon
garantiert mit 2 % Fehler klarkommt) normalerweise brauchbar
benutzen.
Wenn man aber von den 5 V abweicht, dann ist es halt Zufall, inwiefern
die Daten noch passen. Das Minimum wäre dann wohl das Hinterlegen
eigener Kalibrierdaten im EEPROM, die man während der Board-Tests
ermittelt. Besser noch wäre eine Kalibrierung zur Laufzeit. Kann
man beispielsweise beim ersten einlaufenden Zeichen von der
Gegenseite machen (so ähnlich, wie die Modems ihre Baudrate auf das
"AT" angepasst haben, das vom Computer kam).
Im Datenblatt steht:
Factory Calibration: 8.0MHz 3V 25°C ±10%
3V als Referenz ist ja auch sinnvoll, da der Spannungsbereich ja von
1.8V bis 5.5V geht und 3V dabei einigermaßen in der Mitte des Bereiches
liegt.
fchk
Hallo zusammen,
ich verwende 5V und kalibriere zur Laufzeit!
Erstaunlich ist, dass wenn ich die Kalibrierungszeit erhöhe, immer
wieder Ausreißer sehe, die es eigentlich nicht geben dürfte.
Ich werde mal die Versorgungsspannung prüfen, ob die sauber ist.
Wolfgang schrieb:> Hallo zusammen,>> ich verwende 5V und kalibriere zur Laufzeit!>> Erstaunlich ist, dass wenn ich die Kalibrierungszeit erhöhe, immer> wieder Ausreißer sehe, die es eigentlich nicht geben dürfte.>> Ich werde mal die Versorgungsspannung prüfen, ob die sauber ist.
Gegen welche Zeitbasis kalibrierst du denn?
Gute Erfahrungen mit <1% habe ich mit Laufzeitkalibibrierung gegen 400€
bei 1200 Bit/s auf 7,3728MHz. Nicht ganz zufällig eine
Baudratenfrequenz.
'€' = 0x80. Ergibt 8 aufeinanderfolgende Nullen, die man mit Pinchange
am Tx-Pin und Timer1 sehr schön ausmessen kann. Vor allem bekommt man
eine hohe Auflösung des Messwertes. Danach kann man auf jede beliebige
Baudrate hochgehen.
> Ist es ein 328 oder ein 328p? Wenn es ein 328 ist, probiere mal einen> 328p (neuerer Fertigungsprozess) aus.
Die sind auf gleichem Niveau. Eigentlich müsste der 328 328A und der
328P 328PA heissen.
mfg.
Hallo zusammen,
ich kalibriere gegen das Startbit meines Protokolls. (ungefähr 5us lange
Low Phase)
Die 168A sind die "Guten". Hier habe ich bauteilabhängig zwischen 0 und
5% Ausfälle. Beides reproduzierbar. Es gibt 168er, die nie Datenpakete
verlieren und dann gibt es wieder welche, die immer so bei 5% liegen.
Die 328er liegen bedauerlicherweise immer bei ca. 20%
Erstaunlich ist aber, dass wenn ich OSCCAL händisch setze (JTAG ICE
mkII), ich das kalibrierte Ergebnis nur schlechter machen kann, was ja
eigentlich bedeuten würde, dass mein Code schon den optimalen OSSCAL
Wert findet!
Wolfgang schrieb:> Hallo zusammen,>> ich kalibriere gegen das Startbit meines Protokolls. (ungefähr 5us lange> Low Phase)
Viel zu kurz.
> Die 168A sind die "Guten". Hier habe ich bauteilabhängig zwischen 0 und> 5% Ausfälle. Beides reproduzierbar. Es gibt 168er, die nie Datenpakete> verlieren und dann gibt es wieder welche, die immer so bei 5% liegen.>> Die 328er liegen bedauerlicherweise immer bei ca. 20%> Erstaunlich ist aber, dass wenn ich OSCCAL händisch setze (JTAG ICE> mkII), ich das kalibrierte Ergebnis nur schlechter machen kann, was ja> eigentlich bedeuten würde, dass mein Code schon den optimalen OSSCAL> Wert findet!
Bei den 328P, die ich hier habe, liegt der Factory-Wert um und bei 0x8A.
Damit driftet man bei der Kalibrierung leicht in den Bereich <0x80. Das
Bit7 des OSCCAL bestimmt die Auflösung der Kalibrierwertes. Bei den
anderen Conrollern 168A/PA dito 88er liegt der Factory-Wert zw. 0xB0 und
0xCF. Damit "trifft" er dann im Bereich >0x80 und die Fehlerrate ist
geringer. Aber ich messe das auch in der Initialisierung des Controllers
ein. Da nehme ich mir dann auch die Zeit, das mit einer längeren 0 bzw.
gegen Timer2 mit Uhrenquarz einzumessen. Dann kann man auch den OSCCAl
einfach auf 0xFF setzen und ihn "runtertakten" lassen. Dann trifft er
immer bei OSCCAL > 0x80.
Der Wert der dabei unter gleichen Spannungsbedingungen ermittelt wird,
ergibt sich aber zuverlässig immer wieder. Die Temperatureinwirkung ist
geringer als die der Spannung. Zumindest zwischen ca. -18° und 22°.
Einer festen Kalibrierung steht eigentlich nichts entgegen. Gerade wenn
man auf Baudrate einstellt, ist der Fehler der grundsätzlich falschen
Baudrate schon mal raus.
mfg.
Also nachdem was das Datenblatt sagt ist das nicht ganz einfach, wobei
ich glaube dass es zwischen einem 168 und einem 328 keinen prinzipiellen
Unterschied geben sollte.
Punkt 1: der Frequenzbereich ist 7.3 - 8.1 MHz, d.h. nominell ist die
Mittenfrequenz (was man sicher hinkriegen können sollte) nicht 8 sondern
7.7 MHz
Punkt 2: siehe Doku zum Register OSCCAL, der Wert darin ist
"zweigeteilt" und stellt zwei überlappende Frequenzbereiche dar, wobei
Bit 7=0 den niedrigeren, Bit 7=1 den höheren Bereich angibt, aber 0x7F
eine höhere Frequenz gibt als 0x80 - aber 0xFF eine noch höhere...
D.h. man kann den Registerwert nicht als Integer mit Vorzeichen
behandeln und muss die Überlappung beachten.
Das ist der Punkt auf den ich als Ursache tippen würde.
Nimmst Du eine echte RS232?
Bei USB-RS232 Umsetzern ist mir aufgefallen, daß die Bitzeiten schon
einen sehr hohen Jitter haben. Vermutlich, weil sie kein Baudratenquarz
als Zeitbasis benutzen.
Thomas Eckmann schrieb:> Wolfgang schrieb:>> Hallo zusammen,>>>> ich kalibriere gegen das Startbit meines Protokolls. (ungefähr 5us lange>> Low Phase)> Viel zu kurz.
Das sehe ich auch so: 5 us / 125 ns = 2.5 %.
Jasch schrieb:> Punkt 1: der Frequenzbereich ist 7.3 - 8.1 MHz, d.h. nominell ist die> Mittenfrequenz (was man sicher hinkriegen können sollte) nicht 8 sondern> 7.7 MHz
Falsche Annahme.
Der Wert wird nur deshalb so angegeben, weil damit der garantierte
Bereich sowohl die Einstellbarkeit von 8,0 MHz als auch der
„Baudratenfrequenz“ 7,3728 MHz gewährleistet. Weitergehende Zusagen
will man einfach nicht machen.
Der typische Abstimmbereich des Oszillators steht im Datenblatt, aber
er ist halt nicht garantiert. Er umfasst etwa 4 bis 12 MHz.
Interessanterweise geht der Bereich beim ATmega168 offenbar höher
(etwa 14 MHz) als bei den anderen Familienmitgliedern.
Da Wolfgang den Oszillator ja selbst kalibriert, würde ich auch ein
Problem mit dem ‚Sprungverhalten‘ um den OSCCAL-Wert 0x80 herum
vermuten. Es ist nicht ganz einfach, für diese nicht-eineindeutige
Abbildung einen Algorithmus zu entwickeln, der unter allen Umständen
stabil ist (been there, done that).
Es gäbe da noch eine Notlösung:
Teile jedes zu versendende Byte in zwei Halbbytes und versende diese.
Beim Empfang ignorierst du immer die höherwertigen 4 Bits und baust aus
jeweils zwei Halbbytes wieder ein Byte zusammen.
Das Verfahren ist auch robust auch bei größeren Taktschwankungen.
Wenn du willst, kannst du Bit 4 (das 5. von rechts) als Kennzeichen
nutzen, ob das betreffende Halbbyte ein Low- oder ein High-Halbbyte ist.
Nochmal: bei 5 us und 8 MHz kann die Genauigkeit doch bestenfalls bei
2.5 % liegen, je nach Algorithmus wohl eher 5.0 oder gar 7.5 %.
Oder irre ich mich?
der alte Hanns schrieb:> bei 5 us und 8 MHz kann die Genauigkeit doch bestenfalls bei 2.5 %> liegen
Wenn man oft genug misst (mit verschiedenen Werten von OSCCAL), sollte
sich auch die Mitte des möglichen Bereichs finden lassen (und damit
eine bessere Genauigkeit als 2,5 %), aber es stimmt schon, das ist
ziemlich knapp alles.
Jörg Wunsch schrieb:> Wenn man oft genug misst
Damit wird dann aber das Messintervall ein Mehrfaches von 5 us.
Was heißt eigentlich 'Laufzeitkalibrierung' genau? Wird da ein
gleitender Mittelwert über mehrere Datenpakete gebildet? Oder immer nur
einmalig für das nachfolgende Datenpaket - dann stellt sich mir die
Frage, wie lange der Oszillator zum Einschwingen braucht.
Ich weiß nicht, ob es hier hilft, aber nur mal so als Idee:
LIN (www.lin-subbus.org) ist mit dem Ziel entworfen worden, dass die
Slaves keinen Quarz benötigen. LIN-Frames starten mit einem BREAK, d.h.
einem Low-Signal von mindestens 13 Bitlängen gefolgt von einem
Synchronbyte 0x55. Dieses Synchronbyte ist für die Bitratenermittlung
der Slaves gedacht.
Schau Dir das mal an, vielleicht findest Du ja einen LIN-Stack, wo Du
das abschauen kannst.
fchk
Ich würde auch sagen, der Fehler liegt bei der Autobauderkennung.
Kann man leicht prüfen.
Man generiert einen festen Ausgangstakt über die Output-Compare
Funktion. Damit kann man direkt und sehr einfach den CPU-Takt messen.
Oder über die Clock Out Fuse, wenn der AVR diese hat. Damit sieht man
das Ergebnis der Autobauderkennung und RD-Oszillatorkalibrierung.
Nun lässt man das Programm laufen und erzwingt definiert die Autobaud
Funktion. Wahrscheinlich sind die Ergebnisse der Frequenzmessung stark
fehlerbehaftet.
Als Gegenbeweis, dass der RC-Oszillator es besser kann, verstellt man
dessen Kalibrierung manuell. Damit kann man ihn auf <1% Fehler
abgleichen und der UART läuft stabil und fehlerfrei.
Ich hatte mal ein Projekt, wo nur ein 32k Uhrenquarz am Controller hing,
aber dennoch 115k2 per UART genutzt worden. Eine automatische
Kalibrierung per Timer war spielend leicht und immer exakt. Die
Kalibrierung lief dauerhaft, damit konnte man auch Temperaturdriften
kompensieren (hab ich aber nicht getestet).
Autobaud mit nur EINEM Zeichen sollte man mit möglichst geringer
Baudrate machen, um den systematischen Fehler zu senken. Das Ganze per
ICP macht es noch deutlich genauer, wenn gleich Polling per CPU zur Not
auch geht.
Wir hatten schon ziemlich alle Osccalwerte von h43 bis h95 (beim
Atmega164).
Als Übergangslösung bis alles auf Quarz umgestellt war haben wir die
Controller per Hand selektiert.Die bösen mit Oscalwerten unter h50
wurdenfür andere Projekte verwendet.
@ PeterL (Gast)
>Wir hatten schon ziemlich alle Osccalwerte von h43 bis h95 (beim>Atmega164).>Als Übergangslösung bis alles auf Quarz umgestellt war haben wir die>Controller per Hand selektiert.Die bösen mit Oscalwerten unter h50>wurdenfür andere Projekte verwendet.
Was ist an einem Wert unterhalb 0x50 böse? Eben WEIL kalibriert wird,
spielt der Fehler des RC-Oszillators keine Rolle!
Hallo zusammen,
vielen Dank für die vielen Gedanken und Vorschläge!
Was ich ausschließen kann, ist das "Rutschen" des OSCCAL Wertes unter
0x80. Ich habe mehrere 328er die dasselbe Verhalten zeigen. Einen davon
habe ich dann mit DebugWire konfiguriert und konnte sehen, dass OSCCAL
nach dem Reset 0x9C war. Der kalibrierte Wert lag dann immer bei 0x92 -
0x93.
Das mein Kalibrierungssignal mit 5us sehr kurz ist, ist mir bewusst,
jedoch musste die Kalibrierung in ein bestehendes System integriert
werden, ohne die Möglichkeit den Sender anzupassen. Es handelt sich
nicht um die UART, sondern um ein in Software abgebildetes Busprotokoll,
welches ca. 300kB macht. Das Referenzsignal wird von einem 328er mit
16MHz Quarz erzeugt. Das Protokoll hat eigentlich den Takt in die Daten
integriert, sprich es werden immer High Pulse variabler Länge, gefolgt
von einer Low Phase mit definierter Länge erzeugt. Die Länge des High
Pulses definiert ob eine "1" oder "0" übertragen wurde. Lediglich das
Startbit ist etwas länger, so dass alle Controller die Empfangsroutine
erreichen können und dieses wurde zum kalibrieren missbraucht.
Wie es scheint, liegt das Problem nicht an meinem Kalibrierungscode,
weil ich auch nicht fähig war manuell bessere Werte zu setzen.
Kann es sein, dass der Oscillator nicht stabil läuft?
Ich habe in Erinnerung, dass beim Verändern des OSCCAL Registers man
immer zwei Schritte vor und einen zurück machen soll, sonst kann es
passieren, dass der Controller, den einen Schritt nicht übernimmt.
(Steht in ner AppNote) Kann es sein, dass beim 328 hier noch etwas zu
beachten ist?
Ich werde heute noch verschiedene Typen von 168 und 328 bestellen und am
Wochenende testen. (habe mir Gott sei Dank letzte Woche einen Nullkraft
Sockel geleistet :-) )
>Ich werde heute noch verschiedene Typen von 168 und 328 bestellen und am>Wochenende testen.
Bestell gleich nochn paar Quarze mit. Für den ganzen Aufwand den du bis
jetzt betrieben hast hättest du vermutlich locker schon 1000Stück
kaufen können.
>Bitte die Anforderung, dass keine Quarze in Frage kommen, zu>akzeptieren.
Wenn es nicht geht, geht es nicht.
Bitte akzeptieren das eine Fehlentwicklung stattgefunden hat.
Wie viel Kohle willst du da noch reinstecken?
Wolfgang schrieb:> Das mein Kalibrierungssignal mit 5us sehr kurz ist, ist mir bewusst,> jedoch musste die Kalibrierung in ein bestehendes System integriert> werden, ohne die Möglichkeit den Sender anzupassen. Es handelt sich> nicht um die UART, sondern um ein in Software abgebildetes Busprotokoll,> welches ca. 300kB macht. Das Referenzsignal wird von einem 328er mit> 16MHz Quarz erzeugt. Das Protokoll hat eigentlich den Takt in die Daten> integriert, sprich es werden immer High Pulse variabler Länge, gefolgt> von einer Low Phase mit definierter Länge erzeugt. Die Länge des High> Pulses definiert ob eine "1" oder "0" übertragen wurde. Lediglich das> Startbit ist etwas länger, so dass alle Controller die Empfangsroutine> erreichen können und dieses wurde zum kalibrieren missbraucht.
Was heisst denn jetzt variable Länge? Von-bis und alles dazwischen?
Doch wohl jeweils definierte Länge für 0 und 1?
Dann verstehe ich allerdings nicht, warum du überhaupt kalibrierst. Den
Unterschied zwischen kurz und lang kann der Empfänger doch auch so
erkennen. Denn der oszillator läuft sehr stabil. Solange sich Spannung
und Temperatur nicht ständig drastisch ändern. Also nicht von heute auf
morgen sondern von jetzt auf gleich.
Es sei denn der Unterschied ist einfach zu gering. Aber dann hat man an
der PWM grundsätzlich was falsch gemacht. Oder dein Controller läuft mit
8MHz einfach zu langsam, sodaß der Unterschied zwischen 0 und 1 einfach
nicht signifikant genug ist. Daran würde ein 8MHz-Quarz dann aber auch
nichts ändern. Ein 20MHz-Quarz aber schon. Auch wenn es keine Option
ist. Aber wenn dem so ist, kann man nur Holgers letzter Aussage
zustimmen.
mfg.
Genau, es handelt sich um definierte Längen!
Der ursprüngliche Plan war natürlich, dass man keine Kalibrierung
benötigt. Da man mit 8MHz und 300kB/s in Software (gerade bei einem
Signal mit doppelter Bandbreite) schon recht am Limit ist, ist mir
bewusst.
Leider gab es ja immer wieder Probleme, die mit kalibrierten
Oszillatoren aber minimiert werden konnten. Mit dem 168er funktionierte
es ja wirklich gut! Einzig der 328er macht jetzt Probleme.
Das man mit ausreichender Hardware viele Probleme erschlagen kann, ist
klar. Ich hätte auch einen eigenen uC nur für die Kommunikation nehmen
können, dann hätte ich mir auch viele Probleme mit der
Interruptpriorisierung, Fehlererkennung und -korrektur sparen können,
aber die Anforderung war eben eine Singlechip Lösung aus genannten
Gründen. Ich muss diese Controller auf Platinen verbauen, die teilweise
unwesentlich größer sind als der Controller! Daran kann ich nichts
ändern! Ich musste bei einer Platine sogar die TVS Diode im SOT23-3
weglassen, weil ich meine Leiterbahnen nicht mehr unterbringen könnte.
Das ist nun mal eine harte Anforderung!
Die ursprüngliche Frage war ja: gibt es bekannte Unterschiede in den
Oszillatoren? Hat jemand ähnliche Erfahrungen und/oder Lösungen.
Wolfgang schrieb:> Die ursprüngliche Frage war ja: gibt es bekannte Unterschiede in den> Oszillatoren?
Offensichtlich, siehe die typischen Daten im Datenblatt. Der
Oszillator des '168 lässt sich typisch bis 14 MHz ziehen, die anderen
nur bis 12 MHz. Warum dieses Detail aber gerade in deinem Falle
entscheidend sein sollte, nun, das wirst du nur selbst messen können.
Falk hat ja schon Vorschläge gemacht (CKOUT abgreifen und messen).
Wolfgang schrieb:> Kann es sein, dass der Oscillator nicht stabil läuft?
Auch das solltest du messen können. Sicher, es ist ein RC-Oszillator,
insofern ist er zwangsläufig instabiler als ein Quarzoszillator.
Inwiefern nun seine Kurzzeitstabilität anders ist als bei den anderen
AVRs, das musst du ggf. einfach mal nachmessen. Oszilloskope sind
ja schon eine Weile erfunden, und seit sie digital sind, beherrschen
sie auch Features wie Persistenz.
Jörg Wunsch schrieb:> Jasch schrieb:>> Punkt 1: der Frequenzbereich ist 7.3 - 8.1 MHz, d.h. nominell ist die>> Mittenfrequenz (was man sicher hinkriegen können sollte) nicht 8 sondern>> 7.7 MHz>> Falsche Annahme.>> Der Wert wird nur deshalb so angegeben, weil damit der /garantierte/> Bereich sowohl die Einstellbarkeit von 8,0 MHz als auch der> „Baudratenfrequenz“ 7,3728 MHz gewährleistet. Weitergehende Zusagen> will man einfach nicht machen.
Naja, "garantiert" hat schon einen netten Klang...
> Der typische Abstimmbereich des Oszillators steht im Datenblatt, aber> er ist halt nicht garantiert. Er umfasst etwa 4 bis 12 MHz.> Interessanterweise geht der Bereich beim ATmega168 offenbar höher> (etwa 14 MHz) als bei den anderen Familienmitgliedern.
Interessant, das hatte ich garnicht gesehen, ist ja ein hübsch grosser
Bereich.
Vielleicht sind ja die 328 aus einer Charge die halt nicht so hoch
hinaus kommt wie "typisch" sein sollte?
Hi
> Der typische Abstimmbereich des Oszillators steht im Datenblatt, aber> er ist halt nicht garantiert. Er umfasst etwa 4 bis 12 MHz.> Interessanterweise geht der Bereich beim ATmega168 offenbar höher> (etwa 14 MHz) als bei den anderen Familienmitgliedern.
Hier werden teilweise Äpfel mit Birnen verglichen. Das Diagramm vom
ATMega328 stammt von einem P-Typ, das vom ATMega168 von einem PA-Typ.
Und das geht bis 14 MHz. Bei einem ATMega168P geht der Einstellbereich,
genau wie beim ATMega328P, auch nur bis 13 MHz.
MfG Spess
Wolfgang schrieb:> Das Protokoll hat eigentlich den Takt in die Daten> integriert, sprich es werden immer High Pulse variabler Länge, gefolgt> von einer Low Phase mit definierter Länge erzeugt. Die Länge des High> Pulses definiert ob eine "1" oder "0" übertragen wurde. Lediglich das> Startbit ist etwas länger, so dass alle Controller die Empfangsroutine> erreichen können und dieses wurde zum kalibrieren missbraucht.
Hm...
300kB mit Bitwert im high, und festem "low-Takt" ergibt bei 8MHz CPUtakt
im Mittel 13,3 Takte jedes high bzw. low. Also z.B 13 Takte low, 6,5
Takte für high_0, und 19,5 Takte für high_1. Ist das in etwa so?
Das per Software-Sampiling abzutasten, ist m.E. sportlich (ih bin aber
auch nur Diletant in dem Geschäft...). Ob der Oszillator dabei etwas
schneller oder langsamer läuft, spielt aber nur eine Rolle, wenn die
Unterschiede zwischen high_0 und high_1 entweder sehr klein gewählt
worden wären, oder man nicht zwischendurch mal auf eine der low-Flanken
synchronisiert.
Wie funktioniert denn die Dekodierung?
Wenn du mit festen Zyklen ohne Zwischensynchronisation abstatestest, ab
welcher Bitzahl bekommst du Bitfehler alleine aus der begrenzten
Genauigkeit der 5us-Kalibrierung?
Oliver
Oliver schrieb:> Ob der Oszillator dabei etwas> schneller oder langsamer läuft, spielt aber nur eine Rolle, wenn die> Unterschiede zwischen high_0 und high_1 entweder sehr klein gewählt> worden wären, oder man nicht zwischendurch mal auf eine der low-Flanken> synchronisiert.
Volle Zustimmung.
Man kann doch bei jedem einzelnen Bit auf die steigende Flanke
synchronisieren. Und dann sollten die wenigen Prozent einer Kalibrierung
keine Rolle spielen, der Werkswert für OSCCAL muss reichen.
Ich sehe das Problem in der Decodierung und in der Nachbearbeitung, da
ist bei insgesamt rund 27 Takten nicht viel Spielraum.
Prinzipiell aber ist das machbar, auch ohne die genannte Fehlerquote von
5 %.
Hallo zusammen,
ich habe nun verschiedene uC getestet und bin mittlerweile ziemlich
sicher, dass es nicht am Oscillator liegt! CKOUT zeigt recht genaue 8MHz
Werte.
Mittlerweile habe ich auch schon überlegt, ob der Code für die 32k
Variante buggy sein könnte, aber jetzt kommts: Mein Code mag auch auf
anderen 168er Variante (A,P,V) nicht so recht...
Unterschiedliche H/L Schwellwerte kann man ausschließen, da das Signal <
50ns Rise- und Falltime hat.
Bin mittlerweile echt ratlos...
Edit: Problem höchstwahrscheinlich gefunden: Der Oszillator beim
168-20MU scheint stabiler zu sein, als bei den anderen Varianten...
Ich bin fest überzeugt, dass Ihr Programm fehlerhaft ist, was auch die
für mich unerklärbare Fehlerquote bei den 168ern zeigt.
Ich hatte einen Probeaufbau zusammengesteckt, in Ermangelung von
ATmega328 nahm ich 2 ATmega644, wie von Ihnen vorgegeben der Sender mit
16 MHz Quarz, der Empfänger mit den internen 8 MHz. Statt Ihrer
variablen Bitlänge arbeitete ich mit einer festen:
'0': 500 ns high, 1125 ns low
'1': 1125 ns low, 500 ns high
Das ergibt eine reine bit-Rate von 615 kbit/s, mit einer
Byte-Aufbereitung kam ich auf 70 kByte/s.
Die Übertragung lief absolut fehlerfrei, und das, wohlgemerkt, bei einer
Frequenztoleranz von +/- 10 %, also im Bereich 7.2 - 8.8 MHz.
Fazit: nehmen Sie die unnötige Justierung ('Kalibrierung') von OSCCAL
heraus und triggern Sie bei jedem einzelnen bit auf die Startflanke.
Hallo Herr Hanns,
jetzt bin ich gerade beeindruckt, dass Sie wegen mir eine
Versuchsanordnung aufgebaut haben.
Ich triggere natürlich auf die steigende Flanke! Ich kann aber natürlich
auch nicht ausschließen, dass es noch irgendwo einen Fehler und einen
Störeinfluss gibt!
Was ich mich aber frage, wie Sie in 500ns einen Bitwert verarbeiten bzw.
das fertige Byte wegschreiben? Das sind immerhin nur mehr 4 cycles!
Ich werde mich kommendes Wochenende mit dem Code auseinandersetzen!
VG, Wolfgang
Nur als Denkanstoss, ohne weiteren Kommentar, vielleicht hilft es Ihnen
ja.
.def tmp3 = r14
.def tmp0 = r16
.def count = r24
.equ PIN_serialin =PIND
.equ serialin = 6
.macro bit
sbic PIN_serialin,serialin
rjmp pc-1
sbis PIN_serialin,serialin
rjmp pc-1
sbrc tmp0,serialin
inc tmp3
lsl tmp3
in tmp0,PIN_serialin
.endmacro
in_loop:
clr tmp3
bit
bit
bit
bit
bit
bit
bit
bit
sbrc tmp0,serialin
inc tmp3
st z+,tmp3
inc count
breq pc+2
rjmp in_loop
Wolfgang schrieb:> Was ich mich aber frage, wie Sie in 500ns einen Bitwert verarbeiten bzw.> das fertige Byte wegschreiben? Das sind immerhin nur mehr 4 cycles!
Für das Byte muss der Sender natürlich eine kurze Sendepause einlegen,
deshalb komme ich auch nur auf 70 kByte/s und nicht auf 76.9 = 615/8.
Wolfgang schrieb:> Aja, dann kann ich es nachvollziehen ... Und Sie haben 0% Fehler??
Es lief fehlerfrei mit etwas unter 7.2 und etwas über 8.8 MHz jeweils
eine Kaffeepause lang.
Ich wünsche Ihnen gutes Gelingen.
Hallo zusammen,
alter Hanns, dein Tipp war schon richtig!
Ich habe einen Fehler in Software gefunden! Zwar war mein Protokoll
sauber, es wurde richtig auf die Flanken getriggert und zum richtigen
Zeitpunkt abgetastet, ABER eine Konstellation aus verschiedenen
Altlasten hat mir einen Fehler erzeugt:
Ich schalte nach dem Empfangen den Empfänger über den Interrupt ab und
arbeite das Datenpaket ab. Sollte die Ausführungszeit mal nicht reichen,
zerstört mir ein neu hereinkommendes Datenpaket zumindest nicht das
aktuelle und die Daten bleiben (bis auf das verloren gegangene
Datenpaket) konsistent.
Die Funktion zum Einschalten des Empfängers löscht zuerst das Interrupt
Flag, um nicht fälschlicherweise (das Empfangen in Software setzt ja
auch das IF) den Empfänger zu starten und aktiviert danach den
Interrupt.
Da ein fehlerhaftes Datenpaket aber auch den Empfänger deaktiviert, aber
in weiterer Folge nicht abgearbeitet wird, habe ich in einer Quick &
Dirty Lösung damals meine "EnableReceiver" Funktion in einer Schleife
gebaut.
Was nun passiert ist, dass in einer Schleife >>dauernd das IF Flag
gelöscht<<, der Interrupt konfiguriert und aktiviert wird.
Meiner Interpretation nach kann das den Interrupt, wenn er zu einem
ungünstigen Zeitpunkt ausgelöst wird, unterdrücken.
Warum sich das auf verschiedenen Chip Typen anders verhält, weiß wohl
nur ATMEL, wundert mich jetzt aber auch nicht weiter...
Auf alle Fälle läuft mein Protokoll nun stabil (keine Fehler bei über
200k Datenpaketen)!!
Zum einen vielen Dank an "der alte Hanns", der mich zur richtigen Stelle
geführt und mich mittels eines eigens aufgebauten Testszenarios
überzeugt hat, das richtige zu tun.
Auch den anderen einen herzlichen Dank!
@Holger: es freut mich im Nachhinein, dass du nicht recht hattest...
ich finde das mit dem "Sie" sehr gut. Es verleiht der Unterhaltung ein
gewissen Niveau und zeugt von gegeseitigem Respekt. Ich werde das in
Zukunft ebenso "hannshaben".
Daumenhoch, viele Grüße
Axelr.
@ Axel R. (axelr)
>ich finde das mit dem "Sie" sehr gut. Es verleiht der Unterhaltung ein>gewissen Niveau und zeugt von gegeseitigem Respekt.
Biedermeierzeit reloaded?
Wolfgang schrieb:> Das Protokoll hat eigentlich den Takt in die Daten> integriert, sprich es werden immer High Pulse variabler Länge, gefolgt> von einer Low Phase mit definierter Länge erzeugt. Die Länge des High> Pulses definiert ob eine "1" oder "0" übertragen wurde.
Da ist tatsächlich der Takt redundant in den Daten enthalten. Warum zum
Teufel wird diese Eigenschaft dann nicht genutzt?
Täte man das, wäre die Taktrate komplett irrelevant, eine Kalibrierung
(zumindest für den Empfang) völlig überflüssig und damit dein ganzes
Problem überhaupt nicht existent.
Also die letzten beiden Kommentare wieder...
@Oliver? Wie erklärt sich nun der Unterschied zwischen den Chiptypen?
@c-hater: Hättest du den Thread gelesen, würdest du wissen, das dies
getan wird. Gab aber eben trotzdem Probleme, da die ganze Sache (steht
ebenfalls auch im Thread) schon recht sportlich ist!
Falk Brunner schrieb:> Das ist bei JEDER asynchronen Datenübertragung so . . .
Nein. Es gibt sehr viele asynchrone Verfahren, bei denen nur Teile des
Taktes im Signal stecken. Typisches Beispiel: RS232.
Und genau nur bei denen ergibt eine lokale Taktgenerierung und damit
verbundene Sachen wie eine Kalibrierung und Synchronisierung dieses
lokalen Taktes einen Sinn.
Bei Verfahren mit vollständigem Taktsignal hingegen nicht. Und das
beschriebene Protokoll ist ja geradezu ein Paradebeispiel für ein
solches Verfahren. Es gibt Verfahren, da ist das nicht ganz so
offensichtlich.
@c-hater (Gast)
>> Das ist bei JEDER asynchronen Datenübertragung so . . .>Nein. Es gibt sehr viele asynchrone Verfahren, bei denen nur Teile des>Taktes im Signal stecken. Typisches Beispiel: RS232.
Krümelkacker. Dass der Empfänger IMMER eine Taktrückgewinnung machen
muss, ist doch wohl klar. Ob er auf jedes Bit oder nur jedes Byte oder
noch größere Datenpakete synchronisieren kann, ist eine andere Frage.
>Und genau nur bei denen ergibt eine lokale Taktgenerierung
Nö, die gibt es immer, nur halt in verschiedenen Ausprägungen.
>Bei Verfahren mit vollständigem Taktsignal hingegen nicht.
Doch. Auch wenn es scheinbar schon da ist.
Wolfgang schrieb:> @Oliver? Wie erklärt sich nun der Unterschied zwischen den Chiptypen?
Keine Ahnung. Aber mit an Sicherheit grenzender Wahrscheinlichkeit ist
auch das ein Progarmmierfehler.
Oliver
Falk Brunner schrieb:> Doch. Auch wenn es scheinbar schon da ist.
Naja, irgendwie ist tatsächlich immer der Vergleich mit einem
"Referenztakt" erforderlich, auch wenn der Takt vollständig geliefert
wird, da hast du eindeutig Recht.
Ich korrigiere mich also dahingehend, daß die beschriebene Kalibrierung
unsinnig ist. DAS ergibt nur dann einen Sinn, wenn das Taktsignal der
Quelle nicht vollständig verfügbar ist und deshalb eine sozusagen
"freilaufende" Referenz benötigt wird.
Können wir uns darauf einigen?
@ c-hater (Gast)
>Naja, irgendwie ist tatsächlich immer der Vergleich mit einem>"Referenztakt" erforderlich, auch wenn der Takt vollständig geliefert>wird, da hast du eindeutig Recht.
AKA CDR, clock and data recovery.
>Ich korrigiere mich also dahingehend, daß die beschriebene Kalibrierung>unsinnig ist. DAS ergibt nur dann einen Sinn, wenn das Taktsignal der>Quelle nicht vollständig verfügbar ist und deshalb eine sozusagen>"freilaufende" Referenz benötigt wird.
Die wird immer benötigt, alles nur eine Frage der Kurzzeitstabilität.
Beim Manchestercode hat man nach jedem Bit eine Synchronmarke, bei UART
muss man 10 Bit kurzzeitstabil sein, beim good ole PAL muss es eine
Zeile a 64us stabil sein.
>Können wir uns darauf einigen?
OK.