Takt je Schleife berechnen

OP #2156430
Lesenswert?

Hey, ich will eine Zeitverzögerung mit dem runterzählen in einer 
schleife erreichen.

Der code in bascom sieht so

aus

While A<>B
B=B+1
Wend

Die Bascom Simulation sagt mir das die schleife 71 Takte braucht (A und 
B als long)

Berechnen ich nun A für 5 minuten und lasse solange zählen bis A=B 
(67605633) und lasse das auf dem Mikrocontroller laufen (danach geht 
eine led an) mit 16 Mhz laufen, dann komme ich auf ca. 5 min und 9 
sekunden.
Das ist ja schon arg ungenau. Stimmt das mit den 71 Takten wohlmöglich 
nicht?
#2156441
Lesenswert?

@  Felix A. (flakki)


>Hey, ich will eine Zeitverzögerung mit dem runterzählen in einer
>schleife erreichen.

Kann man machen, ist aber ungenau und nervig. Nimm einen Timer, ist 
1000mal besser und gar nicht schwer.

>Berechnen ich nun A für 5 minuten und lasse solange zählen bis A=B
>(67605633) und lasse das auf dem Mikrocontroller laufen (danach geht
>eine led an) mit 16 Mhz laufen, dann komme ich auf ca. 5 min und 9
>sekunden.
>Das ist ja schon arg ungenau. Stimmt das mit den 71 Takten wohlmöglich
>nicht?

Siehe oben.

MFG
Falk
Gast #2156461
Lesenswert?

Felix A. schrieb:
> Mein Problem mit den Timern ist nur, das ich dann alle 3
> Mikrosekunden einen interrupt im Hauptprogramm hätte. Das wollte ich nun
> mit dem runterzählen vermeiden.

Wenn du dich mit dem Timer ernsthaft befaßt hättest, wüßtest du, dass 
das nicht so ist. Abgesehen davon: Wieso stört das dein Hauptprogramm, 
wenn du das Timing über Timer machst?
Gast #2156471
Lesenswert?

Felix A. schrieb:
> ja, ich will es aber nicht mit timern machen, da ich alle 2 bis 3
> mikrosekunden auflösung haben will

Du mußt 5 Minuten lang warten mit einer Auflösung von 2 Mikrosekunden?

> und das hauptprogramm nicht unterbrochen werden soll.

Wärend deiner Warteschleife steht das Hauptprogramm doch komplett.
OP #2156524
Lesenswert?

also vielleicht sollte ich das nochmal erklären:

Ich will doch nur in einer schleife runterzählen bevor etwas passiert. 
Und bei 16 Mhz macht der doch einen befehl pro 0,0625 mikrosekunden.
Damit kann ich sehr wohl mit 2 mikrosekunden genauigkeit arbeiten.
Selbst mit der while schleife in bascom brauche ich für einen durchlauf 
nur 4,3 mikrosekunden. Ich will doch nur wissen, warum der Fehler auf 
dem Controller ensteht und was man dagegen machen kann.
OP #2156535
Lesenswert?

Ich meine den Fehler von 9 sekunden (Post 1).

Ich will nach einem Interrupt eine Einspritzdüse öffnen, dann xxx 
Mikrosekunden auf lassen, und dann wieder schließen.
Die schleife beginnt also nach dem interrupt. Das Problem bei der düse 
ist dabei, das ich möglichst auf die Mikrosekunde genau einstellen 
können muss.
Gast #2156540
Lesenswert?

Ich hasse Salamitaktik.

Wie oft (pro Sekunde) soll diese Düse angesteuert werden?

Die Düse regelmäßig für 2µs zu öffnen ist mit etwas Assembler kein 
Problem, die Düse alle 2 µs anzusteuern schon.
Gast #2156548
Lesenswert?

10ms sind schon deutlich besser, mit einem Timer(interrupt) lässt das 
dem µC noch Zeit um andere Sachen zu machen.

Die 2µs Wartezeit erreichst du am besten mit ein paar nops oder einer 
Zählschleife in Inline-Assembler. Guck in die Bascomanleitung und hier 
ins ASM-Tutorial.

