Wie erschaffe ich einen 1 ms Takt bei einer Frequenz von 16MHz

#6491957
Lesenswert?

Hallo zusammen,
Ich hab da ein Problem beim erstellen eines bestimmten Taktes,
vielleicht mag mir da jemand helfen.
Undzwar soll ich einen 1ms Takt erschaffen bei einem Arduino der mit
16MHz getaktet ist.
Ich hab das so realisiert dass ich den Prescaler auf 1024 setze,
womit ich ja auf einen Takt von 64us komme.
Also konkret : 16000000MHz/1024 = 15625. Nun rechne ich 1/15625 um auf 
den Takt von 64us zu kommen.
Um die gewünschte Frequenz von 1ms zu erreichen
rechne ich : 15625/1000Hz = 15,625 .
Das Ergebnis (15,625) ziehe ich vom 8 Bit Timer (TCNTO) ab,
also : 256 - 15,625 ~= 241  =>  TCNTO = 241;
Nun habe ich noch eine counter Variable eröffnet, die jede erreichte 
Sekunde
den Status einer LED ändern soll.
Das habe ich so realisiert dass jedesmal wenn ein Überlauf im Zähler 
geschieht, der counter inkrementiert wird. Wenn counter nun den Wert der 
Variable  numWaits (siehe in meinem Code) erreicht,  änder ich den 
Status der LED. Meine Frage ist nun : Welchen Wert sollte ich numWaits 
geben,
damit die LED auch jede Sekunde einmal den Zustand wechselt ?
Meine Lösung, die allderdings nicht funktioniert war : numWaits = 1000 , 
denn 15*64us = 960us => 1ms und   1s sind ja 1000ms. Die LED blinkt dann 
allerdings garnicht mehr bzw. in sehr langen Abständen.

Wäre sehrr erfreut wenn mir da jemand aushelfen könnte.
Bedanke mich vielmals im Voraus.

Heinz
Angehängte Dateien:
#6491977
Lesenswert?

Hallo Jack ,
ich bin neu in diesem Forum, (fängt ja schonmal gut an )
der Code ist klein und ich dachte an sich dass ja nur der Wert einer
Variable ermittelt werden muss und dass dafür ein png auf dass man 
sofort zugreifen kann ausreicht. Vielleicht kannst du mir ja helfen,
insofern dass du mir erstmal erzählst wie der Code den volriegen sollte 
deiner Meinung nach.
#6491980
Lesenswert?

Heinz P. schrieb:
> Vielleicht kannst du mir ja helfen,
> insofern dass du mir erstmal erzählst wie der Code den volriegen sollte
> deiner Meinung nach.

Nicht meiner Meinung nach: über dem Feld, in dem du deinen Beitrag 
eingibst, stehen einige Informationen, darunter:

1
Formatierung (mehr Informationen...)
2

3
    [c]C-Code[/c]
4
    [avrasm]AVR-Assembler-Code[/avrasm]
