Kleine Daten auf dem Arduino speichern und wieder abrufen

Ich habe mir das kleine Sidekick von Arduino bestellt und wollte ein wenig damit experimentieren.
LEDs an- und ausschalten klappt schon mal. Ist toll wenn man etwas sieht.

Jetzt frag ich mich, wieviel der kleine Speicher auf dem Arduino aufnehmen kann und auch ob das permanent ist oder nur solange der Strom fließt.
Ich hatte mir gedacht zwei Buttons anzuschließen.
Der erste Button ist ein Counter und zählt heimlich im Hintergrund.
Wenn man den zweiten Button drückt soll eine Ausgabe im Serial Monitor erscheinen wie oft der erste Button gedrückt wurde.
Geht soetwas?
Und speichert der Arduino das auch wenn ich das USB-Kabel abziehe und nach einiger Zeit wieder einstecke?

Tipo:
Und speichert der Arduino das auch wenn ich das USB-Kabel abziehe und nach einiger Zeit wieder einstecke?

Der Arduino UNO hat 2 KB RAM-Speicher, der beim Ausschalten und beim Reset jedesmal gelöscht wird.

Und er hat zusätzlich 1 KB EEPROM-Speicher, der beim Ausschalten permanent erhalten bleibt.

Der EEPROM-Speicher darf unbegrenzt ausgelesen werden, aber er nutzt sich beim Schreiben ab und der Hersteller garantiert nur für 10.000 Schreibzyklen. Wenn Du zu häufig in den EEPROM-Speicher schreibst, wird der Speicher kaputtgeschrieben. Vorgesehen ist der EEPROM-Speicher eigentlich für dauerhafte Konfigurationseinstellungen, die sich eher selten ändern.

Eine Alternative ist vielleicht für Dich vielleicht ein DS1307 Uhrenmodul, das ist eine Echtzeituhr mit Batteriepufferung, die beim Ausschalten weiterläuft. Als kostenloses Goodie obendrauf hat die DS1307 einen ebenfalls batteriegepufferten RAM-Speicher von 56 Bytes. Dieser batteriegepufferte RAM-Speicher bleibt so lange erhalten, bis die Pufferbatterie entweder leer geworden ist oder aus dem Uhrenmodul herausgenommen wird.

Zunächst mal geht sowas natürlich.

Im einfachsten Fall ist die Anzahl der Tastendrücke weg wenn Du dem arduino den Strom klaust. Programm bleibt aber erhalten.
Im etwas aufwändigeren Fall schreibst Du die Anzahl beim Drücken in das nichtflüchtige Eeprom und liest es beim Start wieder aus.

Grüße
Klaus

Und speichert der Arduino das auch wenn ich das USB-Kabel abziehe und nach einiger Zeit wieder einstecke

Der Arduino kann auch über die runde Buchse mit 7V .. 12V versorgt werden, und läuft auch wenn kein USB Kabel steckt. Dann musst du nur googlen wie man erreicht, dass der Start des SerialMonitor kein Reset verursacht :wink:

jurs:
Eine Alternative ist vielleicht für Dich vielleicht ein DS1307 Uhrenmodul, das ist eine Echtzeituhr mit Batteriepufferung, die beim Ausschalten weiterläuft. Als kostenloses Goodie obendrauf hat die DS1307 einen ebenfalls batteriegepufferten RAM-Speicher von 56 Bytes. Dieser batteriegepufferte RAM-Speicher bleibt so lange erhalten, bis die Pufferbatterie entweder leer geworden ist oder aus dem Uhrenmodul herausgenommen wird.

Oh das hört sich ja Klasse an. Allerdings habe ich rein zufällig nur das DS1302 Uhrenmodel gekauft.
Laut Datasheet hat sie auch einen Speicher, aber nur 31 Bytes. Sollte aber reichen für ein paar Zahlen, oder?

michael_x:
Der Arduino kann auch über die runde Buchse mit 7V .. 12V versorgt werden, und läuft auch wenn kein USB Kabel steckt. Dann musst du nur googlen wie man erreicht, dass der Start des SerialMonitor kein Reset verursacht :wink:

Der Arduino ist für solch eine hohe Spannung ausgelegt?
Wielange hält er dann eigentlich?
Gibt es dazu irgendwelche Statistiken wielange ein Arduino unter Strom stehen kann bis er aufgibt?

Tipo:
Oh das hört sich ja Klasse an. Allerdings habe ich rein zufällig nur das DS1302 Uhrenmodel gekauft.
Laut Datasheet hat sie auch einen Speicher, aber nur 31 Bytes. Sollte aber reichen für ein paar Zahlen, oder?

