Werte im RAM speichern

Hi,
kann ich Werte fest im RAM speichern, so dass die auch noch vorhanden sind, wenn der Arduino mal ausgeschaltet wird?

Mein Problem ist, dass meine Software aktuell regelmäßig abschmiert, dann der Arduino aber sofort neu startet.
Gerne würde ich alle Uhrzeiten so speichern, dass ich die später nachvollziehen kann, sprich nicht nur den Zeitpunkt des letzen Reboots sondern auch vorherige.
Dadurch erhoffe ich mir, vielleicht ANsätze zu finden, wo der Fehler in meinem Programm ist, wenn zb der Abstuz immer in regelmäßigen ABständen oder immer dann wenn eine bestimmte FUnktion ausgeführt wird.

Gruß

Im EEProm ist das leicht. Im RAM geht das nur wenn der Strom nicht unterbrochen wird. Das klappt aber auch nicht immer. Siehe hier: http://arduino.cc/forum/index.php/topic,56809.0.html. Dort wird diskutiert, wie das geht. Weiterhin stellen alle fest, daß es bei Ihnen klappt, nur bei mir nicht :frowning:

Falls Die Uhrzeit aus einer RTC kommt wäre es am einfachsten diese Zeit direkt nach dem Rest ins EEProm zu schreiben.

Hi Udo,

die Zeit kommt vom RTC.
Wie schreibe ich in den EEPRom? Bleiben die Daten dort auch bestehen, wenn der Arduino erneut resettet? Mir geht es ja darum, nicht nur die letzte Zeit des Absturzes zu erfassen sondern alle die passieren.

Gruß
THorsten

EDIT//
Schon gefunden:

Hi,
so ganz komm ich noch nicht klar, hoffe ihr könnt aufklören:
Den Bsp Code habe ich in den Tutorials gefunden:

/*
 * EEPROM Write
 *
 * Stores values read from analog input 0 into the EEPROM.
 * These values will stay in the EEPROM when the board is
 * turned off and may be retrieved later by another sketch.
 */

#include <EEPROM.h>

// the current address in the EEPROM (i.e. which byte
// we're going to write to next)
int addr = 0;

void setup()
{
}

void loop()
{
  // need to divide by 4 because analog inputs range from
  // 0 to 1023 and each byte of the EEPROM can only hold a
  // value from 0 to 255.
  int val = analogRead(0) / 4;
  
  // write the value to the appropriate byte of the EEPROM.
  // these values will remain there when the board is
  // turned off.
  EEPROM.write(addr, val);
  
  // advance to the next address.  there are 512 bytes in 
  // the EEPROM, so go back to 0 when we hit 512.
  addr = addr + 1;
  if (addr == 512)
    addr = 0;
  
  delay(100);
}

