Forum: Mikrocontroller und Digitale Elektronik Arduino UNO mit I2C und SPI Bus


von thomo999 (Gast)


Lesenswert?

Hallo,

ich nutze hier einen Arduino UNO mit einem SD-Card Board am SPI als 
Logbuch für Amateurfunkverbindungen. Jetzt wollte ich das Projekt um 
eine RTC (Chip DS1307) am I2C erweitern.
Leider läuft die RTC nur wenn das SD Board nicht angeschlossen ist am 
SPI.

Kann es sein das der UNO beide Busse nicht gleichzeitig kann. Denn die 
Pins sind ja unterschiedlich.  SPI 10-13 I2C A4-5.

Danke für die Antworten im Voraus.

von Stefan S. (sschultewolter)


Lesenswert?

thomo999 schrieb:
> Kann es sein das der UNO beide Busse nicht gleichzeitig kann. Denn die
> Pins sind ja unterschiedlich.  SPI 10-13 I2C A4-5.

Nein! TWI/I2C und SPI können auch "gleichzeitig" arbeiten. Sicher dass 
du deinen Sketch/Code vermurkst hast?

von Jürgen S. (jurs)


Lesenswert?

thomo999 schrieb:
> ich nutze hier einen Arduino UNO mit einem SD-Card Board am SPI als
> Logbuch für Amateurfunkverbindungen. Jetzt wollte ich das Projekt um
> eine RTC (Chip DS1307) am I2C erweitern.
> Leider läuft die RTC nur wenn das SD Board nicht angeschlossen ist am
> SPI.
>
> Kann es sein das der UNO beide Busse nicht gleichzeitig kann. Denn die
> Pins sind ja unterschiedlich.  SPI 10-13 I2C A4-5.

Doch, das funktioniert bestens.

Allerdings sehe ich im Arduino-Forum immer wieder Programmieranfänger, 
die mit 2 KB RAM-Speicher nicht viel anfangen können. Die verschwenden 
sinnlos RAM-Speicher durch ineffektive Programmierung, obwohl sie 
eigentlich RAM-Speicher möglichst sparsam verwenden müßten, und wundern 
sich dann, dass das Programm nicht läuft.

Da die SD-Library alleine schon gut 1 KB RAM wegschluckt, müßte der Rest 
des Programms mit deutlich unter 1 KB RAM-Speicher arbeiten können. Das 
ist eigentlich locker möglich. Aber nicht jeder Anfänger bekommt das so 
ohne weiteres hin.

Beispiel "Ausgabe von String-Konstanten":
1
Serial.println("Hallo, das ist ein Test");
Die Zeile braucht 23 Bytes RAM-Speicher.
Die folgende Variante mit dem F-Makro macht im Endeffekt dasselbe, 
braucht aber keinen zusätzlichen RAM-Speicher:
1
Serial.println(F("Hallo, das ist ein Test"));

Ein anderes Beispiel ist die Verwendung von RAM schluckenden "Libraries" 
für irgendwelche Pillepalle Funktionen, die man sich sonst auch direkt 
hinschreiben kann. Zum Beispiel zum Lesen oder Schreiben einer Uhrzeit 
auf einer DS1307: Das machst Du entweder mit einer eigenen Funktion. 
Oder mit einer Library. Die Library erzeugt im allgemeinen mehr Overhead 
und RAM-Verbrauch im Programm.

Und wenn das Programm mehr RAM brauchen würde als der Controller 
eingebaut hat, läuft das Programm nicht mehr.

von thomo999 (Gast)


Lesenswert?

Danke erstmal für die schnellen Antworten.

Danke auf für den Tip mit dem F Makro, den kannte ich noch nicht.

Ich habe mich vielleicht oben nicht ganz richtig ausgedrückt. Ich habe 
natürlich um Fehler auszuschließen, nicht nur mit meinem eigenen 
Programm getestet. Der Fehler tritt schon auf, wenn ich nur das SD Card 
Board anstecke und nur eines der Exempel Programme der RTC Lib nutze, 
dh. die SD Card Lib ist gar nicht geladen und die SD wird auch nicht 
angesprochen. Hängt also nur elektrisch mit am Arduino und am SPI Bus, 
unter folgenden PINS 11 12 13 SPI Bus Pin 8 ist CS (chip select), die 
RTC hängt an den beiden i2c Pin oberhalb von PIN 13 die dort in der SMD 
version vom uno extra heraus geführt wurden.

