Interrupt & Co gesucht...

Hallo,
ich übe gerade das DatenLoggen auf SD. Funktioniert auch recht gut und
zuverlässig.

Mit:

if ((seconds == 5) && (SDZL == 1))

schreibe ich immer, wenn Sekunde "5" ist- Daten. Also alle 60 Sekunden, oder
jede Minute. Das ganze läuft in der loop. Nun habe ich aber festgestellt, wenn
ich in einem "switchCase" hänge, das das nicht mehr funktioniert…

Nun hatte ich an Interrup gedacht, aber wenn ich das richtige verstehe, dann
reagieren die nur auf externe Impulse. Gibt es eine Möglichkeit, die RTC
(ChronoDot) als "Schalter" zu vergewaltigen.
Was für eine Möglichkeit würde es denn noch geben, um diese "If" Abfrage im
Hintergrund laufen zu lassen?
Gruß und Dank
Andreas

hi,

kenne chronodot nicht, aber jede “normale” RTC hat einen pin, der jede sekunde (oder einem einstellbaren bruchteil davon) einen impuls ausgibt. den könntest Du an einen interrupt koppeln.

ist es wichtig, daß es genau bei 5 passiert? wenn nicht, schau nach, ob er wieder (seit dem letzten mal) bei 5 oder größer ist, und logge dann…

EDIT: das ding hat SQW, dort kommt der impuls raus.

gruß stefan

Hallo,
das ist alles "Versuch" Die "5" sind ein Versuchsbeispiel" Eigentlich wollte
ich dafür jeden "x-beliebigen" Wert.
Bei minütlichen Loggen kommen mächtige Datenwulst auf einen zu. Ich habe das
einmal 3 Tage laufen lassen, 25920 Werte,
Wer´s braucht? Da schluckt sogar Excel.

Das mit dem "SQW" muss ich mir einmal anschauen…
Gruß und Dank
Andreas

Die eTimer1 Lib ist eine Möglichkeit:
http://playground.arduino.cc/Code/Timer1

Da die maximale Zeit ca. 8,3s ist, musst du allerdings die Anzahl der Interrupts mitzählen. Also z.B. den Timer auf 5 Sekunden einstellen. Und wenn du dann 5 Minuten willst, alle 60 Interrupts etwas machen.

Und Interrupts kannst du auf zig Systemen der CPU auslösen. Das passiert ständig ohne das du davon was mitbekommst (z.B. bei Seriell, SPI, I2C oder PWM). Die externen Interrupts sind nur eine Quelle. Hier ist eine Liste aller Interrupt Vektoren:
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Hallo,
ja mit der "TimerLib" geht das, es gibt auch eine "InterruptLib". Ich möchte das
aber ohne Lib machen. Nach Deinem zweiten Link scheint das ja möglich zu sein.
Da hapert es aber wieder an meinem "C". Und Interrup´s zählen ist wohl nicht
gerade der richtige Weg. Ich komme aber so langsam auf den Sprung.
Gruß und Dank
Andreas

Eine "InterruptLib" wird wahrscheinlich nur für die externen Interrupts sein.

Timer Interrupts zählen ist genau der richtige Weg. Das ist auch was der Arduino bei millis() macht. Wenn du das per Hand machst und den Timer direkt programmierst ist das auch nicht anders. Das ist ist nun mal ein 16 Bit Timer und die Frequenz hat durch den Prescaler einen minimalen Wert, wodurch sich eine maximale Periode ergibt. Die Timer1 Lib kapselt dir lediglich den Zugriff auf die Timer Register und macht das für dich verständlicher. Gerade wenn du dich nicht auskennst ist das eher zu empfehlen.

Eine andere Alternative wäre die Time Lib + TimeAlarms Lib. Damit läuft das auf dem Timer0, der sowieso schon verwendet wird, statt auf einem extra Timer. Dafür hat man dann mehr Code.

SkobyMobil:
Mit:

if ((seconds == 5) && (SDZL == 1))

schreibe ich immer, wenn Sekunde "5" ist- Daten. Also alle 60 Sekunden, oder
jede Minute. Das ganze läuft in der loop. Nun habe ich aber festgestellt, wenn
ich in einem "switchCase" hänge, das das nicht mehr funktioniert…

Hallo,

versuch es mal mit
if ((seconds >= 5) && (SDZL == 1))

