Forum: Mikrocontroller und Digitale Elektronik Arduino Nano - externe Interrupts


von Steffen S. (obelix76)


Lesenswert?

Hallo,

ich bin - was Arduino angeht - Neueinsteiger. Hab mir jetzt für kleines 
Geld einen Arduino Nano (V3) zum "spielen" geholt.

Ich bin am basteln mit einem RTC-Modul, dem DS3231 (jenes hier: 
http://www.ebay.de/itm/RTC-DS3231-AT24C32-Memory-Real-Time-Clock-IIC-Modul-fur-Arduino-PIC-CP14003-/271832393280?pt=LH_DefaultDomain_77&hash=item3f4a792640)
Später(tm) soll damit, dem Nano sowie zwei SAA1064 eine RTC-gesteuerte 
Uhr entstehen, aber das tut hier eher nix zur Sache. Ich bin noch an den 
"Basics"...

Das DS3231 ist dahingehend konfiguriert, daß es einen 1Hz Takt an seinem 
SQW-Pin ausgibt. Die beiden I2C-Leitungen sind im Modul bereits per 4,7K 
Pullups nach Vcc gezogen.

Folgende "Verdrahtung" auf dem Breadboard: SQW des RTC-Moduls an Pin D2 
des Nano. Dieser Signalausgang wird mit einem 10k Pullup-Widerstand nach 
Vcc gezogen. Ein 1Hz Signal kommt an dem nano auch an. SCL der RTC geht 
nach A5, SDA nach A4 am Nano. Vcc/GND am RTC gehen nach Vcc und GND am 
nano (da ich den im Moment über den USB mit Strom versorge und darüber 
auch serielle Ausgaben zum Debuggen abfange, power ich das RTC darüber 
gleich noch mit).

Das erstmal zum Aufbau, um möglichen Nachfragen vorzubeugen. ;)

Jetzt zu meinem Problem: Ich möchte mit dem 1Hz Signal der RTC im 
Sekundentakt folgendes machen: Mit der RTC "reden" und die Zeit abholen, 
diese dann über den seriellen Port ausgeben. Hatte ich so auch schon mit 
nem "blanken" Mega8 gemacht - und dort etwa 20ms in der ISR "verbraten".

mit dem Nano versuche ich das wie folgt zu lösen (minimal angepaßtes 
Beispiel aus der Lib):
1
/*
2
 * TimeRTC.pde
3
 * Example code illustrating Time library with Real Time Clock.
4
 * This example is identical to the example provided with the Time Library,
5
 * only the #include statement has been changed to include the DS3232RTC library.
6
 */
7
8
#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
9
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
10
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
11
12
int LED = 13;
13
volatile int state = LOW;
14
15
16
void setup(void)
17
{
18
    pinMode(LED, OUTPUT); 
19
    Serial.begin(9600);
20
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
21
    Serial.println("RTC.Get done");
22
    if(timeStatus() != timeSet) 
23
        Serial.println("Unable to sync with the RTC");
24
    else
25
        Serial.println("RTC has set the system time");  
26
    attachInterrupt(0, ISR0, RISING);        
27
}
28
29
void loop(void)
30
{
31
  delay(1000);
32
  //digitalClockDisplay();
33
}
34
35
void digitalClockDisplay(void)
36
{
37
    // digital clock display of the time
38
    printDigits(hour());
39
    Serial.print(":");
40
    printDigits(minute());
41
    Serial.print(":");
42
    printDigits(second());
43
    Serial.print(' ');
44
    printDigits(day());
45
    Serial.print('.');
46
    printDigits(month());
47
    Serial.print('.');
48
    printDigits(year()); 
49
    Serial.print(" - Temperatur: ");
50
    Serial.print(RTC.temperature()/4.0);
51
    Serial.print("°C");
52
    Serial.println();
53
}
54
55
void printDigits(int digits)
56
{
57
    if(digits < 10)
58
        Serial.print('0');
59
    Serial.print(digits);
60
}
61
62
void ISR0(){
63
  digitalClockDisplay()
64
  state = !state;
65
  digitalWrite(LED, state);
66
}

Der Code soll also bei jeder ISR die auslöst, die Abfrage an die RTC 
machen, alles am Serial ausgeben, die state-Variable togglen und die LED 
an Pin13 (die auf dem Board verlötete LED) umschalten.

Leider macht es das nicht... Am Serial Port werden genau zwei Zeichen 
ausgegeben ("RT") von dem String "RTC.Get done" in der setup(), danach 
"hängt" das System.

Verändere ich den Code, daß ich die digitalClockDisplay() aus der ISR 
rausnehme und in der loop() platziere (wie es das Beispiel im Original 
hatte), funktioniert das Konstrukt problemfrei.

Da ich den Controller allerdings nicht mit unsinnigem Warten 
beschäftigen will, wüßte ich jetzt gern, wo denn mein Denkfehler liegt. 
Hat jemand eine Idee, wo ich ansetzen könnte bzw. was ich offensichtlich 
verkehrt mache?

Danke schon mal vorab!



obelix

von chris (Gast)