5
    [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
#6491982
Lesenswert?

Heinz P. schrieb:
> Vielleicht kannst du mir ja helfen, insofern dass du mir erstmal
> erzählst wie der Code den volriegen sollte deiner Meinung nach.

Wie wäre es mit der Möglichkeit, die auf der Hand liegt:
Kopieren und einfügen. Oder, wie es weiter oben unter den wichtigen 
Regeln steht:
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Wie sollen wir denn sonst in deinem Code rumpfuschen können und ihn dir 
verbessern?
Das Bild tippt sicherlich keiner ab und probiert es bei sich am 
heimischen Rechner.
Gast #6492028
Lesenswert?

Dieter D. schrieb:
> Du packst den Code in eine Kurznamen.txt Datei und lädst diese wie ein
> Bild hoch.

Und warum nicht mit Extension .cpp, .c oder .ino?
Sonst ist das Syntax-Highlightning des Editor, mit dem man die Datei 
anzeigt, fürchterlich hilflos.

Heinz P. schrieb:
> Weil ich mittels des Timers intern einen Takt von 1ms erzeugen will,
> also sprich, eine Zeitmessung durchführen will, bei der der counter
> die sekunden seit Programmstart zählt.

So ein Timer läuft doch schon bei Arduino. Du musst den Zählwert nur mit 
der Funktion millis() auslesen.
#6492034
Lesenswert?

Wolfgang schrieb:
> Dieter D. schrieb:

> Und warum nicht mit Extension .cpp, .c oder .ino?
> Sonst ist das Syntax-Highlightning des Editor, mit dem man die Datei
> anzeigt, fürchterlich hilflos.
Danke dir, ist geschehen.

> So ein Timer läuft doch schon bei Arduino. Du musst den Zählwert nur mit
> der Funktion millis() auslesen.
Ja nur sollte ich das mittels einem Timer Interrupt lösen.
Gast #6492076
Lesenswert?

STK500-Besitzer schrieb:
> Die Fuses haben doch gar nichts mit dem Programmcode zu tun.

Aber mit der vom µC verwendeten Taktfrequenz.
Ohne die passende Fuse-Einstellungen kann man in den Code solange man 
lustig ist ein "#define F_CPU 16000000UL" rein schreiben. Das 
interessiert den Takt des Controllers überhaupt nicht.
Gast #6492097
Lesenswert?

Wolfgang schrieb:
> Aber mit der vom µC verwendeten Taktfrequenz.
> Ohne die passende Fuse-Einstellungen kann man in den Code solange man
> lustig ist ein "#define F_CPU 16000000UL" rein schreiben. Das
> interessiert den Takt des Controllers überhaupt nicht.

Das #define kommt vom Programmierer.
Die Fuses-Einstellung kommt auch vom Programmierer.

Beides interessiert sich aber nicht für einander, sondern nur der 
Programmierer.

Joachim B. schrieb:
> Welcher Compiler schaut in die Hardware?

Keiner. s.o.
Gast #6492114
Lesenswert?

Wolfgang schrieb:
> Aber die Fuses-Einstellung kommt nicht aus dem Code.

Bei dir vielleicht nicht!
Die AVR Gcc Tool Chain kann sehr wohl die Fuses aus dem Quelltext 
generieren.

Dein Argument gilt also für dich und nicht unbedingt für den Rest der 
Welt.


Nachtrag:
Für Joachim B. (jar) gilt das offensichtlich auch.
Gast #6492121
Lesenswert?

Wolfgang schrieb:
> Aber die Fuses-Einstellung kommt nicht aus dem Code. Und wenn die beiden
> Einstellungen nicht zusammen passen, tut der Controller etwas anderes,
> als im Code steht.

Habe ich doch gesagt:
Ausser dem Programmierer interessiert sich niemand für die Verbindung 
zwischen Fuses und Quellcode.
Darum er/sie/es sich kümmern.
Und wenn man nur den Programmcode auf den Controller, werden die Fuses 
nicht "angefasst".
#6492141
Lesenswert?

STK500-Besitzer schrieb:
> Ausser dem Programmierer interessiert sich niemand für die Verbindung
> zwischen Fuses und Quellcode.
> Darum er/sie/es sich kümmern.

meinte ich doch

wenn nun ein Arduino mini328p mit 8MHz Quarz oder Resonator ohne clk/8 
genutzt wird weiss der Compiler erst mal nichts davon!

Also ohne korrekte Setzung der F_CPU kommt nur Unsinn raus, jedenfalls 
nicht die Zeiten die der Programmierer erwartet.
#6492206
Lesenswert?

Hallo,

ich entnehme aus dem Post das der TO in Amtel Studio ohne Arduino IDE 
Extention programmiert. Das Board ist ein Arduino Clone mit 16MHz. 
Deswegen sollten die Fuse Einstellungen soweit passen.

Der TO kann ja einmal unter Tools > Device Programming > Fuse
die Einstellungen per Screenshot zeigen. Fenster entsprechend 
zurechtgezogen.

Wenn das passt, liegt die Taktabweichung an den ungünstig gewählten 
Prescaler/Compare Wert. Du bist bestimmt auf einen Compare von 14,63 
gekommen und hast naheliegend auf 15 gerundet. Problem ist, dass man 
zusammen mit Prescaler 1024 eine sehr hohe Abweichung hat. Rechne mit 
den Zahlen nochmal rückwärts und ermittel den realen Takt. Ich komme auf 
eine Abweichung von -11,719Hz. Der Fehler summiert sich auf.
Nimm einen Prescaler 64 mit Compare 249.
Mache dir das Leben leichter mit dem CTC Mode.
Beitrag #6492336 wurde von einem Moderator gelöscht.
Gast #6492424
Lesenswert?

Heinz P. schrieb:
> Undzwar soll ich einen 1ms Takt erschaffen bei einem Arduino der mit
> 16MHz getaktet ist.
> Ich hab das so realisiert dass ich den Prescaler auf 1024 setze,
> womit ich ja auf einen Takt von 64us komme.
> Also konkret : 16000000MHz/1024 = 15625. Nun rechne ich 1/15625 um auf
> den Takt von 64us zu kommen.

Hä?

Ja sag mal, kann denn ein Timer beim Arduino nicht den Takt durch 16000 
teilen? Oder per Prescaler durch 16 und dann per Timer durch 1000, oder 
Prescaler durch 32 und Timer durch 500 oder Prescaler durch 64 und Timer 
durch 250? Oder durch 128 und Timer durch 125.

Alles sehr seltsam - zumindest für mich, der ich mich bislang fern 
gehalten habe von allen AVR und Konsorten.

W.S.
Gast #6492425
Lesenswert?

Arduino Fanboy D. schrieb:
> STK500-Besitzer schrieb:
>> Ausser dem Programmierer interessiert sich niemand für die Verbindung
>> zwischen Fuses und Quellcode.
> Und für dich wohl auch.....
>
> Lesestoff:
> https://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.html

BlaBla schrieb:
> STK500-Besitzer schrieb:
>> Die Fuses haben doch gar nichts mit dem Programmcode zu tun.
>
> Dann guckt doch mal hier:
> Beitrag "Elf-File in Atmel Studio erzeugen"

Oh! Ich habe ja ewig nichts mehr mit AVR gemacht. Danke für den Hinweis.
Macht das AtmelStudio das von alleine?
Gast #6492444
Lesenswert?

Heinz P. schrieb:
> Die LED blinkt dann
> allerdings garnicht mehr bzw. in sehr langen Abständen.

alle acht sekunden etwa?

> Interrupt Response Time
> The interrupt execution response for all the enabled AVR interrupts
> is four clock cycles minimum.

jede Instruktion im ISR ist noch ein clock cycle (wenn nicht mehr)
(ich glaub 4 für if(true) und 7 für if(false))

willst Du also (relativ) zuverlässig zählen, musst Du diese Takte mit 
berücksichtigen.
macht mindestens 8 für den ISR (nach 14 facher ausführung) nochmal 11.

sind zwischen zwei Statusänderungen 123 clock cycles.
bei 64µS pro clockcycle sind das also ~8mS statt einer

und wenn Du dann annimmst es sei nur eine, dann wird die LED
eben nach 7.872 sekunden den Status wechseln statt nach einer ;)