Mein Originalprogramm welches ich selbst geschrieben habe, nutzt 18KB 
Flash und 1297Byte für globale Variablen es bleiben 751 Byte für lokale 
Variablen.
siehe  Compilerausgabe.
1
Der Sketch verwendet 18.788 Bytes (58%) des Programmspeicherplatzes. Das Maximum sind 32.256 Bytes.
2
Globale Variablen verwenden 1.297 Bytes (63%) des dynamischen Speichers, 751 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.

von Stefan S. (sschultewolter)


Lesenswert?

Jurs treibt sich ja auch hier rum ;) wink


thomo999 schrieb:
> Ich habe mich vielleicht oben nicht ganz richtig ausgedrückt. Ich habe
> natürlich um Fehler auszuschließen, nicht nur mit meinem eigenen
> Programm getestet. Der Fehler tritt schon auf, wenn ich nur das SD Card
> Board anstecke und nur eines der Exempel Programme der RTC Lib nutze,
> dh. die SD Card Lib ist gar nicht geladen und die SD wird auch nicht
> angesprochen. Hängt also nur elektrisch mit am Arduino und am SPI Bus,
> unter folgenden PINS 11 12 13 SPI Bus Pin 8 ist CS (chip select), die
> RTC hängt an den beiden i2c Pin oberhalb von PIN 13 die dort in der SMD
> version vom uno extra heraus geführt wurden.
Ob nun oben oder unten auf A4/5. Intern ist es der gleiche Pin des 368p.

> Mein Originalprogramm welches ich selbst geschrieben habe, nutzt 18KB
> Flash und 1297Byte für globale Variablen es bleiben 751 Byte für lokale
> Variablen.
> siehe  Compilerausgabe.
>
>
1
Der Sketch verwendet 18.788 Bytes (58%) des 
2
> Programmspeicherplatzes. Das Maximum sind 32.256 Bytes.
3
> Globale Variablen verwenden 1.297 Bytes (63%) des dynamischen Speichers, 
4
> 751 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
5
>
Für die Funktionen die du beschrieben hast, ist das deutlich zu viel!

Leg mal folgende Funktion an und lass dir den Rückgabewert ausgeben.
1
int getFreeRAM() 
2
{
3
  extern int __heap_start, *__brkval; 
4
  int v; 
5
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
6
}


Und mal hier deinen Sketch reinstellen inkl. der Verweise zu den Libarys 
wäre für die Lösung nicht verkehrt.

von Jürgen S. (jurs)


Lesenswert?

thomo999 schrieb:

> die RTC hängt an den beiden i2c Pin oberhalb von PIN 13 die dort in der
> SMD version vom uno extra heraus geführt wurden.

???

Neben Pin-13 haben alle UNOs erstmal noch zwei Pins: GND und AREF.
Das ist auch beim "UNO SMD" Board nicht anders.

Erst mit dem "R3" Design wurden zwei extra Pins eingeführt, also z.B. 
beim "UNO R3" Board. Aber SDA und SCL sitzen dann nicht neben Pin-13, 
sondern neben dem AREF-Pin, sind also der dritte und vierte Pin oberhalb 
Pin-13, wenn es ein R3-Board mit diesen Pins ist!

> Der Fehler tritt schon auf, wenn ich nur das SD Card
> Board anstecke und nur eines der Exempel Programme der RTC Lib nutze,
> dh. die SD Card Lib ist gar nicht geladen und die SD wird auch nicht
> angesprochen.

Also Dein selbstgeschriebenes Programm mal außen vor und nur bezogen auf 
das RTC-Demoprogramm:
- nur mit RTC-Modul funktioniert das RTC-Demoprogramm einwandfrei?
- mit zusätzlich angestecktem SD-Modul funktioniert das RTC-Demoprogramm 
dann nicht mehr?

