Hallo Leute,
ich sitze gerade an einem Programm, in welchem 2 Funktionen berechnet
werden. Vom Prinzip her bekomme ich auch das Raus was ich raus haben
will. Ich würde jetzt gerne erreichen, dass die zweite Funktion nicht
dauerhaft gerechnet wird, sondern nur zu einem bestimmten Zeitpunkt.
Jetzt ist die Frage, wo Platziere ich meine Funktion_2 damit dies auch
geschieht.
Kurz zu den Abhängigkeiten.
Funktion_1 berechnet aus der Leitdauer und einem Wert der über ein
Potenziometer eingelesen wird einen Steuerwinkel.
Funktion_2 berechnet aus dem Steuerwinkel (also Funktion_1) und der
Leitdauer, den Strom.
Zur Überprüfung der Funktion 2 habe ich ein paar LEDs ab einem
bestimmten schwellwert Leuchten lassen und bin mit dem Ergebnis
zufrieden…bis jetzt ;).
Ich würde gerne Funktion_2 nur dann berechnen lassen wenn ein Timer
(Timer4) die anliegende Leitdauer erfasst hat.
Tja wo platziere ich jetzt meinen Funktionsaufruf?
Meine Überlegungen waren:
Im Interrupt, in welchem die Leitdauer erkannt wird,(war leider
nicht erfolgreich
in der Main, das geht zwar aber dann wird dauerhaft gerechnet, das würde
ich gerne vermeiden
im Nulldurchgang, hier währe Zeit genug um Funktion 2 zu berechnen, aber
dann wird im kompletten Nulldurchgang die Funktion durchgerechnet,
Ich würde das gerne so hinbekommen, das Funktion_2 nur einmal pro
Netzperiode durchgerechnet und das Ergebnis zurückgeliefert wird
Vielleicht hat ja jemand von euch eine gute Idee?
Ich habe den Quellcode als Datei angefügt, ich kann den auch hir posten
wenn dies erwünscht wird.
Wie kommt man auf die Idee, eine APS Datei hochzuladen,
wieso hat man die Grundlagen nicht vor dem Diplom gelrrnt,
und warum dauert das Diplom schon seit 2011 ?
Fragen über Fragen.
Lange Berechnungen platziert man normalerweise nicht im Interrupt.
die Grunddatei ist nicht von mir, und dementsprechend schon etwas älter.
Diplom gibts auch nicht mehr hehehe.
das eine längere funktion nicht in einem Interrupt berechnet werden
sollte leuchtet mir ein.
DIe Idee einen flag zu setzten in Timer 4 hatte ich auch schon.
Timer 4 arbeitet so,
es wird sowohl die steigende als auch die fallende flanke erkannt, die
zeit zwischen den flanken stellt die leitdauer da.
Mir ist aber nicht klar wie ich dort eine flag setzten kann, da hir
keine software Interrupts angesprochen werden
Timer 4 reagiert auf einen Externe interrupt. Bzw. auf die stiegende und
fallende Flanke. (any Edge)
Ich müsste ja da irgendwie "da zwischen kommen" um dort meine Flag zu
setzten, das ist mir nicht klar.
Ich müsste also sowas sagen wie
"fallende flanke erkannt" flag=1
nur wie komme ich dazwischen?
hier mal die Timer 4 init
1
voidTimer4Init(void)//Ermittlung der Periodendauer LD
Muß T4 auf beide Flanken triggern? Offensichtlich willst du doch nur auf
eine Flanke (fallende) reagieren. Wäre es da nicht einfacher, gleich auf
die fallende Flanke zu triggern?
Wenn nicht, müßtest du beim Eintritt in die ISR des T4 den Pin nochmal
abfragen und mit dem vorherigen Zustand vergleichen. Und dann natürlich
wieder in einer Variablen merken für die nächste Auslösung. So bekommst
du raus, ob das auslösende Ereignis eine steigende oder fallende Flanke
war.
Tobi schrieb:> Timer 4 reagiert auf einen Externe interrupt. Bzw. auf die stiegende und> fallende Flanke. (any Edge)> Ich müsste ja da irgendwie "da zwischen kommen" um dort meine Flag zu> setzten, das ist mir nicht klar.>> Ich müsste also sowas sagen wie> "fallende flanke erkannt" flag=1
Ja und?
Wenn dein Interrupt auf beide Flanken triggert und du wissen willst ob
das jetzt eine steigende oder eine fallende Flanke war, wie kannst du
das machen?
Was ist denn eine fallende Flanke? Eine fallende Flanke hat man dann,
wenn der Pin von 1 auf 0 wechselst. Siehst du dir also im Interrupt den
Zustand des Pins an, und stellst du fest, der ist 0, dann kann die
auslösende Flanke nur eine fallende Flanke gewesen sein. Denn bei einer
steigenden Flanke (von 0 auf 1) wäre der Pin ja nach der Flanke auf 1
und nicht auf 0.
Guten Morgen zusammen,
mir ist schon klar was eine Flanke ist. Und ich muss auch sowohl die
fallende, als auch die steigende Flanke erkennen. Ich dachte eigentlich
das ich durch das zählen von
i==1
i==2
i==3
den Status des Pins abfrage. Ich meine das funktioniert ja auch für das
Erfassen der Zeit zwischen den Flanken. Ich würde jetzt gerne meine
Funktion berechnen sobald i==3 geworden ist.
if (i==3)
{
LAMBDAmess =TCNT4 ;
flag=1;
}
Was dann in der Main folgendes bewirken soll:
if (flag==1)
{
PORTA &=~(1<<PINA0);
Ieff = Stromberechnung(LAMBDA, ALPHA);
Flag = 0;
PORTA |=(1<<PINA0);
}
Die Rechnung wird auch angestoßen, aber leider nicht nur einmal, sondern
bis zum nächsten Nulldurchgang der Netzspannung. Desweiteren macht es
den Eindruck, als ob die Berechnung doch im Interrupt ausgeführt wird.
Was logischerweise zu einem Fehlverhalten ab einer bestimmten Spannung
führt.
Tobi schrieb:> Die Rechnung wird auch angestoßen, aber leider nicht nur einmal, sondern> bis zum nächsten Nulldurchgang der Netzspannung.
Dann hast du einen Prgrammfehler irgendwo anders.
> Desweiteren macht es> den Eindruck,
Es macht den Eindruck?
Hör mal. Bist du der Programmierer oder bist du nicht der Programmierer?
Ein Programmierer gibt nichts auf 'es macht den Eindruck'. Er überprüft,
was abgeht.
> Was logischerweise zu einem Fehlverhalten ab einer bestimmten Spannung> führt.
Was immer du unter Logik verstehst.
Deine Fragen sind so dermassen konfus und die gefragten Dinge sind
(allem Anschein nach) so dermassen trivial zu lösen, dass ich ernsthaft
denke, das alles ist mindestens 15 Schuhnummern zu groß für dich. Auch
du wirst am Anfang anfangen müssen zu lernen. So wie Milliarden anderer
Programmierer vor dir. Computer sind da gnadenlos. Durchmogeln geht
nicht. Und auch durch das Aufzählen von Buzzwords kommt man nicht
weiter, was für Blender und BWL-er ein echtes Problem darstellt. Und
nein, auch mit einem fertigen Programm, das wer anderer geschrieben hat,
kommt man nicht weiter. Entweder man kann programmieren, dann kann man
ein vorhandenes Programm abändern. Oder man kann es nicht, dann ist das
ein aussichtsloses Unterfangen. Es ist ein Trugschluss zu denken "Ooch,
ich versteh zwar 90% nicht, aber ich will ja nur <xyz hier einsetzen>
ergänzen." und das das alles irgendwie eine ganz einfache Sache wäre.
Der Umbau eines Kühlschranks zu einem Flugzeugträger ist eine einfache
Sache, aber nicht die Umarbeitung eines bestehendes Programmes von
jemanden, der nicht programmieren kann und keine Erfahrung in solchen
Dingen hat.
Udo Schmitt schrieb:> Was hat das eigentlich mit Softwarearchitektur zu tun?> Hier gehts doch nur um die ersten 10 Seiten von K&R.
Aber woher soll denn das ein quer eingestiegener fachfremder Praktikant
wissen?
Mal abgesehen davon, dass du nicht mal imstande bist, dein Vorhaben
vernünftig zu erklären:
Tobi schrieb:
1
if(i==3)
2
{
3
LAMBDAmess=TCNT4;
4
flag=1;
5
/////// Wie ware es mit zurucksetzen ? //////////////
6
i=0;
7
/////////////////////
8
}
> Was dann in der Main folgendes bewirken soll:> if (flag==1)> ...> Die Rechnung wird auch angestoßen, aber leider nicht nur einmal, sondern> bis zum nächsten Nulldurchgang der Netzspannung.
Was ja auch normal ist, wenn darunter ein else mit i++; steht.
Tobi schrieb:> bis zum nächsten Nulldurchgang der Netzspannung. Desweiteren macht es> den Eindruck, als ob die Berechnung doch im Interrupt ausgeführt wird.
Wenn man etwas beobachtet oder fremde Programme laufen lässt, kann es
schon zu solch merkwürdigen Eindrücken kommen.
Wenn man etwas selbst geschrieben hat, dann gibt es keine Eindrücke.
Und wie diese Berechnung von main() in die ISR reinspazieren sollte,
entzieht sich meinem Vorstellungsvermögen.
Tobi schrieb:> Was dann in der Main folgendes bewirken soll:> if (flag==1)> {> PORTA &=~(1<<PINA0);> Ieff = Stromberechnung(LAMBDA, ALPHA);> Flag = 0;> PORTA |=(1<<PINA0);> }> Die Rechnung wird auch angestoßen, aber leider nicht nur einmal, sondern> bis zum nächsten Nulldurchgang der Netzspannung. Desweiteren macht es
Wie lange dauert denn diese Berechnung ?
die Berechnungszeit dauert schon etwas länger. 2ms.
Auch wenn ich den Status des entsprechenden Pins abfrage wird die
Berechnung solange ausgeführt bis der Status des Pins wieder wechselt.
1
intmain(void)
2
{
3
if(PIND&(1<<PIND1))
4
5
{
6
y=1;
7
}
8
else
9
{
10
y=2;
11
if(y=2)
12
{
13
PORTA|=(1<<PINA0);//sichtbarmachen auf Oszi
14
Ieff=Stromberechnung(LAMBDA,ALPHA);
15
16
PORTB|=(1<<PINB2);//rote LED an
17
y=3;
18
PORTA&=~(1<<PINA0);//sichtbarmachen auf Oszi
19
}
20
}
Ziel soll sein:
Flanke des PIND! = erkannt
Berechnung 1x ausführen.
Da fehlt die Hauptschleife. Das halte ich mal der Verkürzung fürs Forum
zu Gute.
Aber das hier
1
if(y=2)
2
{
ist kein Vergleich auf Glerichheit, sondern eine Zuweisung.
Ja, das geht in C. Und der GCC warnt auch davor, dass das höchst
wahrscheinlich ein Fehler ist.
Die angestrebte Logik musst du mir allerdings mal erklären.
1
if(Pinabfrage)
2
y=1;
3
4
else{
5
6
y=2;
7
8
if(y==2){
9
machwas;
10
y=3;
11
}
12
}
da y im else Zweig auf jeden Fall erst mal auf 2 gesetzt wird, wird die
nachfolgende Abfrage, ob y gleich 2 ist, immer mit true beantwortet
werden. D.h. du hättest den ganzen Teil mit dem y auch einfach weglassen
können. Würde auf genau dasselbe rauslaufen
Wieso taucht da jetzt eigentlich auf einmal eine versuchte explizite
Flankenerkennung auf?
Ich dachte, der Auslöser ist zuallererst einmal ein Interrupt, welcher
bei jeder Flanke sowieso erst mal aufgerufen wird. Dort stellst du fest,
ob es eine steigende Flanke war und wenn ja, wird der Hauptschleife
signalisiert, die Berechnung anzustossen.
So zumindest war doch der Plan. Oder nicht?
1
volatileuint8_tdoTheJob;
2
3
ISR(.....)// wird aufgerufen bei irgendeinem Flankenwechsel
4
{
5
if(Pin...istauf1)// dann wars eine steigende Flanke
ja so war der plan.
Das Ding ist nur, das wenn ich sage
doTheJob = 0;
das immer noch gerechnet wird. Das will ich aber nicht. Das geht aber
sowohl auf dem einen weg nicht wie auch auf dem anderen.
tobi schrieb:> ja so war der plan.> Das Ding ist nur, das wenn ich sage>> doTheJob = 0;>> das immer noch gerechnet wird. Das will ich aber nicht. Das geht aber> sowohl auf dem einen weg nicht wie auch auf dem anderen.
Frage doch den Status beim Eintritt in die ISR ab. Wo siehst du
da ein Problem ?
Karl Heinz schrieb:
1
ISR(.....)// wird aufgerufen bei irgendeinem Flankenwechsel
2
{
3
ifdoTheJob==0// Wenn noch nicht gesetzt...
4
{
5
if(Pin...istauf1)// dann wars eine steigende Flanke
Erstmal besten Dank für die Anregung!
Es läuft schon etwas besser, aber noch lange nicht so wie gewünscht.
Probleme sind folgende.
Ich frage in der ISR den Pin PD1 ab.
1
ISR(INT1_vect)
2
{
3
if(PIND&(0<<PIND0))
4
{
5
doTheJob=1;
6
PORTB&=~(1<<PINB2);//rote LED an
7
PORTB|=(1<<PINB3);//gelb LED an
8
}
9
}
In der main folgt dan folgendes:
1
if(doTheJob=1)
2
{
3
PORTA&=~(1<<PINA0);//sichtbarmachen auf Oszi
4
Ieff=Stromberechnung(LAMBDA,ALPHA);
5
doTheJob=0;
6
PORTA|=(1<<PINA0);//sichtbarmachen auf Oszi
7
}
Wenn ich jetzt sage, dass
doTheJob=1 -> rote LED=an, gelbe LED = aus
und
do the Job=0->rote LED=aus, Gelbe LED=an
ist dauerhaft die Rote LED an.
Das durch
PORTA &=~(1<<PINA0);//sichtbarmachen auf Oszi
PORTA |=(1<<PINA0);//sichtbarmachen auf Oszi
erzeugte TTL signal baut sich auf und liegt zwischen 3,2 ms und 12ms.
Ich möchte aber, dass es ein statisches stehendes signal ist.
zum besseren Verständniss habe ich mal 2 oszi Bilder angehängt und den
Quellcode.
Zu den Oszibildern
Blau=Ul
rote=Ua
Hellblau=Strom
Grün=PORTA
Tobi schrieb:> hmmm>> mit> if(doTheJob==1)>> geht garnichts mehr,> die Rote LED ist aber auch jetzt immer zu an
ganz ehrlich.
Ich denk mich da jetzt nicht in die Programmlogik rein, solange du
solche dummen Fehler auf Anfängerniveau der ersten Stunde machst.
Apropos Anfängerfehler:
Tobi schrieb:> if(PIND & (0<<PIND0))
Schau bitte im Tutorial nach, wie man Eingänge richtig abfragt. Dass es
"irgendwie so ähnlich" ausschaut, reicht leider nicht.