'sid
#6492469
Lesenswert?

sid schrieb:
> jede Instruktion im ISR ist noch ein clock cycle (wenn nicht mehr)
> (ich glaub 4 für if(true) und 7 für if(false))
>
> willst Du also (relativ) zuverlässig zählen, musst Du diese Takte mit
> berücksichtigen.
> macht mindestens 8 für den ISR (nach 14 facher ausführung) nochmal 11.
>
> sind zwischen zwei Statusänderungen 123 clock cycles.
> bei 64µS pro clockcycle sind das also ~8mS statt einer
>
> und wenn Du dann annimmst es sei nur eine, dann wird die LED
> eben nach 7.872 sekunden den Status wechseln statt nach einer ;)
>
> 'sid

Laut meinem Verständnis spielt das keine Rolle. Das ist eine konstante 
Verzögerung. Das ist kein Fehler der sich aufsummiert o.ä.. Der Taktpin 
schaltet nur um paar Takte später wie das Event eigentlich ausgelöst 
wurde. Da dieses "später" konstant ist, ist der Pintakt in seiner 
Genauigkeit davon unbeeinflusst.
Gast #6492477
Lesenswert?

Veit D. schrieb:
> Laut meinem Verständnis spielt das keine Rolle. Das ist eine konstante
> Verzögerung. Das ist kein Fehler der sich aufsummiert o.ä.. Der Taktpin
> schaltet nur um paar Takte später wie das Event eigentlich ausgelöst
> wurde. Da dieses "später" konstant ist, ist der Pintakt in seiner
> Genauigkeit davon unbeeinflusst.

Seeehr richtig.
Gast #6492482
Lesenswert?

W.S. schrieb:
> Ja sag mal, kann denn ein Timer beim Arduino nicht den Takt durch 16000
> teilen? ...

