Forum: Mikrocontroller und Digitale Elektronik Programm Läuft um Faktor 10 flasch


von Philipp L. (viech)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

mein Atmega88 ist auf int. 8Mhz "gefused".
Auch im AtmelStudio habe ich die F_CPU=8000000UL angegeben.

Wenn ich jetzt mit folgendem Code meinen Ausgang setzte, ist dieser 
(oszi) genau 82us eingeschaltet.
Das ist ca. Faktor 10 + etwas ungenauigkeit ?

ISR (INT0_vect)
{
PORT_D7 = 1;
_delay_us(10);
PORT_D7 = 0;

komisch ist, dass die Zeit bei weglassen der Definition F_CPU=8000000UL 
~korrekt ist.
Jedoch bringt er dann den Fehler F_CPU not defined..

Was kann der Fehler sein?

von flacher ball (Gast)


Lesenswert?

Philipp L. schrieb:
> komisch ist, dass die Zeit bei weglassen der Definition F_CPU=8000000UL
> ~korrekt ist.
> Jedoch bringt er dann den Fehler F_CPU not defined..

wie geht das?

von Jan B. (do9jhb)


Lesenswert?

Philipp L. schrieb:
> Hallo zusammen,
>
> mein Atmega88 ist auf int. 8Mhz "gefused".
> Auch im AtmelStudio habe ich die F_CPU=8000000UL angegeben.
>
> Wenn ich jetzt mit folgendem Code meinen Ausgang setzte, ist dieser
> (oszi) genau 82us eingeschaltet.
> Das ist ca. Faktor 10 + etwas ungenauigkeit ?

Genauer gesagt läuft es um Faktor 8 falsch, das kommt dadurch dass die 
CPU tatsächlich mit 1 MHz läuft... Mach Mal den 8er Vorteilen 
(LOW.CKDIV8 Fuse) weg, dann sollte es richtig funktionieren...

von Chris L. (kingkernel)


Lesenswert?

Du hast in den Screenshot noch die CKDIV8-Fuse gesretzt, die teilt den 
Takt nochmal durch 8. Also hast du reell nur noch 1MHz

von Mario M. (thelonging)


Lesenswert?

Wenn F_CPU nicht gesetzt ist, wird die Warnung ausgegeben und F_CPU auf 
1MHz gesetzt. Dass das Timing dann stimmt, spricht dafür, dass der 
Controller mit 1 MHz läuft, also CKDIV8 aktiv ist.

von flacher ball (Gast)


Lesenswert?

Mario M. schrieb:
> wird die Warnung ausgegeben

yes, that s it, thx

von Philipp L. (viech)


Lesenswert?

Vielen Dank, das war auch das Problem der restlichen Programmfehler.

Aber:
Mit folgendem Code müsste ich doch nun genau auf 87us kommen.
Hatte ich auf dem Mega8 mit Timer2 auch schon gemessen, muss aber nun 
auf Mega88 und Timer0 umstellen.

Ich messe nun aber 92us (also +5us).

Auszug der Intitialisierung:
OCR0A=87;                        //Compareregister
TCCR0A |= (1<<WGM00)+(1<<WGM01); //Fast PWM mit TOP=0xFF
TCCR0B |= (1<<CS01);             //Prescaler=8
TCNT0 = 0;                       //Aktuellen Zählerstand=0;
TIMSK0 |= (1<<OCIE0A);           //CompareA=Ein

ISR (INT0_vect)
{
PORT_D7 = 0;
TCNT0 = 0;
}

ISR (TIMER0_COMPA_vect)
{
PORT_D7 = 1;
}

: Bearbeitet durch User
von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Du gehst davon aus das die 8 MHz stimmen. Tun sie aber nicht.

Und dein Quelltext dürfte auch noch genug Fehler haben...

: Bearbeitet durch User
von Philipp L. (viech)


Lesenswert?

> Du gehst davon aus das die 8 MHz stimmen. Tun sie aber nicht.
Beim Mega8 (DIP auf Steckbrett) sind es mit dem code (auf Timer2) ganz 
genau 87us.
Gehen die MLF´s nach der Reflow-Behandlung denn soo falsch?

> Und dein Quelltext dürfte auch noch genug Fehler haben...
Von Quellcode (siehe oben) kann man dabei eher nicht sprechen.
Ich schalte in der ISR doch nur den Ausgang.

: Bearbeitet durch User
von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Philipp L. schrieb:
>> Du gehst davon aus das die 8 MHz stimmen. Tun sie aber nicht.
> Beim Mega8 (DIP auf Steckbrett) sind es mit dem code (auf Timer2) ganz
> genau 87us.
Timer2 ist das mit TCCR0 aber nicht, 87us sind Zufall.

> Gehen die MLF´s nach der Reflow-Behandlung denn soo falsch?

Der RC Takt ist Produktions, Temperatur und Spannungsabhängig. Kann aber 
kalibriert werden.

>
>> Und dein Quelltext dürfte auch noch genug Fehler haben...
> Von Quellcode (siehe oben) kann man dabei eher nicht sprechen.
> Ich schalte in der ISR doch nur den Ausgang.

Alleine was man da schon sieht... Beschreib doch mal EXAKT was der Code 
GENAU machen soll, nicht das Fernziel sondern nur der Testcode.

von Philipp L. (viech)


Lesenswert?

> Alleine was man da schon sieht... Beschreib doch mal EXAKT was der Code
> GENAU machen soll, nicht das Fernziel sondern nur der Testcode.

Das Gesamtprogramm funktioniert mit exaktem Takt und bedarf daher 
aktuell keiner Detailbeschreibung (DCC-Dekoder).

Mit dem Testcode teste ich doch nur den Takt...
Dies soll folgendes machen:
Bei int0 (kommt regelmäßig) -> Ausgang ausschalten und Timer0 rücksetzen
Bei Timer0-compareA (nach 87us) -> Ausgang einschalten

> Timer2 ist das mit TCCR0 aber nicht
Beim Mega8 auf Timer 2 ist es natürlich eine andere Initialisierung, 
schon richtig.
Hier beziehe ich mich ja auf das aktuelle Problem und nicht auf die 
funktionierende Steckbrettvariante..

>87us sind Zufall.
8Mhz Takt
Prescaler 8 beim Timer = 1Mhz
Compare = 87

Da sind 87us eher kein Zufall...

: Bearbeitet durch User
von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> Mit folgendem Code müsste ich doch nun genau auf 87us kommen.

Zum einen beginnt ein Timer bei 0, man muss bei OCR0A also 1 abziehen. 
Zum anderen vergeht nach dem Erreichen des Compare-Werts eine gewisse 
Zeit (Latenz), bis das Port-Schalten in der ISR erreicht wird, wieviel 
genau muss ein C-Kenner sagen. Für Assembler siehe den Datenblattauszug 
im Anhang.

von Wolfgang (Gast)


Lesenswert?

Philipp L. schrieb:
> Ich messe nun aber 92us (also +5us).

Was fummelst du auch in der ISR am Zählstand rum. Wenn deine Latenz 
höher ist, als die Periode des Timertaktes, verlierst du Schritte, d.h. 
die Zeit verlängert sich.
Lass deine Routine einfach mal im Simulator oder mit Debugger laufen und 
guck dir an, was der Timer macht, während in die ISR gesprungen und die 
Register gesichert werden.

von Axel S. (a-za-z0-9)


Lesenswert?

Philipp L. schrieb:
> Mit folgendem Code müsste ich doch nun genau auf 87us kommen.
> Ich messe nun aber 92us (also +5us).
>
> Auszug der Intitialisierung:
> OCR0A=87;                        //Compareregister
> TCCR0A |= (1<<WGM00)+(1<<WGM01); //Fast PWM mit TOP=0xFF
...
> ISR (TIMER0_COMPA_vect)
> {
> PORT_D7 = 1;
> }

Was soll das Setzen von PD7 in der ISR? Der Sinn einer Hardware-PWM 
besteht doch genau darin, daß die Hardware die Pins wackeln läßt und man 
nicht mehr den unkalkulierbaren Zeitversatz für den Aufruf der ISR drauf 
hat.

von Vollpfostenberater (Gast)


Lesenswert?

Axel S. schrieb:

> Was soll das Setzen von PD7 in der ISR?

Na was wohl? Soll er die 87µs dem Oszi durch gut Zureden mitteilen?

Deine Fragen werden von Tag zu Tag intelligenter.

von Wolfgang (Gast)


Lesenswert?

Vollpfostenberater schrieb:
> Na was wohl? Soll er die 87µs dem Oszi durch gut Zureden mitteilen?

Nein, er könnte das Oszi an den OC0A Pin hängen.

> Deine Fragen werden von Tag zu Tag intelligenter.
Wer im Glashaus sitzt ...

von Stefan F. (Gast)


Lesenswert?

Vollpfostenberater schrieb:
>> Was soll das Setzen von PD7 in der ISR?
> Na was wohl? Soll er die 87µs dem Oszi durch gut Zureden mitteilen?
> Deine Fragen werden von Tag zu Tag intelligenter.

Bist du ganz sicher, verstanden zu haben, wie ein PWM Timer 
funktioniert? Ich empfehle dir, das entsprechende Kapitel im 
Datenblatt in Ruhe zu lesen und ggf. fragen zu stellen, falls etwas 
unklar ist.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Eigentlich ist es ja lächerlich bei den Vorraussetzungen weiter zu 
machen aber was solls, ist Wochenende:

- er "benutzt" den Fast PWM Mode, lässt aber keinen Pin direkt davon 
ansteuern, macht also keinen Sinn.
- bastelt sich dann den Compare Interrupt, in dem er den Pin setzt, 
dafür braucht es keinen PWM Mode, aber geht.
- dann wird der Pin zu beliebigen, von Aussen bestimmten, Zeitpunkten 
zurück gesetzt, eben wenn ein Int0 kommt, warum auch immer.
- diverse Ungenauigkeiten (nicht kalibrierte RC Clock, Latenz der ISRs) 
kommen auch noch dazu.

Und trotzdem soll das Ding genau 87us haben? (was eigentlich? Periode, 
high, low? Aber eigentlich auch egal weil es die 87us wenn überhaupt nur 
zufällig hat.)

Das Ganze mal abgesehen davon das mir die PORT_XY = 1/0 Syntax nicht 
geläufig ist, aber ich benutze auch noch das 4.19 AVR Studio, würde aber 
auf irgendein selbstgebasteltes/kopiertes/sonstwas Makro tippen, dessen 
genaue Funktion ich aber nicht kenne.

: Bearbeitet durch User
von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

an Philipp L.

Zum Ausprobieren und als Denkanstoß.

von Philipp L. (viech)


Lesenswert?

Tim T. (tim_taylor)
Du bist immer sehr schnell mit Kritik...
Das ist ja okay, aber kritisiere doch bitte keinen mehrfach als test 
bezeichneten Code:
Das ich in der PWM-ISR manuell einen Ausgang setze, ist doch nur mal 
schnell für die Zeitkontrolle am Oszi gewesen.

Ich habe einen externen Interrupt (positive Flanke am int0) und möchte 
jedesmal genau 87us nach diesem interrupt ein paar Befehle ausführen.
Der nächste Interrupt am int0 kommt frühestens nach 116us und stört 
daher nicht.

Bestimmt kann man das auch besser machen, aber darum geht es hier doch 
überhaupt nicht.

Dieses Vorgehen funktioniert ebenfalls mit compare=87 auf dem mega8 
(dip) und timer2 im fast-pwm ganz exakt mit 87us..

Die Frage war:
Sollte der oben gelistete Code nicht auch auf diesem mega88 genau 87us 
nach int0 den Ausgang schalten?
Funktioniert ja auf dem mega8 (steckbrett) auch..

Die Frage war nicht:
Ist das die allerbeste Vorgehensweise.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Und dann eben nochmal: Mit dem Programm und der Taktquelle sind die 87us 
ZUFALL.

von Stefan F. (Gast)


Lesenswert?

Vom Interrupt-Ereignis bis zur Ausführung der Interruptroutine vergehen 
einige Takte, mal mehr mal weniger. Bei Eintritt in die Interruptroutine 
werden einige Register auf den Stack gesichert, bevor dein I/O Pin 
gesetzt wird.

Pi mal Daumen würde ich hier von bis zu 12 Takten ausgehen. Bei deinen 
1MHz Systemtakt macht das bis zu 12ms Verzögerung aus.

von my2ct (Gast)


Lesenswert?

Tim T. schrieb:
> Und dann eben nochmal: Mit dem Programm und der Taktquelle sind die 87us
> ZUFALL.

Reiner Zufall wird es wohl eher nicht sein, sondern seinen Grund haben.

Der µC macht genau das, was man ihm gesagt hat. Also stimmt einfach nur 
die Erwartung nicht mit den tatsächlichen Abläufen überein. Um diese 
Diskrepanz zu klären, muss man dem µC genau auf die Finger schauen. Nur 
so kann man feststellen, was ihn daran hindert, den Pin nach 87µs zu 
wackeln.

Betrachtung im Simulator, Debugger und der tatsächlich ablaufende Code - 
µC-Takt für µC-Takt - werden die Lösung offenbaren. Ein Fehler im µC 
wäre mit hoher Wahrscheinlichkeit wohl anderen schon aufgefallen.

von Dieter F. (Gast)


Lesenswert?

Stefanus F. schrieb:
> macht das bis zu 12ms Verzögerung aus.

Das würde ich aber nochmal nachrechnen :-)