Die Speicherung von Zahlen beansprucht genau so viel RAM im Uhrenmodul wie im RAM-Speicher des Arduino
byte - 1 Byte http://arduino.cc/de/Reference/Byte
integer - 2 Bytes http://arduino.cc/de/Reference/Int
long - 4 Bytes http://arduino.cc/de/Reference/Long
float - 4 Bytes http://arduino.cc/de/Reference/Float

Tipo:
Der Arduino ist für solch eine hohe Spannung ausgelegt?

Das Board hat einen Spannungsregler, der das auf 5V runter regelt. Der Prozessor läuft immer mit 5V.

Es ist aber ein Linearregler, d.h. die Differenz wird in Wärme umgesetzt. Daher besser mit 7V oder 9V versorgen als mit 12V. Vor allem wenn man viel Strom zieht.

Gibt es irgendwelche Statistiken wielange ein Arduino unter Strom stehen kann bis er aufgibt?

Ein paar Jahre solltens wohl schon werden...
Wenn du ihn mit einem Steckernetzteil mit z.B. 9V versorgst, und nur Taster und Signal-LED dran hast, wird der Spannungsregler sicher nicht zu heiss: 9V * ( 50 mA Arduino + 20mA LED) ~ 0.6W , davon ca. 4V * 70mA im Regler und 5V * 50mA in den beiden atmega controllern.

jurs:
Die Speicherung von Zahlen beansprucht genau so viel RAM im Uhrenmodul wie im RAM-Speicher des Arduino
byte - 1 Byte http://arduino.cc/de/Reference/Byte
integer - 2 Bytes http://arduino.cc/de/Reference/Int
long - 4 Bytes http://arduino.cc/de/Reference/Long
float - 4 Bytes http://arduino.cc/de/Reference/Float

Das heißt also, dass ich bei meinem Uhrenmodel mit 31 Bytes an RAM nur maximal 15 Integer Werte speichern kann?
Hm, nicht gerade viel. :~
Mal doof gefragt, ist es davon unabhängig ob ich 15x z.B. eine "10" speichere oder 15x eine "15000"?
Ich vermute mal, dass der Speicherplatz dann komplett reserviert wird, sobald ich einer Variablen den Typ Integer zuweise.
Gibt es dann auch einen Befehl, der mir sagt wieviel Speicher noch zur Verfügung steht?
Ich konnte bisher nur "read, write und clear" finden.

Nein. Die Verwaltung erledigst du auf dem Arduino. Wie bei anderem Speicher auch. Du kannst nur sagen "speichere Byte x auf Adresse y".

Wenn du keine Nullen abspeichern willst, kannst du den Speicher am Anfang einmal löschen und dann alle Zellen zählen die auf Null stehen. Oder du nimmst ein Byte indem du speicherst was noch frei ist, bzw. wie viel belegt ist.

Serenifly:
Nein. Die Verwaltung erledigst du auf dem Arduino. Wie bei anderem Speicher auch. Du kannst nur sagen "speichere Byte x auf Adresse y".

Wenn du keine Nullen abspeichern willst, kannst du den Speicher am Anfang einmal löschen und dann alle Zellen zählen die auf Null stehen. Oder du nimmst ein Byte indem du speicherst was noch frei ist, bzw. wie viel belegt ist.

Hui, ok. Ich stehe ja noch am Anfang aber habe gerade "Bahnhof" verstanden.
Ich habe mir wohl das falsche Tutorial (EEPROMWrite) angeschaut.
Da steht zwar auch etwas von einem Counter aber woher weiß ich denn dann wie weit der Counter gehen darf? Im Tutorial steht 512 für was das auch immer steht und bei dem Uhrenmodell? Uah, hilfe.
Ok ich kann einfach probieren bis wo ich schreiben darf. Allerdings sagt mir das dann ja noch immer nichts über den verbrauchten Platz aus bzw. wieviel noch frei ist.

Machen wir es mal einfacher. Du willst nur einen Zähler abspeichern. Wie viel Speicher du hast ist da vollkommen egal. Um einen 16 bit int abzuspeichern brauchst du nur 2 Bytes. Und du weißt immer wo die stehen. Die ganzen 31 Bytes brauchst du dafür sowie nicht. Du würdest deinen int einfach immer auf den Adressen 0 und 1 abspeichern.

Du musst also erst mal deinen int in Bytes aufteilen. Da gibt es mehre Optionen. Aber am einfachsten geht es so:

int counter;
byte low = lowByte(counter);
byte high = highByte(counter);

Das kann man dann auch einfach in einem Array speichern, für den Fall das die RTC Lib ein Array als Parameter will:

int counter;
byte bytes[2];
bytes[0] = lowByte(counter);
bytes[1] = highByte(counter);

Und nach dem Auslesen wieder zusammensetzen geht so:

counter = word(high, low);

