ina219.getCurrent_mA(); Funktion in der ISR nicht aufrufbar

#5956512
Lesenswert?

Ich habe einen Arduino Nano und ein INA219 Strommessmodul.
Ich möchte über die TimerOne.h Bibliothek einmal die Sekunde den 
Stromwert auslesen.
Hierzu wird 1 mal die Sekunde die ISR per Timer mit dem Namen Strom 
aufgerufen.
Normalerweise sollte der Befehl zum abfragen " I = 
ina219.getCurrent_mA(); " in der ISR mit dem Namen Strom stehen.  Da 
funktioniert er aber nicht und der Arduino Nano stützt ab.
Zum Testen habe ich mal versucht eine andere Methode in der ISR 
aufzurufen. Das geht. Es scheint also ein Problem mit dieser einen 
Funktion zu sein.
Weiß jemand warum ich gerade diese Funktion nicht aufrufen kann aber 
andere Sachen schon?
1
#include <TimerOne.h>
2
#include <Wire.h>
3
#include <Adafruit_INA219.h>
4
Adafruit_INA219 ina219;
5

6
int I = 0;                          //Stromwert
7

8
void setup(void){
9
ina219.begin();
10
Timer1.initialize(1000000);         //Timer auf 1 Sekunden stellen
11
Timer1.attachInterrupt(Strom);      //ISR Strom wird jede Sekunde aufgerufen
12
Serial.begin(115200);
13
}
14
void loop(void){   
15
I = ina219.getCurrent_mA();         //hier wird die Funktion aufgerufen
16
delay(1000);
17
Serial.println("Läuft noch");
18
}
19
void Strom(void){
20
//I = ina219.getCurrent_mA();       //hier wird die Funktion nicht aufgerufen.Warum?
21
Serial.println(I);
22
}
Gast #5956530
Lesenswert?

Generell ist es eine riskante Sache, aus Interrupts heraus Funktionen 
aufzurufen, die extern kommunizieren oder viel Speicher belegen. Dein 
Serial.println() halte ich dort ebenfalls für eine ganz schlechte Idee.

Denn Interrupts können andere Funktionen unterbrechen, die bereits viel 
Speicher belegt haben. RAM ist bei den kleinen AVR Mikrocontrollern 
knapp bemessen.
#5956535
Lesenswert?

Hallo,

auch wenn das hier warscheinlich nicht das Problem ist, solltest du 
Objekt so initialisieren das sie zum Aufrufzeitpunkt auch verfügbar 
sind.
Serial.begin() sollte also noch vor der Timer1.attachInterrupt() stehen, 
sonst könnte die ISR mit Serial.print() noch vor Serial.begin() 
ausgeführt werden.

Bekommst du vom Compiler irgendwelche Warnungen?

Sascha
Gast #5956605
Lesenswert?

Sandro N. schrieb:
> Sascha W. schrieb:
>> solltest du
>> Objekt so initialisieren das sie zum Aufrufzeitpunkt auch verfügbar
>> sind.
>
> Da hast du grundsätzlich recht aber wie du schon geschrieben hast spielt
> das hier keine rolle :-)
>
> Achso, und ich bekomme keine Probleme beim Compiler .

Aber, das Problem, hast du jetzt verstanden, oder?
#5956783
Lesenswert?

Sascha W. schrieb:
> Oder besser noch, im IRQ ein Flag setzen und in der Loop darauf
> reagieren. In Loop darf dann natürlich kein delay vorkommen.

ja, so habe ich das jetzt auch gelöst. Ich musste nur sicherstellen, 
dass der Code in einer Stunde genau 3600 mal ausgeführt wird.
Solange der Loop nicht länger als 1 Sekunde braucht sollte das auch 
funktionieren.
Ich hatte mich schon gefragt wozu so ein "Job Flag" gut sein soll. Mann 
kann ja alles in die ISR schreiben dachte ich. Aber in meinem Fall ging 
es eben doch nur über eine "Flag".
(Firma: egal) #5956791
Lesenswert?

Sascha W. schrieb:
> Brain 2.0 schrieb:
>> Und warum überhaupt per IRQ ?
>> 1 sek ist doch nicht zeitkritisch, das geht auch wunderbar in der loop.
> Oder besser noch, im IRQ ein Flag setzen und in der Loop darauf
> reagieren. In Loop darf dann natürlich kein delay vorkommen.
>
> Sascha

Oder in der IRQ erst den ADC-Wert sichern und dann den ADC neu starten.
So bracht man nicht Warten bis der ADC fertig ist, dar hat dann fast 
eine Sekunde zeit um fertig zu werden. Die Werte sind dann zwar eine 
Sekunde alt, dafür aber nirgends Wartezeiten wegen dem ADC. Und in 
etlichen Anwendungsfällen ist das durchaus langt das durchaus.
Moderator (Firma: Titel) Persönliche Seite #5956799
Lesenswert?

Sandro N. schrieb:
> Solange der Loop nicht länger als 1 Sekunde braucht sollte das auch
> funktionieren.
Für mich enthält eine main()-Loop, die mehr als 50ms(*) braucht, schon 
einen Fehler. Denn dort drin wird zyklisch alles abgearbeitet, was 
während des letzten Durchlaufs in den Interrupts so angefallen ist.

(*) je nach Anwendung 10..100ms

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