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.
#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
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.
> 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.
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.
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.