Da kommt es dann darauf an in welchem Format deine RTC lib die Daten will. Oft wird da ein Byte Array und dessen Größe übergeben. Auch beim Auslesen des RAMs. Man erstellt dann einen Puffer und sagt der Funktion sie soll in beschreiben.

Als Adresse übergibt man die Anfangsadresse auszulesenden Bereichs.

Ich habe mir das selbst geschrieben und es so gemacht:

void DS1307RTC::setRAM(uint8_t rtc_addr, uint8_t* data, int size)
{}

Dann fülle ich einfach ein Array mit meinem Daten und übergebe die Start-Adresse (in deinem Fall 0), das Array und die Größe des Arrays (in deinem Fall 2).

Ein guter Weg mehrere Werte zu speichern ist einfach die Werte durch zu nummerieren:
RTC.setRAM(alarmNumber * ALARM_SIZE, data, ALARM_SIZE);

Bei meinem Programm ist ALARM_SIZE = 5. Dadurch wird alarmNumber 0 auf den Adressen 0-4 gespeichert. AlarmNumber 1 aber landet automatisch auf 5-9. AlarmNumber 2 ist dann 10-14, da 2 * 5 = 10, etc.

Aber da musst du wie gesagt mal deine RTC Lib anschauen. Das kann da auch anders sein! RAM Zugriff ist auch nicht bei allen Libs implementiert.

EDIT:
Ich nehme mal an die DS1302 fängt auch bei Adresse 0 an. Funktioniert nämlich etwa anderes wie bei den anderen RTCs. Das RAM fängt bei C0h an, aber es gibt einen speziellen "Burst Mode" um mehrere Zellen hintereinander anzusprechen. Und dafür fangen die Adressen explizit bei 0 an. Sowohl für RAM als auch die Clock Register.
Abgesehen davon setzten vernünftige Libs das intern um.

Verlinke mal zu deiner RTC Lib, dann kann man da auch genaueres sagen und dir genauen Code liefern :slight_smile:

Serenifly:
Verlinke mal zu deiner RTC Lib, dann kann man da auch genaueres sagen und dir genauen Code liefern :slight_smile:

Danke für die ausführliche Beschreibung.
Hm ... mir ist gerade aufgefallen, dass der Anbieter gar kein Datasheet bereithält.
Hier habe ich die DS1302 Real Time Clock Module gerade erst gekauft. Ist aber noch eingepackt. :smiley:
Ich versuche mal etwas mehr darüber zu finden.

Edit:
Toll, das Modell findet sich ja direkt hier bei Arduino wieder: Arduino Playground - HomePage
Allerdings sind meine Pins alle auf einer Seite, aber sie sind ja beschriftet. :wink:

Datenblatt gibt es hier:
http://datasheets.maximintegrated.com/en/ds/DS1302.pdf

So extrem anders wie die DS1307 ist es nicht, aber man benötigt eine spezielle Lib dazu.

Das gibt es für den Arduino mehrere Libs. Ich würde mal mit der anfangen:
http://www.henningkarlsen.com/electronics/library.php?id=5

Die hat nämlich Lesen und Schreiben von Arrays und einzelnen Werten mit relativen Adressen. Das ist bei zwei anderen Libs die ich gesehen habe schon mal nicht der Fall (da ging nur ein Byte auf die physikalische Adresse)

Doku ist auch dabei:
http://www.henningkarlsen.com/electronics/resource/DS1302/DS1302.pdf

Du willst erst mal poke() und peek() zum Lesen und Schreiben. Das kann du dann einfach 0 und 1 als Adresse übergeben

Tipo:
Toll, das Modell findet sich ja direkt hier bei Arduino wieder: http://playground.arduino.cc/Main/DS1302
Allerdings sind meine Pins alle auf einer Seite, aber sie sind ja beschriftet. :wink:

Würde ich dir nicht empfehlen, da das erstens keine richtige Lib ist und zweitens mit physikalischen Adressen arbeitet.

Ok, vielen Dank.
Ich hätte jetzt eigentlich gedacht, dass die Libs vom Hersteller kommen.
Dem ist dann wohl nicht so.
Denn dein Link verweist ja auf eine private Seite.

Kann ich also nicht mit hauseigenen Mitteln von Arduino auf diese RTCs zugreifen und sie verwalten?

Klar kann man. Das ist auch nicht so extrem schwer. Ich habe bei mir den RAM Zugriff z.B. selbst implementiert da das bei anderen Libs für meine Bedürfnisse nicht zufriedenstellend gemacht war.

Aber es ist nicht mit ein paar Zeilen hier und da getan, sondern braucht einiges an Code. Also wieso das Ratd neu erfinden wenn es Libs dafür gibt? :slight_smile:

Und die Libs gibt es nicht vom Hersteller weil die nicht Libs für alle Mikroprozessoren und Boards auf dem Markt schreiben können.