von S. Landolt (Gast)


Lesenswert?

> Dieses Vorgehen funktioniert ebenfalls mit compare=87 auf dem mega8
> (dip) und timer2 im fast-pwm ganz exakt mit 87us..

Glück gehabt!
  Setzen Sie mal beim ATmega8 den Systemtakt von 8 MHz auf 1 MHz 
herunter und als Ausgleich den Vorteiler von Timer2 von 8 auf 1. Dann 
sollten Sie doch auch wieder "exakt 87 us" erhalten, oder? Ich wette 
mein Rennrad gegen einen Tretroller, dass das nicht der Fall ist.

von Ralph S. (jjflash)


Lesenswert?

Stefanus F. schrieb:
> Pi mal Daumen würde ich hier von bis zu 12 Takten ausgehen. Bei deinen
> 1MHz Systemtakt macht das bis zu 12ms Verzögerung aus.

12 Takte bei 1MHz würden 12 Microsekunden machen (und nicht 
Millisekunden).

Die Responsetime des ATmega beträgt nach Datenblatt min. 4 Zyklen (macht 
bei 1MHz Systemtakt schon mal 4 µS).

Ich würde dieses Teil wieder mit 8 MHz laufen lassen (und nicht mit 1 
MHz)  und den Timer 0 hierfür neu berechnen, damit die 4 Taktzyklen 
Responsetime nicht mehr so satt ins Gewicht fallen dürften.