von thomo999 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,
die Ausgabe von deiner Funktion im Seriellen Monitor ist 697 also meiner 
Meinung nach immer noch genug.
Ich hänge mal mein Programm mit als zip an. Ich sage aber dazu, das ist 
eines meiner lauffähigen Programme, in dem ich gestern quick and dirty 
reingeschrieben habe und zwar geändert sind die Zeilen 66 - 72 in main 
loop. weil ich mir nur die Zeit erstmal auf dem DISPLAY ausgeben lassen 
wollte. Der Rest ist jetzt noch nicht geprüft. Das Originalprogramm lief 
mit einer DCF77 Uhr über ein Jahr problemlos, leider kann ich die nicht 
nutzen im Auto da stört vermutlich der CAN Bus, deshalb jetzt auch der 
Umbau auf RTC.
Ich glaube nicht das es an meinem Progamm liegt!! Denn die RTC läuft 
bereits dann nicht wenn ich nur das rtc exampel Programm lade und dazu 
elektrisch die SD Karte anstecke, also kann es eigentlich nicht an 
meinem Programm liegen.

von Stefan S. (sschultewolter)


Lesenswert?

Ich geh jetzt einfach mal den Sketch Stück für Stück durch und sag dir 
was mich stört.

Anstatt des DS1307 kannste besser direkt den DS3231 nehmen. Kostet ~4€ 
in der Bucht. Arbeitet deutlich genauer.

Dann solltest du für das LCD Display nicht den ArduinoPin 0 und 1 
nutzen. Dieser wird kann zu Problemen während des Uploads über den 
FTDI/16u2 führen.

Du kannst die Taster auch mit mehreren an einem Analogen Pin betreiben 
und über unterschiedliche Widerstandswerte den entsprechenden 
Tasterdruck erkennen. 3-4 Taster sollten kein Problem sein.

"lcd.print("SyncTime");" verschleudert wieder zuviel Speicher. Wenn 
möglich das F-Macro nutzen. lcd.print(F("SyncTime"));

180ms (zzgl. Sendezeit über UART) ist etwas wenig. Könnte zu Flackern 
beginnen.
Des weiteren Bedarf es keinerlei Strings. Du ließt hier Int Werte ein 
ohne jegliche Formatierung. Das ist unnötig.

Bei den Sekunden arbeitest du mit führenden Nullen, warum nicht auch 
direkt bei Minuten und bei Stunden mit Leerzeichen?

Am besten schau dir mal die Streaming Lib in Arduino an, oder nutzte 
sprinft.

Du solltest zudem auch nicht immer das Display unnötig überschreiben. Es 
reicht nur die entsprechenden Zeiten neuzusetzen. Der ':' wird sich 
bspw. nie Ändern.


So weiter mit der praefix Datei. Für strPrafix solltest du PROGMEM 
anwenden.

In schreibeDaten sehe ich wiedermals dass du lcd.clear() nutzt. Das ist 
nach wie vor langsam und ineffizient. Besser bestimmte Stellen mit ' '
 füllen.

suffix ist das gleiche wie schon bei praefix.

Befindet sich deine RTClib wirklich im gleichen Ordner wie der andere 
Sketch von dir? Wenn nein, dann sollte < > anstatt " " genommen werden.

von thomo999 (Gast)


Lesenswert?

Hallo Stefan,

danke für die vielen nützlichen Tip's, die ich von dir erhalte, werde 
ich bei der Neuprogrammierung mit umsetzen.
Allerdings ist mir eine Sache noch nicht ganz klar. Ich habe heute 
nochmal folgenden Versuch durchgeführt.

Ich habe die SD Karte abgeklemmt und auch das LCD, es waren nur noch der 
UNO und die RTC in Betrieb. Dann habe ich das Beispielprogramm (siehe 
unten) aufgespielt und siehe da die RTC liefert wie gewünscht die 
richtige Zeit in der Seriellen Ausgabe.
Dannach habe ich das LCD angeklemmt alles IO , anschließend dann die SD 
Karte. Schon läuft die RTC nicht mehr, es wird dann 2165 als Jahr 
angezeigt etc.... obwohl im Beispielprogramm die SD Karte nicht mal 
ansatzweise angesprochen wird.
Das ist es was mir die Fragezeichen in die Augen wirft.
Hier mal das Beispielprogramm der Lib welches ich genutzt habe, ist also 
nicht mein Code! Sondern der vom Lib-Entwickler mitgelieferte.
Vielleicht kannst du mir zu diesem Verhalten nochmal etwas schreiben.
Vielen Dank im Voraus.