War ja mal wieder eine schwere Geburt.
#2156549
Lesenswert?

Felix A. schrieb:
> Ich will nach einem Interrupt eine Einspritzdüse öffnen, dann xxx
> Mikrosekunden auf lassen, und dann wieder schließen.

Sowas macht man nicht in einer Schleife.

Dazu nimmt man einen Timer im CTC-Modus.

Nach dem Interrupt schaltest du einen Port, startest den Timer und der 
schaltet nach der im Compare-Register eingestellten Zeit den Port wieder 
ab.

mfg.
#2156567
Lesenswert?

Felix A. schrieb:
> Ich will nach einem Interrupt eine Einspritzdüse öffnen, dann xxx
> Mikrosekunden auf lassen, und dann wieder schließen.

Gut. Meine Lösung wäre:

16-Bit-Timer durchlaufen lassen.

ICP-Interrupt benutzen, darin Düse aufmachen, ICP-Wert holen, Intervall 
draufaddieren, als Compare-Wert für Compare-Interrupt abspeichern, 
Compare-Interrupt freigeben.

Im Compare-Interrupt Düse zumachen, Compare-Interrupt sperren.

Das Hauptprogramm kann währenddessen die Drehzahl erfassen und daraus 
das optimale Intervall berechnen.

In ASM kinderleicht, in C sicherlich auch, in Bascom wird das Timing 
verfälscht, weil der Interrupt-Aufruf auch die Register sichert, die 
nicht gebraucht werden.

...
#2156575
Lesenswert?

Thomas Eckmann schrieb:
> Sowas macht man nicht in einer Schleife.
>
> Dazu nimmt man einen Timer im CTC-Modus.
>
> Nach dem Interrupt schaltest du einen Port, startest den Timer und der
> schaltet nach der im Compare-Register eingestellten Zeit den Port wieder
> ab.
>
> mfg.

es macht wohl wenig sinn wegen 2µs einen Timerinterupt aufzusetzen
2µs sind 64 Takte bei 16Mhz die paar Takte sind mit Initialisieren des 
Timers und Sprung in die ISR schon fast verbraten

edit:
ich würde einen 10ms Timer aufsetzen und in dessen ISR das Öffnen, 
warten und Schließen des Ventils unterbringen.
Gast #2156578
Lesenswert?

netiquette schrieb:
> 10ms sind schon deutlich besser, mit einem Timer(interrupt) lässt das
> dem µC noch Zeit um andere Sachen zu machen.
>
> Die 2µs Wartezeit erreichst du am besten mit ein paar nops oder einer
> Zählschleife in Inline-Assembler. Guck in die Bascomanleitung und hier
> ins ASM-Tutorial.
>
> War ja mal wieder eine schwere Geburt.
OP #2156580
Lesenswert?

so ähnlich war meine erste idee auch... dann ist mir aber beim 
programmieren aufgefallen, das das programm gar nichts anderes machen 
braucht. und vielmehr zwischen do und loop umherspringt. Deswegen die 
idee mit der verzögerung. Im Prinzip soll es so klappen: (habe einen 
magneten am schwungrad)

1. Interrupt (magnet) erfassen > Zündzeitpunkt berechnen > schleife 
zählt bis zündzeitpunkt >zünden > schleife zählt aber weiter nach dem 
zünden bis zum 2. Magneten d.f. Drehzahlerfassung

2. Interrupt (magnet) > Berechnung der Öffnungsdauer > Düse öffnen > 
schleife zählt > dües schließen

Und dann beginnt alles von vorne. Vorteilhaft an diesem konzept finde 
ich, das es eine feste Struktur hat und immer von oben nach unten 
abgearbeitet wird. Allerdings muss ich die Berechnungszeit des 
Zündzeitpunktes wieder vom Kurbelwinkel abziehen. Das ganze Konzept 
klappt dann aber nur wenn ich von den schleifen die anzahl der takte 
kenne. Deshalb auch meine Frage ganz oben in Post 1. Achso, es ist 
natürlich ein 4-Takter.
OP #2156592
Lesenswert?

