Hallo zusammen,
nun habe auch ich das Problem, dass _delay_ms() nicht zum gewünschten
Ergebnis führt, allerdings in einer Größenordnung, welche ich hier per
Sufu, pardon, Suchfunktion in keinem anderen Beitrag gefunden habe.
Eine 60 Sekunden Zeitschleife läuft in nur etwa 51 Sekunden durch, dabei
ist es egal ob ich diese mit _delay_ms(1000) oder _delay_ms(100)
aufbaue. Das ganze läuft auf einem tiny861, interner OSC mit 8 MHz,
Kalibrierung habe ich gemacht und im Flash gespeichert (richtig gemacht
hoffe ich), Code Optimization ist eingeschaltet (-O3), F_CPU korrekt auf
800000UL gesetzt. Verwenden tue ich Studio 7.0, libc Version ist
1.8.0svn
Wenn ich F_CPU auf 940000UL setze, dann stimmt die Zeit in etwa. Das
könnte man jetzt auf diese Weise feintunen, aber das ist ja nicht Sinn
der Sache.
Jemand eine Idee woran es liegen könnte? Oder liegt die Genauigkeit des
internen OSC so weit daneben? Welchen Sinn erfüllt dann die
Kalibrierung?
Beste Grüße
Holger
Holger K. schrieb:> Oder liegt die Genauigkeit des internen OSC so weit daneben?> Welchen Sinn erfüllt dann die Kalibrierung?
Eine Kalibrierung stellt nur Messfehler fest, ohne irgendetwas daran zu
ändern.
https://de.wikipedia.org/wiki/Kalibrierung
Was meinst du mit "Kalibrierung"?
Holger K. schrieb:> Jemand eine Idee woran es liegen könnte?
Du musst den Wert in deinem Programm selber laden und ins richtige
Register schreiben.
Gruß
Flo
Sicher, dass die Fuses richtig gesetzt sind? Oftmals ist bei
fabriksneuen AVRs ein Prescaler vom Faktor 8 eingestellt, so dass der
Chip nur auf 1 MHz läuft; versuchs mal mit
Wow, so viel Input in so kurzer Zeit, Ihr seid klasse!
Also Wolfgang A. gemeint ist die OSC Calibration unter "Device
Programming"
Flo Das könnte gut möglich sein, ich bin davon ausgegangen das er das
alleine verwertet. Muß ich noch ein bisschen lesen, vorallen was der
Wert den er ausgibt, 0xB3 für eine Größe darstellt...
Matthias Sch. Mit -Os verhält er sich exakt genauso wie mit -O3
t15 Meinst Du CKDIV8? Ja die ist gesetzt. Wenn ich die rausmache läuft
meine Schleife statt in 51 Sekunden in nur Rund 5 Sekunden durch. Das
Display-Timing stimmt dann auch nicht mehr.
Schau dir doch erstmal den Wert beim fabrikfrischen
µC an. Und das Datenblatt.
Für 3,3 V Vcc werden +/-10% angegeben, das wären 54..66 s.
Bei 5 V kommt noch was dazu...
Der Abgleich mit OSCCAL bei konstanter Temperatur auf 1% ist
eine Variante. Bei veränderlicher Temperatur werden es aber
schnell 2%.
Will man es genauer haben, ist ein Piezo, oder Quarz
unumgänglich.
Ausnahme: Man KANN eine externe Referenz (z.B. sind mit 50 Hz
aus dem Stromnetz auch 0,1% möglich) auswerten und zum
Nachsteuern von OSCCAL nutzen.
Erfordert aber µC-Resourcen: Port-Pin, Timer, Interrupt,
Programm-Code und Gehirnschmalz.
Holger K. schrieb:> Flo Das könnte gut möglich sein, ich bin davon ausgegangen das er das> alleine verwertet
Tut er aber leider nicht. Du musst das Byte aus dem Flash laden und dann
ins OSCCAL Register schreiben.
Dann klappt das auch mit dem delay. Testweise einfach den Kalibrierwert
mal direkt in deinem Programm setzen.
Gruß
Flo
Holger K. schrieb:> F_CPU korrekt auf 800.000UL gesetzt.> Wenn ich F_CPU auf 940.000UL setze...
Ich hab da mal Punkte reingesetzt. Du bist sicher, daß du das so
angegeben hast?
Dann würde das nämlich ziemlich gut passen:
t15 schrieb:> Sicher, dass die Fuses richtig gesetzt sind? Oftmals ist bei> fabriksneuen AVRs ein Prescaler vom Faktor 8 eingestellt, so dass der> Chip nur auf 1 MHz läuft; versuchs mal mit> #define F_CPU 1000000UL> wär nur eine Idee
Thomas E. schrieb:> Holger K. schrieb:>> F_CPU korrekt auf 800.000UL gesetzt.>> Wenn ich F_CPU auf 940.000UL setze...
Also, ich habe bei aktivierter CKDIV8 Fuse F_CPU auf 800000UL (8 mit 5
Nullen) gesetzt. Dann läuft mein Delay 51 Sekunden statt 60
Nehme ich CKDIV8 raus, muss ich F_CPU auf 8000000UL (8 mit 6 Nullen)
setzen (und selbige Änderung auch in der lcd.c machen), dann läuft mein
Delay 1:04 Minuten anstatt 60 Sekunden.
Den Teufel mit dem Beelzebub ausgetrieben würde ich sagen.
Holger K. schrieb:> Nehme ich CKDIV8 raus, muss ich F_CPU auf 8000000UL (8 mit 6 Nullen)> setzen (und selbige Änderung auch in der lcd.c machen), dann läuft mein> Delay 1:04 Minuten anstatt 60 Sekunden.
F_CPU stellt man gewöhnlich zentral an einer Stelle in der IDE ein oder
in einem einzigen Headerfile. Dafür wird nicht in jedem File
rumgefummelt. Sonst ist da etwas komisch am Quellcode.
Holger K. schrieb:> Also, ich habe bei aktivierter CKDIV8 Fuse F_CPU auf 800000UL (8 mit 5> Nullen) gesetzt.
Das ist falsch.
Mit aktivierter CKDIV8-Fuse rennt Dein µC mit 1MHz. In diesem Fall musst
Du F_CPU auf 1000000UL (1 mit 6(!) Nullen) setzen.
Wenn Du die CKDIV8-Fuse wegnimmst (wozu ich Dir raten würde), dann läuft
Dein µC mit 8MHz. In diesen Fall ist F_CPU auf 8000000UL (8 mit 6
Nullen) anzugeben.
> Dann läuft mein Delay 51 Sekunden statt 60
Klar: Du hast definiert: "Mein µC läuft mit 800kHz". Er läuft aber mit
1MHz, also 20 Prozent schneller. Daher schafft er die 60 Sekunden in 51
Sekunden.
Achtung bei delay_ms mit größeren werten (so ab 200) kann es probleme
geben. ICh mach dann lieber
delay_ms(200); delay_ms(200); delay_ms(200); delay_ms(200);
delay_ms(200);
Gruß J
Holger K. schrieb:> Nehme ich CKDIV8 raus, muss ich F_CPU auf 8000000UL (8 mit 6 Nullen)> setzen (und selbige Änderung auch in der lcd.c machen), dann läuft mein> Delay 1:04 Minuten anstatt 60 Sekunden.
Definiere F_CPU im Projekt und nicht in jedem C-Modul. Das ist sonst zu
fehlerträchtig. 64 Sekunden sind schon ziemlich nah dran.
Jetzt fragt sich natürlich noch, wo die 4 Sekunden verbraten werden. Zum
Beispiel könnten das Zeiten sein, die in ISRs "verbraucht" werden. Die
kann nämlich _delay_ms() überhaupt nicht mitzählen. Hinzu kommen noch
Abweichungen des Oszillators - und natürlich: Deine Schleife selbst.
Zeig mal den Code dazu.
Die Probleme mit delay() finde ich richtig gut.
Spätenstes jetzt sollte klar werden, daß man halbwegs genaue
Verzögerungen mit Timern erledigt, auch wenn man dazu einmalig den Kopf
benutzen muß.
Planlos: Steht im EP
Wolfgang, Frank M: Diese zentrale Stelle im IDE bzw. im Projekt habe ich
noch nicht gefunden (habe aber auch noch nicht wirklich danach gesucht).
das F_CPU in der lcd.c habe ich einfach so übernommen. Ja, vielleicht
kein sauberer Stil, ich lerne ja noch.
Frank M: Klingt einleuchtend. Den Code an der Stelle ist nicht
weltbewegend _delay_ms(500) zweimal hintereinander, dazwischen wird ein
Port getoggelt. Allerdings gibt es eine ISR für einen
Incrementaldrehgeber. Die dürfte aber, solange man nicht dran dreht,
kaum zum tragen kommen.
he?: Hatte ich geschrieben, kein Unterschied
m.n.: Wenn der OSC nicht genau ist, ist es der Timer auch nicht.
Danke für den vielen Input :-)
Gruß
Holger
Holger K. schrieb:> Allerdings gibt es eine ISR für einen> Incrementaldrehgeber. Die dürfte aber, solange man nicht dran dreht,> kaum zum tragen kommen.
Kommt drauf an, ob es sich hierbei um eine ISR mit Timer oder INT0 bzw.
PCINT handelt. Bei ISRs mit Timern spürst Du schon das Sichern und
Wiederherstellen der Register (push/pop) in "Zeitmessungen" per delay.
Du kannst ja mal probeweise die Interrupts komplett abstellen.
> m.n.: Wenn der OSC nicht genau ist, ist es der Timer auch nicht.
Aber schon genauer als Schleifen von delay-Calls. Die Timer arbeiten in
Echtzeit, die Delay-Calls zählen einfach NOPs und können daher den
Overhead, den Du mit der Schleife oder in ISRs erzeugst, nicht erfassen.
Holger K. schrieb:> Diese zentrale Stelle im IDE bzw. im Projekt habe ich> noch nicht gefunden (habe aber auch noch nicht wirklich danach gesucht).> das F_CPU in der lcd.c habe ich einfach so übernommen. Ja, vielleicht> kein sauberer Stil, ich lerne ja noch.
Nicht einfach alles übernehmen. Die Deklaration von F_CPU gehört in das
Makefile, bzw. in die Projekteigenschaften vom Studio, das dann diese
Angabe ins Makefile schreibt.
F_CPU gehört NIE in .c oder .h Files!
Warum nicht? Nun ja, es muss garantiert werden, dass alle Files im
Makefile mit dem gleichen F_CPU übersetzt werden.
Holger K. schrieb:> Diese zentrale Stelle im IDE bzw. im Projekt habe ich> noch nicht gefunden (habe aber auch noch nicht wirklich danach gesucht).
Ich begnüge mich noch mit AVR-Studio 4, deshalb kann ich dir die exakte
Stelle nicht sagen. Aber irgenwo in der Nähe, wo du auch den verwendeten
µC auswählst, kannst du die Taktfrequenz eintragen.
Um Programmierfehler/ -ungenauigkeiten in der Berechnung der Verzögerung
auszuschließen, kannst du vor und nach dem Programmteil einen Breakpoint
setzen und das ganze mal im Simulator laufen lassen. Der zeigt dir dann
auf jeden Fall die korrekte Zeit an (Welche rauskommen müsste.). (Dauert
allerdings!!)
Ralf G. schrieb:> Ich begnüge mich noch mit AVR-Studio 4, deshalb kann ich dir die exakte> Stelle nicht sagen. Aber irgenwo in der Nähe, wo du auch den verwendeten> µC auswählst, kannst du die Taktfrequenz eintragen.
Project -> Configuration Options -> General -> Frequency
Bei Custom Options ist im rechten Fenster der Wert dann eingetragen
(z.B. "-DF_CPU=16000000UL")
Ich widerhole es noch ein mal:
Das OSCCAL Register muss mit dem Wert der Kalibrierungsroutine aus dem
Programm heraus gesetzt werden. Sonst steht dort der Factory Programmed
Wert drin. Mit diesem kann aber die Frequenz um +-10% abweichen,
allerdings auch nur bei 3V garantiert. Was bei vermutlich verwendeten 5V
noch wieder ganz anders sein kann.
ALSO:
In der Schaltung kalibrieren und den Wert in EEPROM/FLASH schreiben
(lassen) und am Anfang deines Programmes den Wert auslesen und in OSCCAL
setzen.
Dann stimmt auch dein delay!!!
F_CPU gehört gescheit ins Makefile, oder je nach IDE in das richtige
Feld, wobei es dann letztendlich auch im Makefile landet!
Aber das eigentlichen Problem des TO ist das OSCCAL nicht korrekt
gesetzt ist.
Gruß,
Flo
Flo schrieb:> Das OSCCAL Register muss mit dem Wert der Kalibrierungsroutine aus dem> Programm heraus gesetzt werden. Sonst steht dort der Factory Programmed> Wert drin. Mit diesem kann aber die Frequenz um +-10% abweichen,
Dann lies auch bitte das Datenblatt! Die +/- 10% kannst Du knicken.
Erfahrungsgemäß weicht der interne Takt ca. 1-2% vom Sollwert ab.
m.n. schrieb:> Dann lies auch bitte das Datenblatt! Die +/- 10% kannst Du knicken.
Ach was. Was meinst du wo ich den Wert her habe?
Hier ein Auszug aus dem Datenblatt:
Factory Calibration: 8.0 MHz bei 3V und 25°C±10%
Table 19-2 auf Seite 189.
m.n. schrieb:> Erfahrungsgemäß weicht der interne Takt ca. 1-2% vom Sollwert ab
Erfahrung geht also über Datenblatt... Na denn...
Gruß,
Flo
Flo schrieb:> Aber das eigentlichen Problem des TO ist das OSCCAL nicht korrekt> gesetzt ist.
Nein.
Sein Problem ist, daß er F_CPU mit 800kHz angegeben hat,
obwohl sein µC mit 1MHz läuft:
Holger K. schrieb:> ich habe bei aktivierter CKDIV8 Fuse F_CPU auf 800000UL (8 mit 5> Nullen) gesetzt. Dann läuft mein Delay 51 Sekunden statt 60
Der Fehler von 800kHz angegeben zu 1000kHz real enstpricht ziemlich
genau dem beobachteten Zeitunterschied von 60s geplant zu 51s real.
Es müßte aber (ohne CKDIV8) eine 8 mit 6 (sechs!) Nullen sein - für 8MHz
Taktfrequenz. Oder eine 1 mit 6 Nullen für 1MHz bei gesetzter CKDIV8
Fuse. Der Fehler durch die fehlende Kalibrierung kommt noch oben drauf.
Ah, dann sind es zwei Fehler. Hab den hier übersehen:
Holger K. schrieb:> Also, ich habe bei aktivierter CKDIV8 Fuse F_CPU auf 800000UL (8 mit 5> Nullen) gesetzt. Dann läuft mein Delay 51 Sekunden statt 60
Dennoch, das von mir geschriebene stimmt ansonsten trotzdem.
Gruß,
Flo
Flo schrieb:> Erfahrung geht also über Datenblatt... Na denn...
Wenn ihr beide mal nicht nur einen Teil gelesen hättet, würdet ihr
bemerken, daß ihr beide recht habt.
Factory calibration: 8MHz 3V 25°C +/-10%
User calibration: 7.3-8.1MHz 1.8-5.5V -40 - +85°C +/-1%
Erwin D. schrieb:> Wenn ihr beide mal nicht nur einen Teil gelesen hättet, würdet ihr> bemerken, daß ihr beide recht habt.
In wie fern. Dort steht doch das die Abweichung +-10% betragen kann bei
factory calibration. Also wenn man OSCCAL nicht auf einen selbst
bestimmten Kalibrierungswert setzt.
Das der viel genauer sein kann wenn OSCCAL richtig gesetzt ist bestreite
ich doch gar nicht.
Dennoch gebe ich zu einen Beitrag nur teilweise gelesen zu haben. Dafür
entschuldige ich mich natürlich. Kommt davon wenn man immer mal
zwischendurch mit dem Smartphone drauf guckt was es neues gibt und so
schnell drüber wischt :-)
Gruß,
Flo
Flo schrieb:> In wie fern. Dort steht doch das die Abweichung +-10% betragen kann bei> factory calibration. Also wenn man OSCCAL nicht auf einen selbst> bestimmten Kalibrierungswert setzt.
Deswegen schrieb 'm.n' ja auch:
m.n. schrieb:> Erfahrungsgemäß weicht der interne Takt ca. 1-2% vom Sollwert ab.
Er schrieb nicht "bei factory calibration" :-)
>> Das der viel genauer sein kann wenn OSCCAL richtig gesetzt ist bestreite> ich doch gar nicht.
Das habe ich aber so verstanden, daß du mit der Aussage von m.n. nicht
einverstanden warst:
Flo schrieb:> m.n. schrieb:>> Dann lies auch bitte das Datenblatt! Die +/- 10% kannst Du knicken.>> Ach was. Was meinst du wo ich den Wert her habe?
Aber nun gut. Wir wissen jetzt: Factory +-10% / User +-1%
Einverstanden? :-)
Erwin D. schrieb:> Aber nun gut. Wir wissen jetzt: Factory +-10% / User +-1%> Einverstanden? :-)
Na Klar! War wohl ein Missverständnis.
Mir ging es nur darum, das die Genauigkeit, ohne das OSCCAL mit
korrektem Wert gesetzt wurde, nicht so gut ist wie erwartet.
Und das der TO das eben selber machen MUSS in seinem Programm. Die
Kalibrierungsroutine speichert den errechneten Kalibrierungsfaktor
nämlich nur im Flash oder EEPROM, weiß ich spontan nicht so genau wo.
Alles ist gut :-)
Gruß,
Flo
Mitlesa schrieb:> Ach ist das schön wenn man sich hier in einem Thread mal> im Friede-Freude-Eierkuchen-Gefühl trennt.
Klar, warum nicht? Macht doch keinen Sinn, daß man sich wegen einem
Mißverständnis die Köppe einschlägt, oder? :-)
Mitlesa schrieb:> Ach ist das schön wenn man sich hier in einem Thread mal> im Friede-Freude-Eierkuchen-Gefühl trennt.
Genau! Man muss nur an das Gute im Forum glauben... ;-)
Erwin D. schrieb:> Klar, warum nicht? Macht doch keinen Sinn, daß man sich wegen einem> Mißverständnis die Köppe einschlägt, oder? :-)
Natürlich nicht. Passiert aber dennoch oft genug hier glaube ich :-)
Flo schrieb:>speichert den errechneten Kalibrierungsfaktor> nämlich nur im Flash oder EEPROM, weiß ich spontan nicht so genau wo.
Das kannst Du Dir aussuchen, nebst Deiner Wunschadresse. Sie muß nur
frei sein, sonst gibts Mecker beim Programmieren.
Ich meine irgendwo hier gelesen zu haben, dass die ATMega den Wert
selbsttätig beim Reset einlesen, bin mir aber nicht ganz sicher. Aber
egal, jetzt weiß ich ja woran es hängt, und werde bei der Gelegenheit
gleich den Code um F_CPU bereinigen.
Besten Dank euch allen!
Flo schrieb:> Erfahrung geht also über Datenblatt... Na denn...
Allemal. Aber man muß das Datenblatt auch verstehen.
Factory Calibration wird bei 3V/25°C gemacht. Bei dieser Spannung und
bei dieser Temperatur beträgt die Toleranz +-1-2%. Über den gesamtem
zulässigen Spannungs-und Temperaturbereich beträgt die Toleranz +-10%.
D.h. zwischen 1,8V und 5,5V sowie zwischen -40°C und 85°C. Betreibt man
den Controller also in der Wüste wird die Frequenz zwischen Tag und
Nacht kräftig schwanken. Bei User Calibration passt man den Takt immer
an die jeweiligen Bedingungen an. Damit bleibt er dann auch in der
Sahara rund um die Uhr auf +-1-2% konstant.
Das lässt sich auch sehr schön nachmessen. Dazu brauchst du ein
Labornetzteil, einen Frequenzzähler, einen Föhn und eine Dose
Kältespray.
Thomas E. schrieb:> Factory Calibration wird bei 3V/25°C gemacht. Bei dieser Spannung und> bei dieser Temperatur beträgt die Toleranz +-1-2%
Sorry, da lese ich im Datenblatt aber was anderes:
Accuracy at given voltage & temperature: +-10%
Bei factory calibration.
Liest sich für mich ziemlich eindeutig.
Erleuchtet mich wenn ich was übersehen haben sollte.
Gruß
Flo
Ist sogar noch eine Fußnote dran:
Accuracy of oscillator frequency at calibration point (fixed
temperature and fixed voltage).
Also nix über den gesamten VCC und Temperaturbereich.
Gruß
Flo
Warum wird hier über _delay_ms() diskutiert?
_delay_ms() kann und wird nie und nimmer die Genauigkeit erreichen, die
ein
vernünftig programmierter Timerinterrupt erzeugen kann.
Da der TO nicht einmal weiss, dass man F_CPU fest auf den Wert der
Ozillators setzt (inter oder extern ist hierbei wurscht), bringt dieser
Thread eigentlich keine vernünftigen Erkenntnisse.
_delay_ms() ist nur eine Krücke, aber keine Timingfunktion wenn es um
die Einhaltung einer definierten Zeit geht.
Wenn man hier die Suchfunktion richtig benutzt, sein Hirn dabei vorher
einschaltet, dann findet man hier massig Infos zu dem Thema.
Hier wird doch gar nicht über _delays_ms() diskutiert. Hier wird über
die Genauigkeit des internen Oszillators diskutiert. Mit und ohne
Kalibrierung.
Der TO weiß im übrigen auch das er F_CPU richtig setzen muss. Steht im
ersten Beitrag. Hast du offenbar nicht richtig gelesen. Er konnte nur
offenbar nur nicht die 8MHz korrekt eintragen. Es fehlte eine Null.
Auch ob _delays_ms() an der vom TO verwendeten Stelle sinnvoll verwendet
wird wissen wir gar nicht.
Also warum schimpfst du so?
Im übrigen, der Timer geht mit fehlender Kalibrierung genau so falsch.
Gruß
Flo
Flo schrieb:> Hier wird doch gar nicht über _delays_ms() diskutiert. Hier wird über> die Genauigkeit des internen Oszillators diskutiert. Mit und ohne> Kalibrierung.
Gemessen wird die Frequenz aber indirekt über die Laufzeit von
_delay_ms(1000), oder?
Und diese Laufzeit ist mindestens F_CPU Takte (bei 1000ms), falls nicht
ein Interrupt noch weitere Takte verbraucht.
Das meint Codix (vermutlich) mit seiner Aussage zu _delay_ms().
Thomas E. schrieb:> Factory Calibration wird bei 3V/25°C gemacht. Bei dieser Spannung und> bei dieser Temperatur beträgt die Toleranz +-1-2%
Aus der application note AVR057:
The ATtiny4/5/9/10/20/40 devices feature an internal 8MHz RC oscillator
with prescalar and calibration register (OSCCAL). The internal RC
oscillator of these devices is factory calibrated for ±10% accuracy at
3V supply voltage and at 25°C. But most of the applications needs more
accurate clock as their basic requirement. For such applications AVR®
offers a way to calibrate the internal RC oscillator. The internal RC
oscillator can be user calibrated to ±1% accuracy by modifying the
OSCCAL register
Also wenn mir Zeiten bei einem Projekt wichtig wären würde ich nicht auf
den internen Oszi setzen.
Eine Quick&Dirty-Lösung: Man weiß ja jetzt, dass _delay_ms() um
100-51/60*100 Prozent daneben liegt, also einfach in _delay_ms() den
gewünschten Wert mit 60/51 multiplizieren. Führt vielleicht zu einem
Ergebnis, dass den eigenen Anforderungen genügt.
Codix schrieb:> _delay_ms() ist nur eine Krücke, aber keine Timingfunktion wenn es um> die Einhaltung einer definierten Zeit geht.
Nö. _delay_ms() ist hochgenau, sofern man keine Interrupts an hat und
Optimierung eingeschaltet ist. Man muss nur wissen, wie man es korrekt
nutzt. Und um irgendwo an einer Stelle im Programm mal ein Delay zu
haben, bei dem der µC sonst eh nix macht, wäre es ziemlich umständlich,
extra den Timer anzuwerfen und eine ISR zu schreiben, nur um sich den
Aufruf von _delay_ms() zu sparen.
Thomas E. schrieb:> Betreibt man den Controller also in der Wüste wird die Frequenz zwischen> Tag und Nacht kräftig schwanken. Bei User Calibration passt man den Takt> immer an die jeweiligen Bedingungen an. Damit bleibt er dann auch in der> Sahara rund um die Uhr auf +-1-2% konstant.
Durch die Kalibrierung eleminiert man doch nicht den Einfluss der
Temperatur.
Rolf M. schrieb:> Nö. _delay_ms() ist hochgenau, sofern man keine Interrupts an hat und> Optimierung eingeschaltet ist. Man muss nur wissen, wie man es korrekt> nutzt. Und um irgendwo an einer Stelle im Programm mal ein Delay zu> haben, bei dem der µC sonst eh nix macht, wäre es ziemlich umständlich,> extra den Timer anzuwerfen und eine ISR zu schreiben, nur um sich den> Aufruf von _delay_ms() zu sparen.
Naja, sooo umständlich ist eine Timer-ISR nun auch wieder nicht aber ja,
das _delay_ms() ist noch einen Tacken einfacher.
Rolf M. schrieb:> Durch die Kalibrierung eleminiert man doch nicht den Einfluss der> Temperatur.
Das zum einem aber auch eine Uhr, die nur auf 1-2% genau geht ist doch
sehr ungenau.
Rolf M. schrieb:> Durch die Kalibrierung eleminiert man doch nicht den Einfluss der> Temperatur.
Was ist daran eigentlich so schwer zu verstehen? Daß eine einmalig
vorgenommene Kalibrierung den Temperatureinfluß nicht eliminiert, ist
eine ziemlich triviale Anmerkung.
Mit der Kalibrierung wird der Takt auf die gerade vorliegenden oder zu
erwartenden Bedingungen eingestellt. Schwanken diese sehr stark, muß
ständig nachgeregelt werden. Z.B. mit empfangenen Daten als Referenz.
Oder mit einer abgespeicherten Temperaturkurve.
m.n. schrieb:> Die Probleme mit delay() finde ich richtig gut.> Spätenstes jetzt sollte klar werden, daß man halbwegs genaue> Verzögerungen mit Timern erledigt, auch wenn man dazu einmalig den Kopf> benutzen muß.
Das war die erste sinnvolle Antwort!!!!
Ralph schrieb:> auch wenn man dazu einmalig den Kopf> benutzen muß.
Das?
Wenn man den Kopf benutzt kommt man fix darauf, dass dieses einen großen
Kern Wahrheit enthält.:
Flo schrieb:> Im übrigen, der Timer geht mit fehlender Kalibrierung genau so falsch.
m.n. schrieb:> Spätenstes jetzt sollte klar werden, daß man halbwegs genaue> Verzögerungen mit Timern erledigt, auch wenn man dazu einmalig den Kopf> benutzen muß.Ralph schrieb:> Das war die erste sinnvolle Antwort!!!!
Ihr schmeißt wegen einer (einmaligen) Initialisierung eines LCDs einen
Timer an? Zum Takte verbraten? ^^
Ralf G. schrieb:> Zum Takte verbraten? ^^
Das ist genau der Punkt. Takte "verbrät" man mit nop-Schleifen, auch
delay genannt. Mit Timern hingegen nicht. Und da man meist sowieso
einen Takt benötigt, um verschiedene Dinge regelmäßig anzustoßen, kann
man den auch statt der delays benutzen.
Ralf G. schrieb:> Ihr schmeißt wegen einer (einmaligen) Initialisierung eines LCDs einen> Timer an? Zum Takte verbraten? ^^
Bestimmt. Weil _delay_ms() ist die Ausgeburt des Teufels und abgrundtief
böse. :-)
Ich sagte ja auch bereits: Wir wissen gar nicht recht was der TO mit dem
delay überhaupt macht. Deswegen ist es doch völlig fehl am Platze sich
darüber zu streiten ob das nun falsch verwendet wird oder nicht.
Mir geht's immer noch um die Genauigkeit der Factory Kalibrierung. Aber
da erwarte ich inzwischen auch keine vernünftige Antwort mehr, wieso die
+-10% bei 3V und 25°C nicht stimmen sollten. Denn Datenblatt und
Application Note stimmen mir ja eigentlich zu, also warum weiter Zeit
damit vergeuden.
Thomas E. schrieb:> Factory Calibration wird bei 3V/25°C gemacht. Bei dieser Spannung und> bei dieser Temperatur beträgt die Toleranz +-1-2%.Flo schrieb:> The internal RC> oscillator of these devices is factory calibrated for ±10% accuracy at> 3V supply voltage and at 25°C
In der Application Note steht was anderes wie ich bereits postete. Ja
die ist eigentlich für andere Tinys, aber in deren Datenblättern ist die
gleiche Tabelle mit genau den gleichen +-10% und der RC Oszillator ist
mit Sicherheit sowieso der gleiche...
Gruß,
Flo
Ralf G. schrieb:> Ihr schmeißt wegen einer (einmaligen) Initialisierung eines LCDs einen> Timer an? Zum Takte verbraten? ^^
_delay_ms() verbrät auch Takte ;), mehr sogar als ein Timer. Und bei
_delay_ms() muss man warten bis die Takte verbraten sind, beim Timer
kann man nebenbei noch was anderes machen. ;)
Also an dieser Stelle wird nichts weiter gemacht als eine Uhr
runtergezählt. Jede Sekunde das LCD aktualisiert, jede halbe Sekunde
eine LED getoggelt. Sonst nichts. Die CPU hat derweil ohnehin absolut
nichts zu tun, sie kann so viel Zeit verNOPpen wie sie will.
Ja, könnte man auch mit einem Timer machen, aber wozu der Aufwand?
Hochgenau muß die Zählung ohnehin nicht sein.
Holger K. schrieb:> Also an dieser Stelle wird nichts weiter gemacht als eine Uhr> runtergezählt. Jede Sekunde das LCD aktualisiert, jede halbe Sekunde> eine LED getoggelt. Sonst nichts. Die CPU hat derweil ohnehin absolut> nichts zu tun, sie kann so viel Zeit verNOPpen wie sie will.
Eine CPU, die nichts zu tun hat, gehört ins Bett (Stichwort: Sleep
Modes).
Holger K. schrieb:> Ja, könnte man auch mit einem Timer machen, aber wozu der Aufwand?> Hochgenau muß die Zählung ohnehin nicht sein.
Dann hast Du ja auch kein Problem. Ansonsten nimm einen Quarz resp. ext.
Quarzoszi als Takt, und ggf. einen AVR, wo Du den anschließen kannst.
Erwin D. schrieb:> Ralf G. schrieb:>> Zum Takte verbraten? ^^>> Das ist genau der Punkt. Takte "verbrät" man mit nop-Schleifen, auch> delay genannt. Mit Timern hingegen nicht. Und da man meist sowieso> einen Takt benötigt, um verschiedene Dinge regelmäßig anzustoßen, kann> man den auch statt der delays benutzen.
Aber nicht für ein paar hundert Nanosekunden. Wie z.B.
Displayinitialisierung oder Ansteuerung von WS2812. Dafür braucht man
ein Delay. Und zwar _delay_us() oder ein paar asm volatile ("nop").
Benutzt man hingegen _delay_ms() ist man auf dem falschen Weg und fast
immer mit einem Timer besser bedient.
Holger K. schrieb:> Ja, könnte man auch mit einem Timer machen, aber wozu der Aufwand?
Das ist überhaupt kein Aufwand. Und spätestens wenn du noch einen Taster
abfragen willst, hast du mit deinen Delays die berühmte Karte, die mit A
anfängt und mit rschkarte endet. Dann versuchst du dein Programm
irgendwie zum Laufen zu bringen und kriegst es am Ende doch nur mit
Timer hin. Das ist Aufwand. Also mach es gleich richtig.
Flo schrieb:> In der Application Note steht was anderes wie ich bereits postete.
Du verstehst es nur nicht, hast es noch nie nachgemessen und hast von
Elektronik allgemein keine Ahnung. Ich habe dir doch schon gestern
geschrieben, wie das zusammenhängt. Ich diskutiere das nicht mit dir.
Such dir dafür jemand anders.
Thomas E. schrieb:> Aber nicht für ein paar hundert Nanosekunden. Wie z.B.> Displayinitialisierung oder Ansteuerung von WS2812. Dafür braucht man> ein Delay. Und zwar _delay_us() oder ein paar asm volatile ("nop").> Benutzt man hingegen _delay_ms() ist man auf dem falschen Weg und fast> immer mit einem Timer besser bedient.
Das ist mir schon klar. Ich schrieb das, weil Holger von einer Uhr
sprach, in der er die Sekunden mit delay_ms(1000) bzw. delay_ms(100)
erzeugen wollte.
Holger K. schrieb:> Eine 60 Sekunden Zeitschleife läuft in nur etwa 51 Sekunden durch, dabei> ist es egal ob ich diese mit _delay_ms(1000) oder _delay_ms(100)> aufbaue.
Für eine Display-Initialisierung und ähnliche Sachen kann man schon ohne
schlechtes Gewissen delay_us() benutzen. Sehe ich genauso.
Thomas E. schrieb:> Du verstehst es nur nicht, hast es noch nie nachgemessen und hast von> Elektronik allgemein keine Ahnung. Ich habe dir doch schon gestern> geschrieben, wie das zusammenhängt. Ich diskutiere das nicht mit dir.> Such dir dafür jemand anders.
Keinen Auftrag bekommen Freelancer? Oder warum so schlechte Laune?
Wenn im Datenblatt UND in der Appnote steht +-10% bei 3V und 25°C gehe
ich davon aus das das im schlimmsten Fall auch so ist und verlasse mich
nicht auf "Erfahrungen" das es meistens besser ist. Da kann ich auch
10000 mal gemessen haben das es besser ist.
Wenn du das so machst, viel Spaß! Spätestens wenn dir ein Projekt um die
Ohren fliegt und man sieht das du dich nicht ans Datenblatt gehalten
hast dann mal gute Nacht. Da kannst du dann lange erklären das es Deiner
Erfahrung nach sonst immer ging!
Wenn du nicht in der Lage bist vernünftig mit anderen Menschen zu reden,
dann lass es eben. Aber beleidige hier nicht einfach irgendwelche
Menschen die du nicht kennst!
Erwin D. schrieb:> Für eine Display-Initialisierung und ähnliche Sachen kann man schon ohne> schlechtes Gewissen delay_us() benutzen. Sehe ich genauso.
Da schließe ich mich an, sehe ich ähnlich. Die delay.h ist nicht
generell schlecht und kann an der richtige Stelle schon ein wenig
eigenen Gehirnschmalz sparen.
Flo schrieb:> Wenn im Datenblatt UND in der Appnote steht +-10% bei 3V und 25°C gehe> ich davon aus das das im schlimmsten Fall auch so ist und verlasse mich> nicht auf "Erfahrungen" das es meistens besser ist.
Nein, das hatten wir doch schon. Die 10% beziehen sich NUR auf die
Factory Calibration. Wenn du den Wert des Calibration Byte selbst
ermittelst, kannst du SICHER davon ausgehen, daß du auf 1% kommst. Denn
das steht ausdrücklich im Datenblatt!
Den Wert für die Factory Calibration sehe ich als "Pi mal Daumen" an,
damit man ohne eigene Calibrierung "ungefähr" die 8MHz bei 3V und 25°C
hat und damit gleich loslegen kann. Wenn man es genauer braucht, macht
man eine User Calibration und kommt damit auf 1%. Wenn man das nicht
sicher erreichen würde, stünde es garantiert nicht im Datenblatt. Die
schießen sich doch nicht ins eigene Knie!
Erwin genauso meine ich es doch auch.
Du kaufst 100000 Tinys und wirst bei default Factory Calibration +-10%
Fehler feststellen bei der RC Frequenz.
Bei fester Temperatur und Spannung.
GENAU DAS MEINTE ICH
Drücke ich mich so undeutlich aus?
Gruß
Flo
Flo schrieb:> Erwin genauso meine ich es doch auch.
Na dann bin ich wieder beruhigt. Hatte schon das dumme Gefühl, daß du
wieder was durcheinander bringst.
Also alles gut :-)
Erwin D. schrieb:> Also alles gut :-)
Alles gut. Ich glaube wirklich ich drücke mich manchmal etwas undeutlich
aus.
Aber deswegen muss man ja nicht gleich ausfallend werden so wie andere
User hier...
Schönen Abend noch,
Flo
Flo schrieb:> Alles gut. Ich glaube wirklich ich drücke mich manchmal etwas undeutlich> aus.
Kann schon sein :-)
Du hattest geschrieben:
Flo schrieb:> Wenn im Datenblatt UND in der Appnote steht +-10% bei 3V und 25°C
Und da du kein Wort davon schriebst, daß die Werte nur bei Factory
Calibration gelten, mußte ich annehmen, du meinst generell 10%. Deswegen
hatte ich nochmal auf die User Calibration hingewiesen mit 1%.
Aber jetzt ist's wirklich gut! :-)
Flo schrieb:> Schönen Abend noch
Ebenso!
Erlaube mir noch einen Nachtrag Erwin
Flo schrieb:> Mir geht's immer noch um die Genauigkeit der Factory Kalibrierung. Aber> da erwarte ich inzwischen auch keine vernünftige Antwort mehr, wieso die> +-10% bei 3V und 25°C nicht stimmen sollten.Flo schrieb:> Sorry, da lese ich im Datenblatt aber was anderes:>> Accuracy at given voltage & temperature: +-10%>> Bei factory calibration.
Ich habe es also schon mindestens 2 mal so geschrieben und auch die
Appnote zitiert.
Aber egal, wir sind uns einig und alles ist richtig so.
Gruß
Flo
Erwin D. schrieb:> Wenn du den Wert des Calibration Byte selbst> ermittelst, kannst du SICHER davon ausgehen, daß du auf 1% kommst.
Ja, wenn Du genau liest bei definierter Temperatur UND Spannung. Sobald
sich einer der beiden Parameter ändert sind die 1 % nicht mehr
garantiert.
Datenblatt S. 189 - Note 1 zur Tabelle:
Accuracy of oscillator frequency at calibration point (fixed temperature
and fixed voltage).
mit Bezug auf die +/- 1%
he? schrieb:> Achtung bei delay_ms mit größeren werten (so ab 200) kann es probleme> geben. ICh mach dann lieber> delay_ms(200); delay_ms(200); delay_ms(200); delay_ms(200);> delay_ms(200);
Ohne jetzt Deinen Compiler zu kennen - treten die Probleme so vielleicht
ungefähr ziemlich genau ab 256 auf? Noch dazu in Zusammenhang mit einer
Compilerwarnung?
Dieter F. schrieb:> Ja, wenn Du genau liest bei definierter Temperatur UND Spannung. Sobald> sich einer der beiden Parameter ändert sind die 1 % nicht mehr> garantiert.
Richtig, genauso ist es.
M. K. schrieb:> Ralf G. schrieb:>> Ihr schmeißt wegen einer (einmaligen) Initialisierung eines LCDs einen>> Timer an? Zum Takte verbraten? ^^>> _delay_ms() verbrät auch Takte ;), mehr sogar als ein Timer.
Nur wenn man länger warten will. ;-)
> Und bei _delay_ms() muss man warten bis die Takte verbraten sind, beim> Timer kann man nebenbei noch was anderes machen. ;)
Ja. Wenn man aber an der Stelle eh nix zum machen hat und warten muss,
bis die Zeit rum ist, steht da nachher eine Schleife, die einfach nur
mit maximaler Geschwindigkeit ein Flag abfragt, das von der ISR nach
Ablauf der Zeit gesetzt wird. Klar könnte man jetzt zusätzlich noch den
Prozessor schlafen legen, aber das hat nur in wenigen Fällen wirklich
einen nennenswerten Vorteil.
Und das nur, um die Verwendung von _delay_ms() zu vermeiden. Ich
behaupte nicht, dass es generell besser ist, sondern dass beides seine
Anwendungsfälle hat. In manchen ist das eine sinnvoller, in manchen das
andere. Nur ist eben die Timer-ISR häufiger sinnvoll als das
_delay_ms(). Deshalb würde ich aber nicht sagen, dass man krampfhaft
jedes Auftreten von _delay_ms() durch die Nutzung von Timern ersetzen
muss.
Thomas E. schrieb:> ein Delay. Und zwar _delay_us() oder ein paar asm volatile ("nop").> Benutzt man hingegen _delay_ms() ist man auf dem falschen Weg und fast> immer mit einem Timer besser bedient.
Du weißt aber, dass man mit _delay_ms() auch nur z.B. 0,1 ms warten
kann?
Flo schrieb:> Wenn du nicht in der Lage bist vernünftig mit anderen Menschen zu reden,> dann lass es eben. Aber beleidige hier nicht einfach irgendwelche> Menschen die du nicht kennst!
Er scheint ja nicht nur in der Hinsicht Defizite zu haben. Auch mit dem
Verständnis von Datenblättern scheint es nicht zu klappen, obwohl ihm
zumindest bewußt ist, dass dieses Verständnis eigentlich erforderlich
ist.
Rolf M. schrieb:> Du weißt aber, dass man mit _delay_ms() auch nur z.B. 0,1 ms warten> kann?Rolf M. schrieb:> Er scheint ja nicht nur in der Hinsicht Defizite zu haben. Auch mit dem> Verständnis von Datenblättern scheint es nicht zu klappen, obwohl ihm> zumindest bewußt ist, dass dieses Verständnis eigentlich erforderlich> ist.
Mein Verständnis von Datenblättern ist ein sehr gutes und dem eines
flogastes oder deinem weit überlegen. Und wenn sich irgendwer beleidigt
fühlt, weil ich nicht auf seine sinnlose Diskussion, die aus nichts
anderem herrührt, als daß er nichts verstanden hat, eingehe, ist das
sein Problem.
Rolf M. schrieb:> Du weißt aber, dass man mit _delay_ms() auch nur z.B. 0,1 ms warten> kann?
Diese Anmerkung hättest du uns bei besserem Kenntnisstand auch ersparen
können.
Denn ich weiß, daß man mit _delay_us() auch 0.1µs warten kann.
Rolf M. schrieb:> Ja. Wenn man aber an der Stelle eh nix zum machen hat und warten muss,> bis die Zeit rum ist, steht da nachher eine Schleife, die einfach nur> mit maximaler Geschwindigkeit ein Flag abfragt,
Ich würde das ja mit Interrupts machen, da wird weder Schleife noch Flag
mit maximaler Geschwindigkeit abgefragt.
Rolf M. schrieb:> Klar könnte man jetzt zusätzlich noch den> Prozessor schlafen legen, aber das hat nur in wenigen Fällen wirklich> einen nennenswerten Vorteil.
Also Energie sparen hat keinen nennenswerten Vorteil? Interessant.
Rolf M. schrieb:> Ich> behaupte nicht, dass es generell besser ist, sondern dass beides seine> Anwendungsfälle hat.> ...
Das sehe ich auch so, hab ich oben doch auch schon geschrieben gehabt ;)
Rolf M. schrieb:> Du weißt aber, dass man mit _delay_ms() auch nur z.B. 0,1 ms warten> kann?
steht ja auch in der Lib, ist das jetzt wirklich was Neues?
Thomas E. schrieb:> Mein Verständnis von Datenblättern ist ein sehr gutes und dem eines> flogastes oder deinem weit überlegen. Und wenn sich irgendwer beleidigt> fühlt, weil ich nicht auf seine sinnlose Diskussion, die aus nichts> anderem herrührt, als daß er nichts verstanden hat, eingehe, ist das> sein Problem.
Deine Überheblichkeit ist dermaßen zum kotzen, das hält ja keiner aus
Uwe
Flo schrieb:> Du kaufst 100000 Tinys und wirst bei default Factory Calibration +-10%> Fehler feststellen bei der RC Frequenz.
Sehr wahrscheinlich wirst du diese Fehler nicht feststellen, sondern
viel geringere.
Die ±10 % sind ein reiner Garantiewert, damit niemand Atm^H^H^HMicrochip
verklagen kann, wenn der vorprogrammierte OSCCAL-Wert doch mal etwas
stärker abweicht als üblich. Die Praxis zeigt, dass der von Haus aus
mitgelieferte Wert in aller Regel sehr viel besser ist.
Insofern ist das ganz gewiss erstmal nicht das Problem des TEs (was
sich ja auch anderweitig dann gezeigt hat), sondern eher, dass die
von ihm behauptete CPU-Frequenz (die _delay_ms als Basis für die
Rechnung benutzt) einfach nicht mit dem realen Wert übereinstimmt.
Jörg W. schrieb:> Flo schrieb:>> Du kaufst 100000 Tinys und wirst bei default Factory Calibration +-10%>> Fehler feststellen bei der RC Frequenz.>> Sehr wahrscheinlich wirst du diese Fehler nicht feststellen, sondern> viel geringere.
Da hast du natürlich Recht Jörg, wahrscheinlich wird die Toleranz nicht
ausgereizt sein. Da ist ja sicher auch noch einiges an Reserve drin. Ich
hab das etwas zu überzogen beschrieben um zu auszusagen was der Wert im
Datenblatt quasi bedeutet.
Aber ich darf micht doch niemals darauf verlassen das der Wert
normalerweise immer nur +-1-2% daneben liegt.
Im Zweifelsfall hat man aber die Arschkarte wenn man sich auf sowas
verlässt und der Wert doch mal mehr streut. Mehr wollte ich doch damit
gar nicht sagen.
Was den TO angeht, das er die Frequenz tatsächlich als 800kHz angegeben
hat, hatte ich tatsächlich beim lesen übersehen. Das schrieb ich ja auch
schon.
Des weiteren wollte ich ihn nur darauf hinweisen, das er eben OSCCAL
selber mit dem Kalibrierwert beschreiben muss, damit die RC Frequenz
besser passt. Das macht der Controller nicht von alleine. Per Default
landet der Factory Calibration Wert in OSCCAL.
Das die User Calibration dann auch nur bei der kalibrierten Temperatur
und VCC stimmt, sollte wohl jedem klar sein.
Gruß,
Flo
M. K. schrieb:> steht ja auch in der Lib, ist das jetzt wirklich was Neues?
Das ist ja auch der Grund, warum ich wohl oder übel lieber direkt in
Assembler "programmiere".
Die Libraries enthalten eben oft nicht das, was tatsächlich hinterher
auch funktioniert.
(Siehe LCD-Initialisierung. Da heißt es dann: "Ist wohl ein
Timing-Problem...oder so...")
Es gibt aber auch viele Freaks, die einen am liebsten steinigen, wenn
man einmal etwas Kritisches zum Thema Compiler oder Programmbibliotheken
sagt.(...und dann noch "Sketche", igitt, was ist das ?(Scherzmachgrins).
Assemblersprache ist aber auch (manchmal) sehr mühevoll, da muss man
halt durch.
Ein Lösungsbeispiel für Zeitschleife in Assembler lautet dann zum
Beispiel so:
siehe Anhang
Vielleicht lässt sich das noch einbinden in den Code.
in diesem Sinne
gustav
Flo schrieb:> Da hast du natürlich Recht Jörg, wahrscheinlich wird die Toleranz nicht> ausgereizt sein.
Bei weitem nicht.
> Aber ich darf micht doch niemals darauf verlassen das der Wert> normalerweise immer nur +-1-2% daneben liegt.Verlassen kannst du dich darauf natürlich nicht, aber bis zum
Beweis des Gegenteils kannst du in erster Näherung davon ausgehen,
dass diese Toleranz erreicht wird, und man kann solche Fehler
getrost erstmal woanders suchen.
> Per Default> landet der Factory Calibration Wert in OSCCAL.
Das ist aber nicht irgendein stur daherkommender Wert, sondern etwas,
was während der letzten Testphase als Ergebnis einer Messung am
realen Bauteil in eine Fuse geschrieben wird. Da ist das Bauteil
bereits fix und fertig im Gehäuse, also ziemlich genau im gleichen
Zustand, in dem du es zu Hause auspackst. ;-)
Daher passt der Wert eben auch normalerweise sehr viel besser als
garantiert.
> Das die User Calibration dann auch nur bei der kalibrierten Temperatur> und VCC stimmt, sollte wohl jedem klar sein.
Die Vcc-Abhängigkeit wurde über die Jahre allerdings massiv reduziert,
und bei den neueren ATtinys ist auch die Temperaturabhängigkeit
nochmal drastisch reduziert worden.
gustav schrieb:> Das ist ja auch der Grund, warum ich wohl oder übel lieber direkt in> Assembler "programmiere".
Ach, und das hilft dagegen, eine falsche Anzahl von Wartezyklen zu
berechnen?
Die Wahrscheinlichkeit, dass sich der Compiler bei der Ermittlung
der Anzahl der Wartezyklen verrechnet, dürfte geringer sein als die,
dass sich der geneigte Assemblerprogrammierer an dieser Stelle
vertut, und wenn du gar keine Ahnung hast, wie _delay_ms() intern
implementiert ist, dann könntest du dich mit den Ratschlägen auch
etwas zurückhalten.
gustav schrieb:> Ein Lösungsbeispiel für Zeitschleife in Assembler lautet dann zum> Beispiel so:> siehe Anhang
Sorry, diese "Lösung" ist funktional noch viel schlechter als
_delay_xx() und daher überhaupt kein Gewinn. Deine Warteschleife
berücksichtigt überhaupt nicht den CPU_Takt und muss für jeden
abweichenden Takt angepasst werden. Ausserdem berücksichtigt Deine
Schleife den Overhead der Schleife selbst nicht, was _delay_ms() und
_delay_us() sehr wohl machen. Außerdem ist der Code wesentlich größer
als der Assembler-Output, den der C-Compiler aus _delay_ms() bzw.
delay_us() generiert.
gustav schrieb:> Vielleicht lässt sich das noch einbinden in den Code.
Du hast das Problem überhaupt nicht verstanden. Warum sollte der TO
diesen Code einbinden?
gustav schrieb:> Das ist ja auch der Grund, warum ich wohl oder übel lieber direkt in> Assembler "programmiere".
Dein Beispiel ist eher ein Grund, in C statt Assembler zu programmieren.
M. K. schrieb:> Also Energie sparen hat keinen nennenswerten Vorteil? Interessant.
Nicht um jeden Preis, nein. Ich fürchte, mein PC verbrät in den 5
Minuten in denen ich das programmiere mehr Strom, als dieser Timer in
100 Jahren einsparen würde, wenn ich die CPU in den Zählpausen schlafen
schicke.
gustav schrieb:> Das ist ja auch der Grund, warum ich wohl oder übel lieber direkt in> Assembler "programmiere".
Das erste, einzigste und vermutlich auch letzte das ich in ASM
programmiert habe war eine 6502 CPU. Und das war zu einer Zeit als die
noch 'in' war :-)
Flo schrieb:> Was den TO angeht, das er die Frequenz tatsächlich als 800kHz angegeben> hat, hatte ich tatsächlich beim lesen übersehen. Das schrieb ich ja auch> schon.>> Des weiteren wollte ich ihn nur darauf hinweisen, das er eben OSCCAL> selber mit dem Kalibrierwert beschreiben muss, damit die RC Frequenz> besser passt. Das macht der Controller nicht von alleine. Per Default> landet der Factory Calibration Wert in OSCCAL.
Okay, aber damit mal wieder zurück zu den Anfängerfragen. (Ich
überspringe mal den Punkt
"Laden_des_Calibration_Wertes_aus_dem_Flash_oder_EEPROM")
Man vergebe mir bitte falls ich mal wieder etwas grundsätzlich falsch
mache, aber:
Egal ob ich zu Beginn nun OSCCAL=0x00; oder OSCCAL=0xff; setze, es
ändert sich rein garnichts ?!
gustav schrieb:> Die Libraries enthalten eben oft nicht das, was tatsächlich hinterher> auch funktioniert.> (Siehe LCD-Initialisierung. Da heißt es dann: "Ist wohl ein> Timing-Problem...oder so...")
Wenn du irgend eine HD44780 Controller Library für für die Ansteuerung
irgendeines LCD mit irgendeinem (mehr oder weniger) HD44780-kompatiblen
Controller verwendest, ohne auf das Busy-Signal des Controllers zu
achten, kann es schon mal passieren, dass ein evtl. knappes
Steuer-Timing in der Library mit einem höheren Zeitbedarf für die
Befehlsausführung im Conroller nicht harmoniert. Ob das in Assembler,
Hex- oder C programmiert ist, ist völlig schnuppe.
Holger K. schrieb:> Egal ob ich zu Beginn nun OSCCAL=0x00; oder OSCCAL=0xff; setze, es> ändert sich rein garnichts ?!
Das kann eigentlich nur bedeuten, dass der Controller nicht mit dem
internen Oszillator als Taktquelle läuft.
Und übrigens: man sollte niemals stumpf OSCCAL auf so extreme Werte
setzen. Der Controller könnte dadurch abstürzen. In jedem Datenblatt
steht, dass man OSCCAL nur in solchen Schritten ändern sollte, dass sich
maximal Taktsprünge von 2% ergeben.
Holger K. schrieb:> Man vergebe mir bitte falls ich mal wieder etwas grundsätzlich falsch> mache
Mehrfach vorgeschlagen, Antwort steht m.W. noch aus:
Test ohne interrupts. Setze “cli();“ vor dein delay.
c-hater schrieb:> Und übrigens: man sollte niemals stumpf OSCCAL auf so extreme Werte> setzen. Der Controller könnte dadurch abstürzen. In jedem Datenblatt> steht, dass man OSCCAL nur in solchen Schritten ändern sollte, dass sich> maximal Taktsprünge von 2% ergeben.
Naja, begonnen habe ich ja mit dem ausgeworfenem Korrekturwert. Nachdem
sich da nichts getan hat habe ich es mit größeren Schritten versucht bis
ich letztlich da angekommen bin.
Und ja, der läuft ganz sicher mit dem internen OSC
@Planlos: Werde ich heute Abend testen, ich hatte dieser Tage wie so oft
nicht viel Zeit für mein Projekt.
Holger K. schrieb:> Und ja, der läuft ganz sicher mit dem internen OSC
Das passt aber irgendwie mit der Aussage nicht recht zusammen. Eine
Änderung des OSCCAL von 0 auf 255 sollte die Frequenz des Oszillators
mindestens verdreifachen.
Dann weiß ich auch nicht, es ist kein Quarz(oszillator) auch kein
unsichtbarer oder eine sonstige Taktquelle da dran, an dem Port hängt
eine LED und laut Fuse ist er auf internen OSC mit 8Mhz eingestellt.
Ich schau mir das nochmal in Ruhe an, da muss ja irgendwo der Wurm drin
sein...
Holger K. schrieb:> Ich schau mir das nochmal in Ruhe an, da muss ja irgendwo der Wurm drin> sein...
Du kannst ja als ersten Test mal eine Firmware machen, die nur das
OSCCAL setzt (oder es einfach auf dem Defaultwert lässt), sonst
nichts. Dann setzt du die CKOUT-Fuse (Bit 6 der Low-Fuse auf 0),
und fortan muss auf PB5 der interne Takt herausgewackelt kommen.
Den kannst du an Oszi oder Zählfrequenzmesser messen.
Jup, guter Plan Jörg, genau das werde ich mal probieren. Dann weiß ich
auch gleich ob die Abweichung beim Delay programmtechnisch bedingt ist,
oder ob bzw. in wie weit der OSC tatsächlich daneben tickt...
Holger K. schrieb:> M. K. schrieb:>> Also Energie sparen hat keinen nennenswerten Vorteil? Interessant.>> Nicht um jeden Preis, nein. Ich fürchte, mein PC verbrät in den 5> Minuten in denen ich das programmiere mehr Strom, als dieser Timer in> 100 Jahren einsparen würde, wenn ich die CPU in den Zählpausen schlafen> schicke.
Ist ja nicht um jeden Preis und deine CPU in deinem PC ist auch ein
wenig was anderes als ein uC in einem Projekt. ;)
So, kaum das man mal ausgeschlafen an die Sache rangeht stellt man fest,
dass OSCCAL=xxx die main() Schleife knapp verfehlt hat :-)
Was den internen OSC und die Factory calibration angeht, die sind
(zumindest bei meinem) anscheinend besser als Ihr Ruf. Folgende
Schwankungen habe ich (bei Vdd=5V) ermittelt:
T = -50°C fosc=7,911 MHz
T = 20°C fosc=8,013 MHz
T = 70°C fosc=8,091 MHZ
Bei T = 20°C entspricht der ermittelte Korrekturwert für OSCCAL (0xB3)
anscheinend auch der Factory calibration, denn ein setzen eben dieses
Wertes ändert nichts weiter. Bei 70°C mag man die rund 1% Abweichung des
OSC damit vielleicht noch etwas verbessern können aber hey... 1% sind
für meine Anwendung mehr als ausreichend, zumal ich den Kameraden ja
nicht bei 70° betrieben wollte.
Geht doch!
Um dem eine Krone aufzusetzen, könnte man das noch dynamisch anpassen.
1. Manch ein AVR hat einen eingebauten Temperatursensor.
2. der WDT-OSC taugt auch als Vergleich, er hat (meist?) einen
umgekehrten Temperaturkoeffizienten.
Könnte man machen, aber halte ich für absolut nicht notwendig (Könnte ja
auch einfach einen Quarz oder einen temperaturkompensierten
Quarzoszillator verwenden). Das ganze wird ein Belichtungstimer für mein
(Platinen)belichter, wenn der bei 7 Minuten real am ende zwei Sekunden
falsch geht, liegt das völlig im Toleranzbereich des Photoresisten.
Holger K. schrieb:> Das ganze wird ein Belichtungstimer für mein (Platinen)belichter,
Oh my god ...
Über 100 Postings über (sub-)prozentgenauen Taktabgleich für einen
Prozess, der auf Grund seiner chemischen Natur eher logarithmisch
"denkt".
Das nennt man wohl Overengineering
Forist schrieb:> Das nennt man wohl *Overengineering*
Ich hab von vorneherein immer wieder betont, dass das ganze nicht
hochgenau sein muss... Wenns mir doch keiner glaubt? ;-)
m.n. schrieb:> Arduino F. schrieb:>> Um dem eine Krone aufzusetzen, könnte man das noch dynamisch anpassen.>> Anstatt der Krone würde ich statisch einen Quarz nehmen.
Der Quarz als gepriesenes Allheilmittel.
Man sollte auch seine Nachteile erwähnen: er schwingt aufgrund seiner
hohen Güte extrem langsam an. Wenn man eine Applikation hat, die
viel schlafen will, aber zwischendrin häufig mal aufwachen, kostet
das einen Haufen Energie. Der RC-Oszillator ist nach einer
Mikrosekunde stabil und benutzbar, ein Quarz braucht typisch was im
Bereich von Millisekunden.
Keramikresonatoren liegen irgendwo dazwischen, sowohl in der
Genauigkeit als auch Anschwingzeit.
Holger K. schrieb:> dass OSCCAL=xxx die main() Schleife knapp verfehlt hat :-)
Nun, das erklärt's dann. :)
> Was den internen OSC und die Factory calibration angeht, die sind> (zumindest bei meinem) anscheinend besser als Ihr Ruf.
Der Ruf des RC-Oszillators ist so schlecht nicht, es gibt eben nur
immer wieder ein paar Dauernörgler, für die bereits beim bloßen
Gedanken an einen solchen die Welt zusammenbricht, was die
Genauigkeit betrifft. Die garantierten eher lausigen 10 % des
Datenblatts leisten dem natürlich noch Vorschub – und bedeuten, dass
man sich in einer Serienproduktion halt nicht drauf verlassen kann,
sondern es exemplarbhängig nachmessen muss. Aber für Einzelstücke
ist das ohnehin kein Thema.
Jörg W. schrieb:> Man sollte auch seine Nachteile erwähnen
Nicht nur die, vorallendingen raubt mir das mindestens einen Port. Ich
habe zwar in meiner Schaltung noch welche frei, die habe ich aber für
spätere Optionen vorgesehen, und habe vor diesem Hintergrund keinen Port
mehr über, den ich für einen Quarzoszillator verwenden könnte. Es ist
halt immer das Gesamtbild entscheidend.
Holger K. schrieb:> Nicht nur die, vorallendingen raubt mir das mindestens einen Port.
Wenn du von einem externen Quarzoszillator sprichst, brauchst du genau
ein Pin, um den Takt in den µC zu bekommen. Beim direkten Anschluß eines
Quarzes brauchst du zwei Pins. Wie kommst du auf "mindestens einen
Port"? Ein Port hat in der Regel 8 Pins. Wozu brauchst du dann die
übrigen 7 bzw. 6 Pins?
Holger K. schrieb:> So, kaum das man mal ausgeschlafen an die Sache rangeht stellt man fest,> dass OSCCAL=xxx die main() Schleife knapp verfehlt hat :-)> [...]
Nur mal so aus Neugierde, denn ich kann mir nicht erklären, was das zu
bedeuten hat: Was meinst Du damit, dass der Ausdruck die main-Schleife
verfehlt hat?
Erwin D. schrieb:> brauchst du genau ein Pin
Das meinte ich eigentlich, sorry falsche Terminologie.
@Hanswurst: Ich hatte es außerhalb der main() schleife stehen.
Holger K. schrieb:
[...]
> @Hanswurst: Ich hatte es außerhalb der main() schleife stehen.
Aha. Danke.
Wenn Du erlaubst, möchte ich noch eine weitere Frage nachschieben:
Inwiefern spielt das eine Rolle, ob der Ausdruck innerhalb oder
ausserhalb der main-Schleife steht? Ich meine, ich gehe davon aus, dass
Du OSCCAL auf einen (genau einen) bestimmten Wert gesetzt hast. Da ist
es, aus meiner Sicht, eigentlich nicht notwendig, ihn mehrfach auf den
gleichen Wert zu setzen. Der bleibt ja im Register bis der Strom
abgeschaltet wird.
Das soll keine Kritik sein: Ich kann nur keinen Sinn darin erkennen, was
ja auch an meiner Unkenntnis irgendeines Details liegen kann. Es ist
auch nicht wichtig, aber irgendwie beschäftigen mich solche
"unwichtigen" Details. Wohl zu viel Columbo geguckt :-)
Ich kann Dir deine Frage nicht beantworten. Wenn Du dem Thread gefolgt
bist hast Du sicher gelesen, dass es zuvor (also außerhalb von main)
nicht funktioniert hat. Was auch immer ich in das Register geschrieben
habe (oder glaubte geschrieben zu haben), es hatte keine Auswirkung.
Nachdem es nun innerhalb von main() steht funktioniert es.
Holger K. schrieb:> Ich kann Dir deine Frage nicht beantworten. Wenn Du dem Thread gefolgt> bist hast Du sicher gelesen, dass es zuvor (also außerhalb von main)> nicht funktioniert hat.
Genau das habe ich nirgendwo gelesen. Wo hast Du das denn geschrieben?
> [...]> Nachdem es nun innerhalb von main() steht funktioniert es.
Ich vermute aber, mein Unverständnis ist von folgendem verursacht:
main () ist eine Funktion. Sie wird aber nicht in einer Schleife
aufgerufen. Eine Schleife kommt nur dann zur Ausführung, wenn man eine
hinschreibt. Also etwa:
1
main(){
2
while(1){
3
}
4
}
Ich habe nun unter eine "main-Schleife" (nicht "main-Funktion") genau so
ein Konstrukt verstanden.
Und darin spielt es, wie ich nach wie vor meine, keine Rolle ob die
Zuweisung an OSCCAL nun innerhalb der Schleife oder ausserhalb
geschieht.
Nur das eben die Zuweisung in dem einen Fall mehrfach ausgeführt wird -
was wiederrum unnötig ist.
1
main(){
2
OSCCAL=xyz;// wird einmal bei Progammstart ausgeführt.
3
while(1){
4
OSCCAL=xyz;// wird bei jedem Schleifendurchlauf ausgeführt.
5
}
6
}
Beides hat aber, bei identischem xyz immer die selbe Wirkung.
Was meinst Du dazu?
Markus F. schrieb:> Für mich bleibt hier nur eine Frage offen: was um Himmels Willen ist> eine "main-Schleife"?
Laut Wikipedia: "Die Mainschleife bei Urphar ist eine Flussschlinge des
Mains am südöstlichen Rand des Mainvierecks in Baden-Württemberg und
Bayern."
:-D
Aber es hat sich halt mal so eingebürgert, obwohl es ja kein richtiger
Ausrduck ist, das die main-Schleife die Dauerschleife in der Main()
Funktion ist. Jeder weis was es ist, jeder nutzt diesen Ausdruck -
jemanden dann deswegen Dumm machen zu wollen ist dämlich. Das ist
genauso dämlich wie jemanden darauf hinzuweisen das ein Kondom nicht
"Gummi" heißt sondern Präservativ - genauso dämlich!
Markus F. schrieb:> Für mich bleibt hier nur eine Frage offen: was um Himmels Willen ist> eine "main-Schleife"?
Übersetze es einfach als "Haupt-Schleife", wenn es dir dann klarer wird.
Ausführlich beschrieben ist das diejenige Funktion oder derjenige
Programmblock, die/der im Hauptteil des Programms in einer
Endlosschleife immer wieder aufgerufen wird.
Beim Arduino z.B. heißt die betreffende Funktion einfach loop().
Draco schrieb:> Markus F. schrieb:>> Für mich bleibt hier nur eine Frage offen: was um Himmels Willen ist>> eine "main-Schleife"?> Aber es hat sich halt mal so eingebürgert, obwohl es ja kein richtiger> Ausrduck ist, das die main-Schleife die Dauerschleife in der Main()> Funktion ist. Jeder weis was es ist, jeder nutzt diesen Ausdruck...
1
Jeder--;
Es ist keine Schleife, also nennt 'man' es auch nicht so!
Es ging um die Hauptschleife, m.a.W. um den endlos ausgeführten
Programmteil in Main(). Wenn du das /while(1) {}/ natürlich
unterschlägst, kannst du die Schleifenstruktur auch nicht mehr
entdecken.
Norbert schrieb:> Das ist keine Schleife und man muss auch kein Raketenwissenschaftler> sein um das zu erkennen, oder?
Komisch, Eigentlich weiß jeder was gemeint ist, aber der gesamte
Hirnschmalz der Community wendet seiner Energie auf um einem
offensichtlichen Anfänger und Newbie mit irgendwelchen dumm gestellten
Suggestivfragen klarzumachen, dass er halt etwas nicht korrekt
ausformuliert hat. Ich bin raus aus diesem Thread, mein Problem ist eh
gelöst. Danke nochmal an die die geholfen haben!