Abgesehen davon hat der interne Oszillator (wie oben schon geschrieben) 
so seine Toleranzen. 2% bis 3% sind normal, 5% wären viel aber imho noch 
zulässig und das ganze ist dann auch noch temperaturabhängig.

von Stefan F. (Gast)


Lesenswert?

Dieter F. schrieb:
> Stefanus F. schrieb:
>> macht das bis zu 12ms Verzögerung aus.
>
> Das würde ich aber nochmal nachrechnen :-)

Sorry, ich meinte natürlich 12µs

von Axel S. (a-za-z0-9)


Lesenswert?

Philipp L. schrieb:
> Das ich in der PWM-ISR manuell einen Ausgang setze, ist doch nur mal
> schnell für die Zeitkontrolle am Oszi gewesen.

Und war gerade deswegen eine blöde Idee <tm>

> Ich habe einen externen Interrupt (positive Flanke am int0) und möchte
> jedesmal genau 87us nach diesem interrupt ein paar Befehle ausführen.

Nach genau 87µs oder nur nach "genau" 87µs? Und geht es wirklich 
darum, daß nach dieser Zeit "Befehle ausgeführt" werden, oder nicht doch 
eher darum, daß dann eine Reaktion zur Außenwelt erfolgen soll?

> Bestimmt kann man das auch besser machen, aber darum geht es hier doch
> überhaupt nicht.