der Zündzeitpunkt soll ertstmal linear zur drehzhal sein, damit sollte 
die berechnungszeit immer gleich sein. die düse muss etwa 700 
mikrosekunden auf sein. Sie ist aber sehr empfindlich, deshalb muss ich 
sie so genau einstellen. +-5 mikrosekunden wäre schon wieder zu ungenau.
Gast #2156745
Lesenswert?

Thomas Eckmann schrieb:
> Felix A. schrieb:
>> die düse muss etwa 700 mikrosekunden auf sein.
>
> Also was soll denn jetzt der ganze Aufstand?
>
> "etwa 700". 700,000 oder vielleicht doch 694?
>
> Mal wieder viel Lärm um nichts.
>
> mfg.

Also jetzt ist doch mal gut, meine Frage war von anfang an wie der 
Fehler (Post 1) zustande kommt. dafür ist es dann auch unerheblich wie 
lange ich die schleife durchlaufen möchte.
#2156755
Lesenswert?

Sei so gut und tu dir selber den Gefallen und mache was Falk dir geraten 
hat. Der gute Mann hat von Mikrocontrollern mehr Ahnung als ein 
Uni-Professor und die 100 Andere die hier mitlabern.

Aber ist klar - die Anfänger müssen immmer das Rad neu erfinden, das 
worüber sich tausende vor ihnen Gedanken gemacht haben und als gut 
erachtet haben ignorieren und wissen alles besser ... Anfänger eben.
Gast #2157611
Lesenswert?

Felix A. schrieb:
> also vielleicht sollte ich das nochmal erklären:
>
> Ich will doch nur wissen, warum der Fehler auf
> dem Controller ensteht und was man dagegen machen kann.

Der Fehler entsteht nicht auf dem Controller.
Der fehler sitzt da, wo er meistens sitzt: Vor der Tastatur...
#2157627
Lesenswert?

tt2t schrieb:
>> Er hat doch nur den Hinweis mit dem Timer gegeben oder hab ich was
>> übersehen?
>
> strg-f falk

Ich glaube, Du interpretierst da was falsch.

Falk hat damit zum Ausdruck gebracht, dass es sinnlos ist, Felix helfen 
zu wollen. Denn Felix sagt "Danke" und denkt "leck mich" und ignoriert 
alle gut gemeinten Hinweise. Er ist so auf seine Bascom-Schleife 
fixiert, dass er nicht erkennt, das es anders viel besser, 
zuverlässiger, genauer und einfacher geht.

Da ich das inzwischen ähnlich sehe, habe ich meinen Beitrag mit einem 
etwas erweiterten Konzept wieder gelöscht.

...
Gast #2157640
Lesenswert?

Hallo.

Ich hab nur den Anfang gelesen... Das Takte zählen klingt recht mühsam. 
einfacher wäre es doch wirklich wenn Du einen Timer antriggerst und wenn 
du schon busywaiting machst, weil sonst nix  zu erledigen ist, dann 
könntest so machen, dass du wartest bis in der timer-isr en flag gesetzt 
wird (in pseudoC):
1
gFlag = 0;
2

3
void interrupt TIMER(void)    // isr kommt wenn eingestellter wert erreicht 
4
{
5
    gFlag = 1;
6
    clr_timer_run-bit();
7
    timer_reg = 0;    // zählt wenn du wieder antriggerst dann bei 0 weg 
8
    clr_isr_flag();
9
} 
10

11

12
void main(void)
13
{
14
  ...
15
  gFlag = 0;
16
  trigger_Timer();   // setze Run-bit
17
  while(!gFlag);
18
  // gFlag = 0;  falls nötig
19
  ...
20
}

oder stört dich da sogar die paar ns von MOV und BRA und paar cycles für 
isr-switch?

wegen dem Fehler: BASCOM ist ja so interpreter-sache und ich hab keine 
ahnung wie/was das im hintergrund macht.  Aus deinen beschreibungen 
erkennt man, dass du wahrscheinlich wirklich nicht so eine Ahnung hast 
von Timern, weswegen dann die Leute auch bissl zackiger sind. Na gut, 
Frohe Ostern

LG, senor timer
Moderator (Firma: Titel) Persönliche Seite #2157656
Lesenswert?

Felix A. schrieb:
> Ich will nach einem Interrupt eine Einspritzdüse öffnen, dann xxx
> Mikrosekunden auf lassen, und dann wieder schließen.
Warum meinst du, die Einspritzdüse bis zu 5 Sekunden lang auf 22 us 
genau ansteuern können zu müssen?

Wo sitzt diese Einspritzdüse?
In einem Motor?
Dann hast du m.E. noch nicht allzuviel Ahnung von Motoren...
Gast #2157703
Lesenswert?

700 µs auf wenige µs genau geht entweder über einen 16-bit-Zähler oder 
einen 16-bit-Timer (700*16=11200, abzüglich Overhead für Port setzen und 
pollen). Was man nimmt, ist Geschmacksache, er pollt ja sowieso. Die 
Auflösung ist dann 4/32=1/8 µs, das dürfte genügen. Das geht aber nur in 
ASM oder C.
#2157708
Lesenswert?

Felix A. schrieb:
> ne ne alle 10-20 ms für etwa 700 Mikrosekunden...

Gut, ich poste meinen zurückgezogenen Beitrag nochmal, mach' was draus 
oder lass' es bleiben:

Felix A. schrieb:
> der Zündzeitpunkt soll ertstmal linear zur drehzhal sein,

Was meinst Du damit?
Ist "Zündzeitpunkt" dasselbe wie das Öffnen der Düse?
Oder gibt es auch noch eine Zündkerze?
Wieviel Zeit muss/darf zwischen Auslösung durch Magnet und Öffnen der 
Düse vergehen?

> damit sollte
> die berechnungszeit immer gleich sein.

Es kommt auf die Berechnung an. Addition und Subtraktion lässt sich (in 
ASM) taktgenau planen. Andere Operationen werden meist als Schleife 
ausgeführt, deren genaue Ausführungsdauer von den Operanden abhängig 
ist. Man sollte daher erstmal nicht davon ausgehen, dass eine Berechnung 
immer die selbe Anzahl von Takten braucht.

> die düse muss etwa 700
> mikrosekunden auf sein.

Na das ist doch ideal für die Compare-Einheit des 16-Bit-Timers.

> Sie ist aber sehr empfindlich, deshalb muss ich
> sie so genau einstellen. +-5 mikrosekunden wäre schon wieder zu ungenau.

Ja und? Der Timer arbeitet auf den Controllertakt genau. Und die 
Interrupt-Aufrufzeit lässt sich mittels Sleep exakt konstant halten.

Also nochmal wie ich das angehen würde:

Controller läuft mit 8 MHz CPU-Takt (Quarz).
16-Bit-Timer läuft mit Vorteiler 1 zu 8, also im Zeitraster von 1 ms.

Input-Capture-Interrupt erkennt Magnetsensor 1 und
- schaltet Düse ein
- nimmt Zeitstempel und sichert ihn für die Drehzahlberechnung
- addiert Intervall (etwa 700) dazu und setzt damit den Termin für den
  Compare-Interrupt zum Ausschalten der Düse

Compare-Interrupt (700 ms später als ICP-Interrupt)
- schaltet Düse aus

Externer Interrupt erkennt Magnetsensor 2 und
- nimmt Zeitstempel vom Timer
- bildet Differenz zum Zeitstempel des letzten ICP-Interrupts
- errechnet daraus die Drehzahl
- korrigiert evtl. das Intervall anhand der drehzahl


Solltest Du noch eine drehzahlabhängige Verschiebung des Öffnens der 
Düse brauchen, dann kommt noch ein weiterer Compare-Interrupt hinzu. Das 
sieht dann etwa so aus:

Input-Capture-Interrupt erkennt Magnetsensor 1 und
- nimmt Zeitstempel und sichert ihn für die Drehzahlberechnung
- addiert Intervall für Zündverzögerung (aus Drehzahl berechnet) dazu
  und setzt damit den Termin für den CompareA-Interrupt zum
  Einschalten der Düse
- addiert Intervall für Düsen-Öffnungszeit (etwa 700) dazu und setzt
  damit den Termin für den CompareB-Interrupt zum Ausschalten der Düse

CompareA-Interrupt (Zündverzögerung später als ICP-Interrupt)
- schaltet Düse ein

CompareB-Interrupt (700 ms später als CompareA-Interrupt)
- schaltet Düse aus

Externer Interrupt erkennt Magnetsensor 2 und
- nimmt Zeitstempel vom Timer
- bildet Differenz zum Zeitstempel des letzten ICP-Interrupts
- errechnet daraus die Drehzahl
- korrigiert das Intervall für Zündzeitpunkt anhand der Drehzahl, das
  wird bei der nächsten Zündung berücksichtigt
- korrigiert evtl. das Intervall anhand der Drehzahl, das wird bei der
  nächsten Zündung berücksichtigt.

Hauptprogramm:
- Sleep


Wenn sichergestellt ist, dass der zweite Magnetsensor erst erreicht 
wird, wenn die Düse garantiert wieder geschlossen ist, dann hat dieser 
externe Interrupt genügend Zeit zum Berechnen der Drehzahl und 
Intervallwerte für die nächste Runde. Da kann auch noch ein ADC-Wert 
eingelesen werden und mit der Drehzahl verglichen werden um das 
Düsenintervall zu steuern (Drehzahlregelung).

Der Timer läuft nach 65,536 ms über, das sind etwa 15 Hz untere Grenze, 
also (beim 4-Takter) etwa 108 Rpm. Sollte es darunter noch funktionieren 
müssen, dann sollten die Compare-Interrupts aktiviert/deaktiviert 
werden.

Und nein, ich habe keine Ahnung von Motor-Managment-Computer, ich habe 
mit Sicherheit einige wichtige Punkte vergessen. Denn ich habe nur das 
umzusetzen versucht, was Du als Anforderung salamimäßig 
(scheibchenweise) preisgegeben hast.

Mit Bascom und Warteschleifen bist Du schlecht beraten, selbst mit 
"Waitus(xy)" in Bascom wird das sehr unzuverlässig. Auch mit Timer und 
Bascom wird es recht ruckelig, da Bascom unnötig Zeit verplempert um 
(unbenutzte) Register zu sichern und die Variablen im SRAM zu halten. Da 
bleibt eigentlich nur C (vom Mais-Teer programmiert) oder ASM. Aber 
reines ASM, kein Inline-ASM von Bascom...

...
Gast #2157749
Lesenswert?

Hallo Felix,

wie kommst Du darauf mit BASCOM eine Motorsteuerung programmieren zu 
wollen?
Ein Motorsteuergerät ist inzwischen so komplex, daß Du mit einer solchen 
festen Struktur keinen Motor richtig zum laufen bekommst.

Schon mal über Signalabsicherungen nachgedacht? Vielleicht über 
Kennfelder?
Die vielen Sensoren, die Du abfragen mußt? Das geht in Deiner festen 
Struktur nicht.

Hol dir mal die gelben Bücher von Bosch zum Thema Motorsteuerung...
und lerne wenigstens ANSI-C...

Grüße,
Thomas
Persönliche Seite #2157841
Lesenswert?

Felix A. schrieb:
> wegen den
> Branch penalties.
Auch wenn sich das Wort eventuell cool anhört ist es hier doch fehl am 
Platz.
Eine mranch-penaltie gibt es nur im Zuge eines falsch vorhergesagtem 
Sprungs, bei der AVR-RISC gibt es so etwas aber nicht sondern ein Sprung 
braucht IMMER eine festgelegte Anzahl Taktzyklen, welche man im 
Datenblatt nachlesen kann...

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