Dann musst du nicht mehr genau die Sekunde treffen. Wenn du seltener als 1Minute logst dürfte +/-1sek, nicht viel ausmachen. Damit dir deine Uhr nicht wegläuft, solltest du das nur beim nächsten Aufruf berücksichtigen. Oder du schreibst die Zeit mit in die Datei.

SkobyMobil:
Mit:

if ((seconds == 5) && (SDZL == 1))

schreibe ich immer, wenn Sekunde "5" ist- Daten. Also alle 60 Sekunden, oder
jede Minute. Das ganze läuft in der loop. Nun habe ich aber festgestellt, wenn
ich in einem "switchCase" hänge, das das nicht mehr funktioniert…

Egal wo und wie du "hängst", ist vermutlich etwas falsch.
Deine Lösung geht davon aus, dass das mindestens jede Sekunde einmal dran kommt.
"SDZL" dient wohl dazu, zu merken ob diese Minute schon geschrieben wurde ???

Wenn es tatsächlich gute Gründe geben sollte, dass du sekundenlang irgendwo "hängst", musst du die

     if ( ( seconds [b]>=[/b] 5) &&  (SDZL == 1) )

Lösung von Theseus nehmen.

Timer, Interrupts, das RTC SQW Signal, usw. macht alles nur komplizierter :wink:

SkobyMobil:
Nun habe ich aber festgestellt, wenn
ich in einem “switchCase” hänge, das das nicht mehr funktioniert…

Das kann eigentlich nicht sein.
Es sei denn, du hast da irgendwelche Routinen die länger als 1 Sekunde laufen. Sind da delays drin?
Wenn deine Software so aussieht, dass die Loop nicht mindestens alle 100ms einmal durchlaufen wird, hast du eher ein Design-Problem. Mess doch mal, in welchen Abständen die loop durchlaufen wird, dann weißt du mehr.

LoopTiming.ino (1.2 KB)

Hallo,
nein, nein, nein

"SDZL == 1" ist ein SD-Zähler. Ich kann den Code hier gerne posten, sind um die
31Kb, da wird sich aber keiner durchwuseln…

Loop…

Code-blah, gack

switchCase

Case 1
Code-blah, gack

Case 2
Hier wird das loggen gestartet. Zeitstempel (ab wann u.s.w.) und SDZL auf
"1" gesetzt. Das loggen wird hier auch beendet.
Durch weiteren Tastendruck komme ich zu Case 3- dann nach default.

Case 3

Code-blah, gack

default:
if ((seconds = 5) && (SDZL == 1))

Jetzt läuft die loop, SDZL ist "1" und alle Minute werden Daten geschrieben.

Taste ich nun nach "Case 1" dann bin ich aus der loop raus. Die Sekunde "5"
läuft vorbei. Taste ich nun nach default, wird auf die nächste "5" gewartet.

Wenn ich ">=5" nehmen würden, dann wird auch bei 6,7,8 u.s.w. geschrieben.
Das könnte man abfangen, funktinoiert aber nur wenn ich in der loop bin.

Wenn ich mich in einer "Case 3" befinde, dann wird doch nur der Code in dieser
Case ausgeführt? Oder habe ich da einen Denkfehler. Ich glaube nicht.

Zeitkritisch ist das ganze nicht. Es wird durch "abfangen" nur ein Datensatz
bei Sekunde "5" geschrieben. Fange ich das nicht ab, sind es locker 8 Datensätze
in der Sekunde.

Ein Beispiel Log:
25.02.14 12:19 19.7 42.9 11.4 57.4 //in loop
25.02.14 12:20 19.7 42.4 11.4 57.1 //in loop
25.02.14 12:21 19.7 44.6 11.4 57.3 //in loop
25.02.14 12:22 19.8 44.0 11.5 55.7 //in loop
25.02.14 12:23 19.8 43.3 11.5 56.2 //in loop

um 12:24 in Case 2

25.02.14 12:25 19.8 48.2 11.6 56.5 //in loop
25.02.14 12:26 19.9 44.3 11.7 57.1 //in loop
25.02.14 12:27 19.9 42.4 11.7 55.6 //in loop
25.02.14 12:28 19.9 42.2 11.8 55.7 //in loop

Oder anderes Beispiel:
Wenn ich in "Case 2" die Schaltuhr überprüfen möchte, dann "sagt" niemand im
"Hintergrund" jetzt "Daten loggen"
Gruß und Dank
Andreas