Du hast dich doch beschwert, daß die Zeit nicht eingehalten wird. Du 
meintest also, es wäre nicht gut genug und es müßte folglich besser 
gemacht werden.

> Die Frage war:
> Sollte der oben gelistete Code nicht auch auf diesem mega88 genau 87us
> nach int0 den Ausgang schalten?

> Die Frage war nicht:
> Ist das die allerbeste Vorgehensweise.

Die Frage wäre eher: ist das überhaupt eine geeignete Vorgehensweise, 
um die 87µs mit der geforderten (aber uns nach wie vor unbekannten) 
Genauigkeit einzuhalten? Und die Antwort hat dir dein Mega88 laut und 
deutlich ins Gesicht gebrüllt: NEIN.

von M. K. (sylaina)


Lesenswert?

Ralph S. schrieb:
> Abgesehen davon hat der interne Oszillator (wie oben schon geschrieben)
> so seine Toleranzen. 2% bis 3% sind normal, 5% wären viel aber imho noch
> zulässig und das ganze ist dann auch noch temperaturabhängig.

Und spannungsabhängig auch noch ;)

von S.I. (Gast)


Lesenswert?

Ralph S. schrieb:
> Die Responsetime des ATmega beträgt nach Datenblatt min. 4 Zyklen (macht
> bei 1MHz Systemtakt schon mal 4 µS).

