Forum: Mikrocontroller und Digitale Elektronik Software architektur, wo plaziere ich meine funktion


von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

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.

von MaWin (Gast)


Lesenswert?

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.

von hj (Gast)


Lesenswert?

Im Timer4-Interrupt ein flag setzen. In der main() dieses flag prüfen 
und ggf. deine Funktion aufrufen.

Und du willst ein Diplom haben?!

von Tobi (Gast)


Lesenswert?

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

von npn (Gast)


Lesenswert?

Tobi schrieb:
> Mir ist aber nicht klar wie ich dort eine flag setzten kann

Setzen:
1
flag = 1;

Abfragen:
1
if flag == 1
2
{
3
    funktion();
4
    flag = 0;
5
}

von Tobi (Gast)


Lesenswert?

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
void Timer4Init(void)  //Ermittlung der Periodendauer LD
2
{
3
  TCCR4B = 0x00;          
4
  TCCR4A = 0x00;          
5
  EICRA |= (0<<ISC11)| (1<<ISC10);    
6
  EIMSK |= (1<<INT1);
7
8
}

: Bearbeitet durch User
von npn (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Tobi (Gast)


Lesenswert?

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.

von Tobi (Gast)


Lesenswert?

Tobi schrieb:
> Flag = 0;

das soll natürlich

flag=0;
sein.

von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von Udo S. (urschmitt)


Lesenswert?

Was hat das eigentlich mit Softwarearchitektur zu tun?
Hier gehts doch nur um die ersten 10 Seiten von K&R.

von Cyblord -. (cyblord)


Lesenswert?

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?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

: Bearbeitet durch User
von Tobi (Gast)


Lesenswert?

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
int main (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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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
      mach was;
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

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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
volatile uint8_t doTheJob;
2
3
ISR( ..... )    // wird aufgerufen bei irgendeinem Flankenwechsel
4
{
5
  if( Pin ... ist auf 1 )   // dann wars eine steigende Flanke
6
    doTheJob = 1;
7
}
8
9
int main()
10
{
11
  ...
12
13
  while( 1 )
14
  {
15
16
    if( doTheJob ) {
17
      mache die Berechnung
18
      doTheJob = 0;
19
    }
20
  }
21
}

ganz stink normaler Ansatz über sog. Job-Flags.

: Bearbeitet durch User
von tobi (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
   if doTheJob == 0   // Wenn noch nicht gesetzt...
4
   {
5
     if( Pin ... ist auf 1 )   // dann wars eine steigende Flanke
6
       doTheJob = 1;
7
   }
8
 }

von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

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

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Das
1
        if(doTheJob=1)

ist immer noch eine Zuweisung und kein Vergleich.

von Tobi (Gast)


Lesenswert?

hmmm

mit
  if(doTheJob==1)

geht garnichts mehr,
die Rote LED ist aber auch jetzt immer zu an

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

Hier ist der nächste
1
ISR (INT1_vect) 
2
{
3
  if(PIND & (0<<PIND0))


das hat doch alles keinen Sinn. Wer mit dem Aufkleben von Heftpflaster 
überfordert ist, sollte sich nicht an Herzoperationen wagen.

von Achim S. (Gast)


Lesenswert?

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.

von Tobi (Gast)


Lesenswert?

Ich bin dem Fehler auf der Spur,
danke für die sachlichen Anregungen.!

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.