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
Holger K. schrieb: > Code Optimization ist eingeschaltet (-O3) Im Allgemeinen ist -Os die richtige Optimierung für util/delay.h
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
1 | #define F_CPU 1000000UL
|
wär nur eine Idee
Holger K. schrieb: > Kalibrierung habe ich gemacht und im Flash gespeichert (richtig gemacht > hoffe ich) Ja, hoffe ich auch.
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.
Welcher AVR ist es denn eigentlich? Es gibt auch welche, deren int. Osc.auf 9.6 MHz laufen kann, z.b Tiny13 als kleinstes Beispiel.
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.
:
Bearbeitet durch Moderator
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!!)
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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
Ach ist das schön wenn man sich hier in einem Thread mal im Friede-Freude-Eierkuchen-Gefühl trennt.
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.
:
Bearbeitet durch User
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: > Nicht mein Problem Warum so angepisst? Ich schrieb doch extra erleuchtet mich. Was ist denn das nun für eine Art und Weise?
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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. ;)
M. K. schrieb: > beim Timer > kann man nebenbei noch was anderes machen. ;) Dann kannst du dich ja mal hier... https://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Routinen_zur_LCD-Ansteuerung_im_4-Bit-Modus ...um ein paar sinnvolle Erweiterungen kümmern, die nebenbei mit einem Timer erledigt werden können! [ auch: ;-) ] ----- Ralf G. schrieb: > ... Initialisierung eines LCDs ... Takte verbraten? ^^
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.
:
Bearbeitet durch User
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.
1 | __builtin_avr_delay_cycles(__ticks_dc); |
2 | 28e: 00 00 nop |
3 | _delay_us(0.1); |
Kompiliert mit 10MHz.
1 | __builtin_avr_delay_cycles(__ticks_dc); |
2 | 2a0: 00 c0 rjmp .+0 ; 0x2a2 <main+0x1e> |
3 | _delay_us(0.1); |
Kompiliert mit 20MHz.
:
Bearbeitet durch User
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
Uwe K. schrieb: > Deine Überheblichkeit ist dermaßen zum kotzen [ironie] so isser halt, stets hilfsbereit und konstruktiv [/ironie]
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.
Jörg W. schrieb: > Eine > Änderung des OSCCAL von 0 auf 255 sollte die Frequenz des Oszillators > mindestens verdreifachen. Ja, Datenblatt Seite 218 ...
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...
Schon mal jetzt mit richtigem F_CPU Wert an der richtigen Stelle übersetzt?
:
Bearbeitet durch User
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...
:
Bearbeitet durch User
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.
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.
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.
:
Bearbeitet durch User
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?
Für mich bleibt hier nur eine Frage offen: was um Himmels Willen ist eine "main-Schleife"?
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!
Norbert schrieb: > Es ist keine Schleife, also nennt 'man' es auch nicht so!
1 | while(1) |
2 | {
|
3 | |
4 | }
|
... ist keine Schleife?! Aha! :'D
Draco schrieb: > Norbert schrieb: >> Es ist keine Schleife, also nennt 'man' es auch nicht so! > >
1 | > while(1) |
2 | > { |
3 | >
|
4 | > } |
5 | >
|
> > ... ist keine Schleife?! Aha! :'D Hast du ein Lese- oder Verständnisproblem? Es geht hier um die Formulierung 'main-Schleife'
1 | int main(void) { |
2 | ...
|
3 | return 0; |
4 | }
|
Das ist keine Schleife und man muss auch kein Raketenwissenschaftler sein um das zu erkennen, oder?
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!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.