Könntest ja mal den Sketch ruhig reinstellen. Ich denke doch. dass da evtl. der falsche Programmierweg gewählt wurde. Ich versuche eigentlich immer, jeden loop so schnell wie Möglich zu durchlaufen.

Du kannst gerne deinen Sketch auf lesbares Maß verkleinern, so dass das "hängen im switch" noch passiert,
denn mit


switchCase

Case 1
Code-blah, gack

Case 2
Hier wird das loggen gestartet. Zeitstempel (ab wann u.s.w.) und SDZL auf
"1" gesetzt. Das loggen wird hier auch beendet.
Durch weiteren Tastendruck komme ich zu Case 3- dann nach default.

Case 3

Code-blah, gack

kann ich rein gar nichts anfangen.
Eine switch Anweisung mit hundert case Fällen ist in weniger als 1 µs fertig.
Wie immer du das "abfangen" machst, dass bei mehreren loop Durchläufen nur einmal geschrieben wird, ist wohl schon ok.

Taste ich nun nach "Case 1" dann bin ich aus der loop raus
Wenn ich mich in einer "Case 3" befinde, dann wird doch nur der Code in dieser
Case ausgeführt

Das solltest du vielleicht mal zeigen, was du mit solchen Sätzen meinst :wink:

Wenn dein Code so ähnlich aussehen sollte:

void loop()
{
 int taste = getTaste();
 switch ( taste )
 {
   case 1:
       DoTaste1();
      break;
   case 2:
     DoTaste2();
     break;
   default:
     // weder Taste1 noch Taste2
 } 
 DoOtherStuff();
}

... wird Entweder DoTaste1() oder DoTaste2() ausgeführt oder das im default Zweig.
Danach kommt sofort DoOtherStuff() dran, und das Ganze natürlich mehrfach pro Sekunde.
Nach meinem Verständnis "bist du" immer in loop().

Ohne Code ist das alles Kaffeesatzleserei!

Auch auf die Gefahr hin, mich zu wiederholen:

guntherb:
Wenn deine Software so aussieht, dass die Loop nicht mindestens alle 100ms einmal durchlaufen wird, hast du eher ein Design-Problem.
Mess doch mal, in welchen Abständen die loop durchlaufen wird, dann weißt du mehr.

Und wir wissen dann auch mehr.

Oben hatte ich dir eine Funktion drangehängt zur Auswertung der Loop()-Zeiten.

Hallo,
ich habe es mal gemessen, einmal nach Deinem Sketch, einmal nach meiner
Methode.
Dein Sketch zählt etwas hoch und runter:
durchschnittlich alle -157ms
minimaler Abstand -1ms
maximaler Abstand -17476ms
Loop wird aufgerufen
durchschnittlich alle -176ms
minimaler Abstand -1ms
maximaler Abstand -19421ms
Loop wird aufgerufen
durchschnittlich alle -196ms
minimaler Abstand -1ms
maximaler Abstand -21364ms
Loop wird aufgerufen
durchschnittlich alle -216ms
minimaler Abstand -1ms
maximaler Abstand -23308ms
Loop wird aufgerufen
durchschnittlich alle -235ms
minimaler Abstand -1ms
maximaler Abstand -25251ms
Loop wird aufgerufen
durchschnittlich alle -255ms
minimaler Abstand -1ms
maximaler Abstand -27196ms
Loop wird aufgerufen
durchschnittlich alle -275ms
minimaler Abstand -1ms
maximaler Abstand -29140ms
Loop wird aufgerufen
durchschnittlich alle -294ms
minimaler Abstand -1ms
maximaler Abstand -31083ms
Loop wird aufgerufen
durchschnittlich alle -314ms
minimaler Abstand -1ms
maximaler Abstand 32509ms
Loop wird aufgerufen
durchschnittlich alle 327ms
minimaler Abstand -1ms
maximaler Abstand 30566ms
Loop wird aufgerufen
durchschnittlich alle 308ms
minimaler Abstand -1ms
maximaler Abstand 28623ms
Loop wird aufgerufen
durchschnittlich alle 288ms
minimaler Abstand -1ms
maximaler Abstand 26680ms
Loop wird aufgerufen
durchschnittlich alle 269ms
minimaler Abstand -1ms
maximaler Abstand 24737ms
Loop wird aufgerufen
durchschnittlich alle 249ms
minimaler Abstand -1ms
maximaler Abstand 22795ms
Loop wird aufgerufen
durchschnittlich alle 51ms
minimaler Abstand -1ms
maximaler Abstand 2279ms
Loop wird aufgerufen
durchschnittlich alle 22ms
minimaler Abstand -1ms
maximaler Abstand 341ms
Loop wird aufgerufen
durchschnittlich alle 3ms
minimaler Abstand -1ms
maximaler Abstand -1595ms
Loop wird aufgerufen
durchschnittlich alle -16ms
minimaler Abstand -1ms
maximaler Abstand -3532ms
Loop wird aufgerufen
durchschnittlich alle -36ms
minimaler Abstand -1ms
maximaler Abstand -5471ms
Loop wird aufgerufen
durchschnittlich alle -55ms
minimaler Abstand -1ms
maximaler Abstand -7410ms