Mit Leitfähigkeiten hat das ganze Problem überhaupt nichts zutun, zumal 
ein Wert von 4µS fast schon für einen Isolator steht. Und vom Systemtakt 
wäre die schon gar nicht abhängig.

von Stefan F. (Gast)


Lesenswert?

S.I. schrieb:
> Mit Leitfähigkeiten hat das ganze Problem überhaupt nichts zutun

Das haben schon alle so verstanden, wie es gemeint war. Nur du nicht, 
weil du es nicht verstehen wolltest.

von Arno (Gast)


Lesenswert?

Nochmal zusammengefasst, was dir hier schon einige aufgeschrieben haben:

So ist der Ablauf:

1) Flanke an Pin löst externen Interrupt aus
2) Verzögerung bis zum Aufruf der ISR (inklusive Register sichern etc.) 
mindestens 4 Takte, mit Register sichern mehr, bei 1MHz also mindestens 
4µs (sperrst du in der Hauptschleife zeitweise die IRQs?)
3) Pin D7 wird auf 0 gesetzt
4) Timer wird - mindestens* einen Takt später, bei 1MHz also mindestens 
1µs später - auf 0 gesetzt
5) 87µs +- Ungenauigkeit des RC-Oszillators vergehen
6) Compare-Interrupt wird ausgelöst
7) Verzögerung bis zum Aufruf der ISR (inklusive Register sichern etc.) 
mindestens 4 Takte, mit Register sichern mehr, bei 1MHz also mindestens 
4µs
8) Pin D7 wird auf 1 gesetzt

Nun weiß ich nicht, ob du mit dem Oszi die Zeit von der Flanke in 
Schritt 1 bis zur Flanke in Schritt 8 misst oder von der Flanke in 
Schritt 3 bis zur Flanke in Schritt 8, aber definiert 87µs ist nur 
Schritt 5.

Und das auch nur mit der Genauigkeit des RC-Oszillators, der schonmal 
einige Prozent daneben liegen kann.

MfG, Arno

*mindestens, weil ich nicht weiß, wie PORT_D7 = 0 in Assembler übersetzt 
wird, das Konstrukt kenne ich so nicht.

von S.I. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Nur du nicht, weil du es nicht verstehen wolltest.

Ich habe nur in Worte gefasst, was Ralph geschrieben hat.
Vielleicht meint er auch "8MHz", wenn er "1MHz" schreibt, weil er sich 
angewöhnt hat die 8 als "1" zuschreiben. Kann jeder machen, wie er 
möchte - kann aber durchaus auch mal nach hinten los gehen.

von Ralph S. (jjflash)


Lesenswert?

4µs ... zufrieden ?

SEKUNDEN und nicht SIEMENS !