An dem Prozessor hängt es vermutlich nicht.

Bei dem µC dürfte es sich um einen ATmega328 oder eventuell um einen 
ATmega32U4 handeln. Das wird der TO bei Zeiten bestimmt noch verraten.

Mit Arduino scheint dieser ganze Thread wenig zu tun zu haben.
Gast #6492525
Lesenswert?

Veit D. schrieb:
> Laut meinem Verständnis spielt das keine Rolle. Das ist eine konstante
> Verzögerung. Das ist kein Fehler der sich aufsummiert o.ä.. Der Taktpin
> schaltet nur um paar Takte später wie das Event eigentlich ausgelöst
> wurde. Da dieses "später" konstant ist, ist der Pintakt in seiner
> Genauigkeit davon unbeeinflusst.

Solange zwischen zwei Auslösungen des interupts mehr als 8 'freie' Takte 
sind stimmt das,
sind es weniger als acht summiert sich das schon zwangsläufig doch auf,
weil kein Platz zur Kompensation bleibt
15 Durchläufe der Schleife (ver)brauchen defacto 123 clock cycles 
(sofern ich mich nicht verzählt hab heisst das.. jdf deutlich mehr als 
15)
und wenn es die Anzahl der Durchläufe der ISR ist (was numwaits mir 
suggeriert) was gezählt wird,
dann sind 123 clock cycles eben nahe 8mS
(und nicht nur 8mS später)

denn wie soll das laufen dass etwas jede mS 'signalisiert' aber 8mS zum 
signalisieren braucht?
dazu müssten dann also minimum acht zähler parallel laufen und das tun 
sie ja nunmal nicht.

Ich würd spasseshalber mal den prescaler auf 128 setzen
(als um den faktor acht verringern)
dadurch läuft jeder clock cycle acht mal schneller und das Ergebniss 
könnte (falls ich Recht habe) passen.
Müsste man nochmal feinjustieren aber ist ja schnell gemacht den 
prescaler zu wechseln nur zum Test.

Vielleicht irre ich mich in der tat...
aber ich meine noch immer das passt so nicht.

'sid
#6492589
Lesenswert?

Hallo,

du buddelst auf der falschen Baustelle.  :-)
Der Timer erzeugt exakt aller 1ms einen Interrupt. Wo soll hier die 
Abweichung herkommen? Nur durch andere Ereignisse kann es zu 
Verzögerungen kommen. Dann hat das erzeugte Signal im schlimmsten Fall 
einen Jitter. Kommt auch darauf an wo und wie man letztlich den Pin 
umschaltet. Der Timer selbst erzeugt davon unbeirrt dennoch exakt aller 
1ms einen Interrupt. Der Timer Counter wird von nichts beeinflusst. 
Übrigens, ein ATmega328P Timer 0 hat keinen Prescaler 128.

Ich weiß nicht wie du auf deine 8 Takte usw. kommst. Vom 
Eingangsposting? Du übersiehst das der Prescaler auf 1024 gesetzt wurde. 
Das heißt der Interrupt im Eingangsposting wird aller 1024 * 15 Takte = 
15360 Takte aufgerufen. Das sind aller 960ms sind. Da bleibt jeder ISR 
Abarbeitung genügend Zeit.
Ich hatte es schon erwähnt. Wenn der TO einen Prescaler 64 und Compare 
Wert 249 nimmt, dazu noch besser den CTC Mode, dann trifft er genau 1ms.

Verständlich?
Gast #6492647
Lesenswert?

Lieber Herr Dirakie,

das sieht nicht schlecht aus. Sie können sich aber gerne auf der 
Lernplattform einen Beratungstermin bei den Betreuern buchen.

Sofern Sie den Code kopiert haben, wird das natürlich sportlich (schauen 
Sie mal in die entsprechenden Whatsapp/Telegram/Discord-Threads).

Ansonsten weiter viel Erfolg bei Aufgabe 4!
Gast #6492778
Lesenswert?

Heinz P. schrieb:
> Ich melde mich dann kommender Woche bei den Betreuern.
> Und Danke nochmal an Alle! Hab viel dazugelernt heute :P

Gerne. Falls Sie am Wochenende noch was machen: Die ISR ist nur für den 
Zähler da und soll sonst nichts machen und die wait... Routinen dürfen 
den counter natürlich nicht ändern.
#6492801
Lesenswert?

DerLiebeProf schrieb:

> Gerne. Falls Sie am Wochenende noch was machen: Die ISR ist nur für den
> Zähler da und soll sonst nichts machen und die wait... Routinen dürfen
> den counter natürlich nicht ändern.

Danke für die Info @DerLiebeProf, ich wollte mich gleich nochmal dran 
setzen.
Die wait Routinen in meiner .cpp sind Überbleibsel aus vorherigen 
Versuchen,
die hatte ich vergessen vor dem Hochladen zu entfernen :) .
#6492908
Lesenswert?

Hallo DerLiebeProf,

ich weiß zwar nicht was du für ein Spassvogel bist, du kannst sonstwer 
sein hinter einem Gastnamen, aber mit "Betreuer" können ja nur wir hier 
gemeint sein. Und falls du doch der echte Prof sein solltest, was ich 
nicht glaube, dann gib mal die komplette Aufgabenstellung bekannt.
Gast #6492975
Lesenswert?

Aufgabe ist, kurz gesagt, eine Art „wallclock“ zu implementieren, die 
die Zeit in ms seit dem letzten Reset zählt plus zwei Funktionen 
waitFor(ms) und waitUntil(ms), sowie passenden Testcode dazu.
#6493024
Lesenswert?

DerLiebeProf schrieb:
> Veit D. schrieb:
>> aber mit "Betreuer" können ja nur wir hier
>> gemeint sein.
>
> Warum?

Guten Abend,

weil wir hier Heinz betreuen.  :-)

> Aufgabe ist, kurz gesagt, eine Art „wallclock“ zu implementieren, die
> die Zeit in ms seit dem letzten Reset zählt plus zwei Funktionen
> waitFor(ms) und waitUntil(ms), sowie passenden Testcode dazu.

Demzufolge wird es kein Blinktakt. Im Grunde wird die millis() und 
delay() Funktion von Arduino nachprogrammiert. Oder auch delay() von 
avr. Okay, für Programmieranfänger ist das schon eine Herausforderung. 
Ich hoffe die Studenten wurden nicht ins zu kalte Wasser geworfen.
Gast #6493110
Lesenswert?

Hat das bisher noch keiner geschnallt?

Prescaler 1/64, dann irgendein 8(oder mehr)-Bit Counter, der CTC
kann mit 1/250. (Max-Count = 249)

16.000.000 / (64 x 250) = 16.000.000 / 16.000 = 1.000

JEDER Compare-Interrupt am gleichen Timer zwischen
Compare-Wert = 1...249 erscheint im 1,000 ms-Rhythmus.
Manchmal klappt es auch beim Overflow-Interrupt.
- Guckst du...

Noch Fragen?
Wahrscheinlich kommen die dann von den 56 Null-Schnallern davor...


Gute Nacht.
Gast #6493137
Lesenswert?

Veit D. schrieb:
> Übrigens, ein ATmega328P Timer 0 hat keinen Prescaler 128.
Hä?
Oh....*Timer* prescaler ... stimmt; mein Fehler!
ich war beim CLKPR (nein, hab ich fehlinterpretiert, steht nirgendwo ;)
hab mich ehrlich gesagt auch n bisschen gewundert, dass der bis 1024 
aber mir nix bei gedacht)
das erklärt auch warum dein gedanklicher ISR schneller läuft als meiner

Salute

'sid
Gast #6493653
Lesenswert?

Jetzt weg mit dem Troll schrieb:
> Eine Zeitmessung macht man doch nicht mit einem 1ms clock. sondern mit
> dem Timercapture. Das ergibt eine viel bessere Aufloesung.

Kommt drauf an, welche Auflösung mach braucht. Für eine Eieruhr sind 
Millisekunden mehr als genug.

Viel bessere Auflösung heißt wohl weniger als 1ms Intervalle. Vergiss 
dabei nicht, dass der 8/16 bit Timer irgendwann überläuft.

Aber das alles hilft dem TO nicht, denn es würde an seiner Aufgabe 
vorbei gehen.
Gast #6493675
Lesenswert?

> Eine Zeitmessung macht man doch nicht mit einem 1ms clock. sondern mit
> dem Timercapture. Das ergibt eine viel bessere Aufloesung.
Man kann nur das capturen, was zuvor schon gezählt wurde.
Und auch ns-genaue (Timer)Abfrage kommt es hier mit Sicherheit nicht an.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren