Frage zu Interrupts bei Atmega32U (Arduino Micro)

OP #3022669
Lesenswert?
• ▲
▼
Moin,

ich habe mir mit einem Arduino Micro eine kleine Sensoranzeige gebaut. 
Das Teil hat - neben den diversen Sensoren (DS1820, DHT22, SCT13 und 
LDR) - 2 Buttons. Mit dem einen dieser Buttons kann man durch eine 
Menüstruktur gehen (nur 1 Ebene: einfach eine Seite pro Sensor, recht 
primitiv also).

Das Ding funktioniert soweit so wie ich das haben wollte: 
http://youtu.be/kgwBwX49tQ8 . Das hier ist der aktuelle Source: 
http://www.daemon.de/idisk/Sensorita.ino.txt.

Nun habe ich folgendes Problem: zunächst hatte ich die Tastendrücke 
einfach innerhalb der loop()-Funktion abgefragt. Da jedoch das Auslesen 
der ganzen Sensoren etwas Zeit in Anspruch nimmt, ist es immer mal 
wieder dazu gekommen, dass ein Tastendruck ignoriert wurde. Das habe ich 
gelöst, indem ich die Tastendrücke über Interrupts abfrage (siehe Code). 
Das funktioniert soweit wunderprächtig, führt aber zu einem anderen 
Problem: hin und wieder (schwierig reproduzierbar) erscheint unmittelbar 
nach einem Tastendruck Zeichensalat auf dem LCD. Abgestürzt ist er dann 
nicht, weil er immer noch auf die Buttons reagiert und sich die Anzeige 
auch ändert (von einem Salat zum nächsten). Ich gehe daher davon aus, 
dass das deshalb passiert, weil der Interrupt in dem Moment eine 
laufende Sensorabfrage unterbrochen hat und dadurch irgendwelche 
Variablen leer/falsch befüllt sind (also ein Bufferoverflow ausgelöst 
wird).

Die Frage ist nun: wie kann man sowas lösen? Ich möchte, dass das Gerät 
grundsätzlich auf Tastendrücke ohne grosse Verzögerung reagiert und 
trotzdem alle 5 Sekunden die Sensoren ausgewertet werden ohne, dass der 
Vorgang unterbrochen wird. Ich könnte zwar während der Sensorabfrage 
temporär die Interrupts abschalten, was aber wieder zu Problem Nummer 1 
führt, dass ab und zu Tastendrücke untergehen.
#3024679
Lesenswert?
• ▲
▼
Taster über Interrupts sind meistens keine gute Idee.

Was du aber tun könntest, um in deinem Programm nicht allzuviel ändern 
zu müssen.
1
void get_sensors () {
2
  // fetch all sensor readings
3
  get_dallas();
4
  get_lux();
5
  get_dht();
6
  get_current();
7
}

kein Mensch zwingt dich, immer alle Sensoren zur gleichen Zeit 
auszulesen.

Wenn du das zeitlich staffelst, dann dauert das Auslesen lediglich eines 
Sensors nicht so lange. Dafür liest du eben alle halbe Sekunde einen 
anderen der Sensoren aus.

Speziell die hier
1
void get_dallas () {
2
  // fetch all dallas DS1820 temperature readings
3
  sensors.requestTemperatures();
4
  for (int id=0; id<TempPins; id++) {
5
    CurrentTemps[id] = sensors.getTempCByIndex(id);
6
  }
7
}
werden den Löwenanteil der Zeit beim Sensorauslesen benötigen.
Aber wie gesagt: lies halt nicht alle auf einmal, sondern bei jedem
1
void loop(void) {
2
  // record current moments
3
  LCDMoment = SensorMoment = millis();
4

5
  // check if there is enough time gone, to re-check the sensors
6
  if (SensorMoment - SensorTimer > SensorReadIntervall) {
7
    get_sensors();

einen nur EINEN anderen. Aber eben jedesmal reihum jeweils den nächsten.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.