Darf man das überhaupt groß schreiben? SEKUNDEN ? Oder verstehen es 
deutsche Menschen nur dann, wenn es Sekunden heißt?

Liest ein Elektroniker automatisch SIEMENS (oder Siemens?) wenn es um 
Zeit geht?

Und warum brennt nacht im Kühlschrank das Licht, wenn die Leitfähigkeit 
zur Lampe nur 4µS beträgt (das s jetzt GROSS geschrieben S ... und bitte 
als Siemens zu lesen)?

Sind dann 3,66mh eine Sekunde oder ist das jetzt eine falsch 
geschriebene Spule?

Mein lieber Henry aber Siemens auch, Herr Isaac Ohm (oder hieß der 
Newton, Tesla oder Heinrich der 8. von Hertzen) dreht sich bestimmt im 
Stromkreisgrabe um?

By the way, wenn das alles irgendwie Namen von Verstorbenen sind, warum 
finde ich dann keinen Menschen, der Sekunde oder Seconds mit Nachnamen 
heißt?

Hab ich da was verpasst? Okay, ich bin ungebildet und gebe an die besser 
gebildeten ab !

Beitrag #5811132 wurde von einem Moderator gelöscht.
von Stefan F. (Gast)


Lesenswert?

Ralph S. schrieb:
> Hab ich da was verpasst?

Ja: den knall.

Jeder normale Mensch versteht trotzt des kleinen Rechtschreibfehlers, 
was gemeint war.

von Cyblord -. (cyblord)


Lesenswert?

Ralph S. schrieb:
> Hab ich da was verpasst? Okay, ich bin ungebildet und gebe an die besser
> gebildeten ab !

Korrekte Terminologie ist wichtig. Und dazu gehören auch die korrekten 
Einheiten. Wenn man sich das gleich richtig angewöhnt tut es nicht weh 
und man muss später nicht in Foren deshalb rumheulen.
Das hat auch nichts mit Bildung zu tun sondern mit Sorgfalt.

: Bearbeitet durch User
von Arno (Gast)


Lesenswert?

Taiga Wutz schrieb im Beitrag #5811132:
> Philipp L. schrieb:
>> Das Gesamtprogramm funktioniert mit exaktem Takt und bedarf daher
>> aktuell keiner Detailbeschreibung (DCC-Dekoder).
>
> Für DCC sind aber andere Zeiten als 87µs gebräuchlich. Siehe hier:
>
> http://www.miba.de/morop/nem670_d.pdf

OT: 87µs sind "die Mitte" zwischen 58µs und 116µs - das ist genau der 
richtige Abtastzeitpunkt, um festzustellen, ob ein Puls 58µs oder 116µs 
lang ist.

MfG, Arno

von Dieter F. (Gast)


Lesenswert?

Arno schrieb:
> OT: 87µs sind "die Mitte" zwischen 58µs und 116µs - das ist genau der
> richtige Abtastzeitpunkt, um festzustellen, ob ein Puls 58µs oder 116µs
> lang ist.

Und da kommt es dann auf 10 µs mehr oder weniger an? Pah... :-)

Da soll er den Timer halt mit den ca. 8 MHz laufen lassen - dann spielt 
der Prolog der ISR nicht die entscheidende Rolle und das Bit wird 
zuverlässig erkannt.

Beitrag #5811404 wurde vom Autor gelöscht.
von Philipp L. (viech)


Lesenswert?

Mich hat doch nur gewundet, warum das "gleiche" Programm beim Mega8 und 
Mega88 so unterschiedliche Zeiten ergibt.
Es ist ja kein Problem, ich passe den compare auf 82 an und alles ist 
gut.
Auch ist die Genauigkeit für DCC auch so schon ausreichend.

Ich hätte beide Codes mit beiden Oszi-Auswertungen vernünftig 
nebeneinander stellen sollen.

Arno schrieb:
> Nochmal zusammengefasst, was dir hier schon einige aufgeschrieben haben:
Ja, habe ich mitgenommen -> Danke!

Am besten wir brechen den Thread hier ab, besser wirds nicht mehr :-)
Dann folgt gleich eine hofffentlich echte Frage in neuem Thread.

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
Noch kein Account? Hier anmelden.