nach meiner Methode
loop()
Serial.print(millis());
Serial.println("A");

hier der Code in der loop

am ende loop

Serial.print(millis());
Serial.println("B");

Ergebnis:
13819A
13837B
Differenz=18

40952A
40970B
Differenz=18

hier beide:

554281A
554285A
554303B
554303A
554306A
Loop wird aufgerufen
durchschnittlich alle -71ms
minimaler Abstand -1ms
maximaler Abstand -9211ms
554349B
554353A
554360A
554381B
554381A
554384A
554402B
554403A
554405A
554424B
554425A
554427A
554445B
554446A
554448A
554467B
554468A
554470A
554488B
554489A
554491A
554510B
554511A
554513A
554531B
554532A
554534A
554553B
554554A
554556A
554574B
554575A
554577A
554596B
554597A
554599A
554617B
554618A
554620A
554639B
554640A
554642A
554660B
554661A
554663A
554682B
554683A
554685A
554703B
554704A
554706A
554725B
554726A
554728A
554746B
554747A
554749A
554768B
554769A
554771A
554789B
554790A
554792A
554811B
554812A
554814A
554832B
554833A
554835A
554854B
554855A
554857A
554875B
554876A
554878A
554897B
554898A
554900A
554918B
554919A
554921A
554940B
554941A
554943A
554961B
554962A
554964A
554983B
554984A
554986A
555004B
555005A
555008A
555026B
555027A
555029A
555047B
555048A
555051A
555069B
555070A
555072A
555090B
555091A
555094A
555112B
555113A
555115A
555133B
555134A
555137A
555155B
555156A
555158A
555176B
555177A
555180A
555198B
555199A
555201A
555219B
555220A
555223A
555241B
555242A
555244A
555262B
555264A
555266A
555284B
555285A
555287A
555305B
555307A
555309A
555327B
555328A
555330A
555348B
555350A
555352A
555370B
555371A
555373A
555392B
555393A
555395A
555413B
555414A
555416A
555435B
555436A
555438A
555456B
555457A
555459A
555478B
555479A
555481A
555499B
555500A
555502A
555521B
555522A
555524A
555542B
555543A
555545A
555564B
555565A
555567A
555585B
555586A
555588A
555607B
555608A
555610A
555628B
555629A
555631A
555650B
555651A
555653A
555671B
555672A
555674A
555693B
555694A
555696A
555714B
555715A
555717A
555736B
555737A
555739A
555757B
555758A
555760A
555779B
555780A
555782A
555800B
555801A
555803A
555822B
555823A
555825A
555843B
555844A
555846A
555865B
555866A
555868A
555886B
555887A
555889A
555908B
555909A
555911A
555929B
555930A
555932A
555951B
555952A
555954A
555972B
555973A
555975A
555994B
555995A
555997A
556015B
556016A
556018A
556037B
556038A
556040A
556058B
556059A
556061A
556080B
556081A
556083A
556101B
556102A
556104A
556123B
556124A
556126A
556144B
556145A
556147A
556166B
556167A
556169A
556187B
556188A
556190A
556209B
556210A
556212A
556230B
556231A
556233A
556252B
556253A
556255A
556273B
556274A
556276A
556295B
556296A
556298A
556316B
556317A
556319A
556338B
556339A
556341A
556359B
556360A
556362A
556381B
556382A
556384A
556402B
556403A
556405A
556424B
556425A
556427A
556445B
556446A
556448A
556467B
556468A
556470A
556488B
556489A
556491A
Loop wird aufgerufen
durchschnittlich alle -93ms
minimaler Abstand -1ms
maximaler Abstand -11397ms
556535B
556540A
556547A
556567B
556568A
556570A
556589B

Für mich dauert so ein Durchlauf so ca. "18 Millis"
Gruß und Spaß
Andreas

Wenn ich das richtig verstehe, dann braucht deine Loop bis über 32sec.? Da solltest du überprüfen, was dazu führt.

Ich verstehe deine Zeitsteuerung nicht. Der normale Weg ist

if(currentMillis - previousMillis > interval) {
      previousMillis = currentMillis;
     Schreibe auf SD-Karte

Man kann das auch so machen:

if(currentMillis > nextMillis) {
 
    do
       {nextMillis = nextMillis+intervall;
 
        } while (nextMillis<currentMillis );
   
     Schreibe SD-Karte

Hier wird möglichst genau das Intervall eingehalten

Da du nicht zu jedem A ein B hast, ist also irgendwo ein vorzeitiges return;
Alles danach willst du also nicht ausgeführt haben.

maximaler Abstand -11397ms

Was soll das bedeuten?
Dass dein Code 11,4 sec ( ein andermal 19 sec) irgendwo hängt, du aber nichts darüber verraten willst ?

Dass es jedesmal 1 ms von B nach A dauert ( doch so lang !) , liegt vermutlich an deinen vielen seriellen Ausgaben. Das ist aber hier nicht dein Problem.

Hallo,
32 Sekunden, dann wäre das ALLES schon in der Tonne.

diese serielle Ausgabe:
-Loop wird aufgerufen
-durchschnittlich alle -93ms
-minimaler Abstand -1ms
-maximaler Abstand -11397ms

erzeugt der Sketch von guntherb
(weiter oben, LoopTiming.ino (1.2 KB - downloaded 4 times.)

Ich habe am Anfang der loop einfach
Serial.print(millis());
Serial.println("A");

am Ende der lopp,
Serial.print(millis());
Serial.println("B");

millis am Anfang der loop = 13819A
millis am Ende der lopp = 13837B

ist eine Differenz von 18 millis

also dauert ein Durchlauf doch ca. 18 millis?

loop()
{
Serial.print(millis());
Serial.println("A");

loop Code

der code in der loop, hier könnte ein "Uhr return" zuschlagen
das einzige, was in der lopp immer gemacht wird:
Anzeige der Zeit auf Display
alle 60 Sekunden von zwei HYT 939 Werte holen
einen Taster abfragen LCD-Beleuchtung
einen Taster abfragen "switch (buttonPressesS1)"

loop Code

Serial.print(millis());
Serial.println("B");
}

Was das zu bedeuten hat, weiß ich nicht:
maximaler Abstand -11397ms

Mein Code hängt an KEINER Stelle, diese "-11397ms" hat der Sketch von
guntherb "gemessen".

Das ist auch alles nicht mein Problem:
wenn ich einen Taster abfragen "switch (buttonPressesS1)"
und dann in "Case 3" die Schaltuhr überprüfe, dann bin ich
aus der loop raus. Weil ich in "Case 3" etwas zu erledigen habe.

Ich hätte aber gerne einen Interrupt der im Hintergrund läuft, nach einer
bestimmten Zeit mich aus der "Case 3" holt, etwas erledigt und wieder zurück
zur "Case 3"

es ist doch so?

loop
{
loopcode

interrupt unterbricht loopcode- macht etwas, und dann wieder:

loopcode
}
So hatte ich mir das gedacht.
Gruß und Dank
Andreas

Wenn ich die Interupts richtig verstanden habe bzgl. der Priorität, so funktionieren die ähnlich wie der return in mitten eines Ablaufs. D.h. es wird sofort in die ISR gesprungen. Wenn du gerade aber etwas an ein Display schickst, sind die Daten mehr oder weniger nur zur Hälfte da.

Ja.

Interrupt Prioritäten im eigentlichen Sinne gibt es auf dem AVR nicht. Alle haben die gleiche Priorität, können sich aber standardmäßig nicht gegenseitig unterbrechen.

Ich meinte Interupt im vergleich zu einem anderen Signal an einem nicht interuptfähigen pin.