Lesenswert?

Steffen S. schrieb:
> Verändere ich den Code, daß ich die digitalClockDisplay() aus der ISR
> rausnehme und in der loop() platziere (wie es das Beispiel im Original
> hatte), funktioniert das Konstrukt problemfrei.

Dann ist die UART-Routine wohl interruptbasiert geschrieben und wartet 
vermutlich blockierend auf freien Platz im FIFO. Da während der ISR alle 
Interrupts gesperrt sind, hast du somit einen Deadlock produziert.


Steffen S. schrieb:
> Da ich den Controller allerdings nicht mit unsinnigem Warten
> beschäftigen will,

Wieso sollte er denn dann sinnlos warten?
In der ISR setzt du ein Flag und wertest das in der main() aus. Wenn das 
Flag nicht gesetzt ist, gehst du in den Sleep Mode.

von Klaus (Gast)


Lesenswert?

> Da ich den Controller allerdings nicht mit unsinnigem Warten
> beschäftigen will,

Das ist nur dann ein sinnvoller Gedanke, wenn der uC stattdessen etwas 
anderes tun könnte. Und selbst dann noch fraglich.

> wüßte ich jetzt gern, wo denn mein Denkfehler liegt.

Genau darin.

> Verändere ich den Code, daß ich die digitalClockDisplay()
> aus der ISR rausnehme und in der loop() platziere (wie es das Beispiel im > 
Original hatte), funktioniert das Konstrukt problemfrei.

Das ist doch schön. Darum bemühen sich andere oft tagelang. Und Du 
änderst das freiwillig? OK. Aus dem Grund, den Du oben genannt hast, 
schon recht. Aber wie gesagt, das ist sinnlos.

von Steffen S. (obelix76)


Lesenswert?

Klaus schrieb:
> Das ist doch schön. Darum bemühen sich andere oft tagelang. Und Du
> änderst das freiwillig? OK. Aus dem Grund, den Du oben genannt hast,
> schon recht. Aber wie gesagt, das ist sinnlos.

vermutlich mein Problem des "warum einfach, wenns auch kompliziert geht" 
:))


chris schrieb:
> Dann ist die UART-Routine wohl interruptbasiert geschrieben und wartet
> vermutlich blockierend auf freien Platz im FIFO. Da während der ISR alle
> Interrupts gesperrt sind, hast du somit einen Deadlock produziert.

ok. Vermutlich bin ich noch im zu "linearen" abarbeiten von Quellcode 
festhängend - aber zu dem Zeitpunkt, wo das Programm sich festhängt, ist 
doch die ISR0-Routine noch gar nicht per Befehl "aktiviert" worden (ich 
hatte sie mit Absicht schon ganz ans Ende der setup() getan)? Oder ist 
die direkt nach dem Reset da, wenn man die mal irgendwo im Code 
definiert? dann könnt ich mir vorstellen, daß sich da was blockiert.


chris schrieb:
> Wieso sollte er denn dann sinnlos warten?
> In der ISR setzt du ein Flag und wertest das in der main() aus. Wenn das
> Flag nicht gesetzt ist, gehst du in den Sleep Mode.

okay. Danke für den Denkanstoß :) So scheint es zu funktionieren.

von Klaus (Gast)


Lesenswert?

Steffen S. schrieb:

> ok. Vermutlich bin ich noch im zu "linearen" abarbeiten von Quellcode
> festhängend - aber zu dem Zeitpunkt, wo das Programm sich festhängt, ist
> doch die ISR0-Routine noch gar nicht per Befehl "aktiviert" worden (ich
> hatte sie mit Absicht schon ganz ans Ende der setup() getan)? Oder ist
> die direkt nach dem Reset da, wenn man die mal irgendwo im Code
> definiert? dann könnt ich mir vorstellen, daß sich da was blockiert.

Hmmm. Da hebe ich mal leicht den rechten Zeigefinger und frage Dich, was 
genau Du denn, spätestens beim Blick in Dein Englisch-Wörterbuch, an dem 
Wort "Interrupt" nicht verstehst? ;-) OK. Lies es einfach nochmal.

Das über die Position des Textes der Interrupt-Routine ist irgendwie 
nicht völlig unvernünftig. Allerdings solltest Du folgendes schon mal 
gelesen habe:

1. Die Ausführung eines Programmes beginnt mit main - das das davon 
abhängt wo main im Text steht, steht nirgendwo und ist damit zwar nicht 
ausgeschlossen aber auch nicht ohne weiteres anzunehmen.

2. Die Ausführung einer Interrupt-Routine beginnt mit dem Auftreten des 
entsprechenden Ereignisses - ebenso hängt das weder von der Position im 
Programmtext ab noch ist das ohne weiteres anzunehmen.

:-)


Gewöhne Dir an, Deine Vermutungen, wenn Du sie nicht sofort nachprüfen 
kannst, erstmal zu notieren und abends im Bett mal nachzulesen bzw. ggf. 
bei Zeiten einen Versuch damit zu machen.

OK. Zeigefinger wieder runter.

Jetzt gehts ja. Schön.

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.