EIn paar Fragen:

  1. Muss das unbedingt das analoge Eingangssignal sein oder kann ich da auch irgendeine variable (Uhrzeit speichern)?
  2. Kann ich auch 2 Werte gleichzeitig speichern? (Stunde + Minute) Sind das dann addr=0 & addr=1? (Also muss ich jedesmal 2 plätze belegen?
  3. Wie funktioniert das mit der ForSchleife, so dass alte Werte nicht überschrieben werden? Obiges Beispiel: Die For-Schleife würde doch nach jedem Reset wieder bei addr=0 anfangen? Sollte aber eigentlich so laufen, dass ich folgend speicher:
    Absturz1 zB um 15:12 => EEPROM.write(o, 15); EEPROM.write(1, 12);
    Absturz2 zB um 18:59 => EEPROM.write(2, 18); EEPROM.write(3, 59);
    etc....
    habe ich das richtig durchschaut?=
    Gruß

Hallo,

ich würde als erstes ein kleines Programm schreiben und damit 1-2 Byte einer gewählten Adresse mit einer Anfangsadresse (z.B.100) belegen.
Dein eigentliches Programm liest dann diesen Zähler und Speichert ab da dann Deine entsprechenden Werte ab und ändert als Abschluss die Anfangsadresse. Somit kann Du dann über ein weiteres Programm dann die Werte auslesen und Anfangsadresse wieder neu festlegen.

Beispiel schreiben und lesen :

void EEPROMaus()
{SensorADR=200;
for(i=0;i<4;i++)
{A=byte(Sensor[i] >> 8);
EEPROM.write(SensorADR,A);
SensorADR++;
A=byte(Sensor[i] & 0x0FF);
EEPROM.write(SensorADR,A);
SensorADR++;
}}
void EEPROMein()
{SensorADR=200;
for(i=0;i<4;i++)
{A=EEPROM.read(SensorADR);
SensorADR++;
B=EEPROM.read(SensorADR);
SensorADR++;
Sensor[i]=int (A << 8)+ int(B);
//Serial.println(Sensor[i]);
}}

Die Daten musst Du so aufbereiten, dass sie byteweise abgelegt werden können.

Gruss Kalli

ganz einfach:
Folgendes gilt für den ATmega328. Andere Controller haben verschiedene Größe von EEPROM.

EEPROM.write(addr, val); schreibt an die Adresse addr den Wert val. Adresse muß zwischen 0 und 1023 sein, val zwischen 0 und 255.

val = EEPROM.read(address); speichert man den Inhalt der Speicherzelle an der Adresse addr in der Variablen val.

Das schreiben des EEPROMs ist sehr langsam ( ca 10mSek).

Problemchen:
Du willst ständig die Werte neu schreiben, damit Du weißt, ob und wann das Programm abgestürzt ist.

Ein EEPROM ist nicht das richtige.

Da Du einen RTC hast (mit einigen Byte gepufferten RAM) schlage ich vor, daß Du dort die Zeit ablegst und dauernd updatest. Dann beim Neustart des Arduino im setup() liest Du die Zeit aus dem RAM des RTC und speicherst sie in der nächsten freien Speicherzelle des EEPROMS. Die Adresse der nächsten freie Speicherzelle speicherst Du im RAM des RTC.

Grüße Uwe

Ist noch die Frage, wie ich auf den RTC schreiben kann?
Gruß

andere Frage: welche RTC hast Du? :wink: :wink: :wink:

DS1307 :slight_smile:

Hallo currymuetze

Die Adressen 0 bis 0x07 sind Register in denen die Zeit und das Datum abgespeichert ist und ständig weitergezählt wird.

Zwischen 0x08 und 0x3f (08 und 63 dezimal) ist 56 Byte Ramspeicher.

Die Register können einfach wie jedes I2C Gerät angesprochen werden. Oder Du benutzt diese Bibliothek: GitHub - davidhbrown/RealTimeClockDS1307: Yet another DS1307 Real-Time Clock library for Arduino (obsolete) .

mit den Funktionen:

data=RTC.readData(addr);  // RAM auslesen
RTC.writeData(addr, data); //daten in RAM abspeichern

wobei addr eine Adresse zwischen 8 und 63 dezimal ist und "data" eine zahl zwischen 0 und 255 dezimel.

Grüße Uwe

Ich schmeiß hier mal meinen Code rein. habe zwei Funktionen genau diesbezüglich geschrieben für meine Nixieclock.

void SaveByte(byte x,byte y){                       // Funktion SaveByte("Position","Daten") Daten in Byte Format
  Wire.begin();                                    // Start I2C Kommunikation
  Wire.beginTransmission(RTC_ADDRESS);            // Beginn Kommunikation auf  Adresse 0x68 
  Wire.send(x+0x07);                             // Speicher Register Adresse+0x07   Adresszähler 1-56 wenn 0-55 dann (+0x08) 
  Wire.send(y);                                 // zu Speicherndes Byte
  Wire.endTransmission();  
}

byte ReadByte(byte x){                             // Funktion ReadByte ("Position") Daten in Byte Format
  byte z;
  Wire.beginTransmission(RTC_ADDRESS);
  Wire.send(x+0x07);
  Wire.endTransmission();
  Wire.requestFrom(RTC_ADDRESS, 1);
  z=Wire.receive();
  return z;
}