1
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
2
3
#include <Wire.h>
4
#include "RTClib.h"
5
6
RTC_DS1307 rtc;
7
8
void setup () {
9
  Serial.begin(57600);
10
#ifdef AVR
11
  Wire.begin();
12
#else
13
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
14
#endif
15
  rtc.begin();
16
17
  if (! rtc.isrunning()) {
18
    Serial.println("RTC is NOT running!");
19
    // following line sets the RTC to the date & time this sketch was compiled
20
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
21
    // This line sets the RTC with an explicit date & time, for example to set
22
    // January 21, 2014 at 3am you would call:
23
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
24
  }
25
}
26
27
void loop () {
28
    DateTime now = rtc.now();
29
    
30
    Serial.print(now.year(), DEC);
31
    Serial.print('/');
32
    Serial.print(now.month(), DEC);
33
    Serial.print('/');
34
    Serial.print(now.day(), DEC);
35
    Serial.print(' ');
36
    Serial.print(now.hour(), DEC);
37
    Serial.print(':');
38
    Serial.print(now.minute(), DEC);
39
    Serial.print(':');
40
    Serial.print(now.second(), DEC);
41
    Serial.println();
42
    
43
    Serial.print(" since midnight 1/1/1970 = ");
44
    Serial.print(now.unixtime());
45
    Serial.print("s = ");
46
    Serial.print(now.unixtime() / 86400L);
47
    Serial.println("d");
48
    
49
    // calculate a date which is 7 days and 30 seconds into the future
50
    DateTime future (now.unixtime() + 7 * 86400L + 30);
51
    
52
    Serial.print(" now + 7d + 30s: ");
53
    Serial.print(future.year(), DEC);
54
    Serial.print('/');
55
    Serial.print(future.month(), DEC);
56
    Serial.print('/');
57
    Serial.print(future.day(), DEC);
58
    Serial.print(' ');
59
    Serial.print(future.hour(), DEC);
60
    Serial.print(':');
61
    Serial.print(future.minute(), DEC);
62
    Serial.print(':');
63
    Serial.print(future.second(), DEC);
64
    Serial.println();
65
    
66
    Serial.println();
67
    delay(3000);
68
}

von Jürgen S. (jurs)


Lesenswert?

thomo999 schrieb:
> Hier mal das Beispielprogramm der Lib welches ich genutzt habe, ist also
> nicht mein Code! Sondern der vom Lib-Entwickler mitgelieferte.

Ach das beknackte Teil mal wieder.

Grundsätzlich würde ich, wenn Du SPI-Hardware dranklemmst, diese 
SPI-Hardware so ansteuern, dass sie nicht aktiviert wird. Also sowohl 
Hardware-Chipselect und den Chipselect Deines SD-Moduls auf OUTPUT/LOW 
setzen.

Und nach "Wire.begin()" eine kleine Pause machen.

Setup also dann ungefähr so:
1
void setup () {
2
  pinMode(SS,OUTPUT); // SPI Hardware-Chipselect auf Output/Low
3
  pinMode(8,OUTPUT);  // SPI Chipselect der SD-Karte auf Output/Low
4
  Serial.begin(57600);
5
#ifdef AVR
6
  Wire.begin();
7
#else
8
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
9
#endif
10
  delay(100); // Kleines delay nach Wire.begin()
11
  rtc.begin();
12
13
  if (! rtc.isrunning()) {
14
    Serial.println("RTC is NOT running!");
15
    // following line sets the RTC to the date & time this sketch was compiled
16
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
17
    // This line sets the RTC with an explicit date & time, for example to set
18
    // January 21, 2014 at 3am you would call:
19
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
20
  }
21
}

Macht das einen Unterschied?

von thomo999 (Gast)


Lesenswert?

Hallo Jürgen,

was soll ich sagen , ES GEHT !!

Damit ist das Problem gelöst, mit den Tips von dir und Stefan, werde ich 
mein Programm entsprechend umschreiben.

Vielen Dank für eure HILFE.

Gruss Thomas

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.