Wie merke ich mir Variablenwerte nach dem Neustart einer Arduino Uno R3-Karte?


7

Gibt es eine Möglichkeit, die Werte der erforderlichen Variablen irgendwo zu speichern (möglicherweise in einer Datei, die bei verschiedenen Ereignissen vom Programm aktualisiert wird), die beim Programmstart nach dem Neustart der Arduino-Karte zurückgelesen werden kann?

Ich versuche, meine AC-Geräte mit der IR-Fernbedienung zu steuern. Wo ich möchte, dass Arduino sich daran erinnert, was in meinem Zimmer nach einem Stromausfall eingeschaltet und was ausgeschaltet war.

Die Verwendung von EEPROM scheint eine ziemlich gute Lösung zu sein, obwohl die Beschränkung auf 100.000 Schreibvorgänge begrenzt ist, weshalb ich versuche, einen anderen Ausweg zu finden.

Die Verwendung eines externen EEPROMs, das diese Einschränkung nicht aufweist oder ziemlich groß ist, ist eine wirklich gute Idee, die ich von fuenfundachtzig erhalten habe, danke für diese großartige Idee. Aber ich weiß nicht, wie ich das in meinem Projekt umsetzen soll. Jede Ressource, um Wissen über die Verwendung eines externen EEPROM zu sammeln, wird sehr geschätzt.

Danke euch allen...


Wenn Sie sich nur Gedanken über einen Neustart und nicht über das Aus- und Wiedereinschalten machen, können Sie RAM verwenden - Sie müssen lediglich verhindern, dass Init-Code ihn löscht. Wenn Sie das Power Cycling auch überleben müssen, brauchen Sie natürlich das EEPROM.
Chris Stratton

Eigentlich mache ich mir große Sorgen um das Power Cycling. Ich versuche, meine AC-Geräte mit der IR-Fernbedienung zu steuern. Wo ich möchte, dass Arduino sich daran erinnert, was in meinem Zimmer nach einem Stromausfall eingeschaltet und was ausgeschaltet war.
Samik Chattopadhyay

Antworten:


6

Der interne RAM des Arduino wird zurückgesetzt, wenn Sie den Chip neu starten. Wenn Sie also Ihre Daten behalten möchten, müssen Sie sie im EEPROM speichern.

Wenn Sie sich Sorgen über die begrenzten Schreib- / Löschzyklen machen, sollten Sie abschätzen, wie oft die Daten aktualisiert (dh in das EEPROM geschrieben) werden und wie lange Sie die Lebensdauer des von Ihnen erstellten Geräts planen. Wenn 100.000 Zyklen dann immer noch ein Problem sind, haben Sie mehrere Möglichkeiten:

  • Behalten Sie die Variablen im RAM und schreiben Sie sie nur etwa alle 5 Minuten in das EEPROM (100.000 Zyklen werden dann etwa ein Jahr lang kontinuierlich verwendet, bis das EEPROM möglicherweise ausfällt).
  • Verwenden Sie ein externes EEPROM (in einer Steckdose), das bei Bedarf leicht ausgetauscht werden kann.
  • Wenn das Ersetzen keine Option ist, sollten Sie stattdessen einen FRAM verwenden (Vorteil gegenüber EEPROM: viel mehr Lösch- / Schreibzyklen, aber auch sehr teuer, daher keine Option für große Datenmengen, aber sicherlich für einige Variablen).

Beachten Sie jedoch, dass Ihre Beschreibung wie ein typischer Anwendungsfall für Benutzereinstellungen klingt, die beim Neustart nicht verloren gehen sollen. Für diese ist das interne EEPROM der richtige Ort: Speichern Sie sie nur, wenn sie geändert wurden und Sie golden sind - der Benutzer wird sie nicht 100.000 Mal leicht ändern ...


Normalerweise verwende ich für diese Art von Dingen ein externes EEPROM. So etwas wie ein AT24C02 funktioniert für die meisten Projekte einwandfrei (es sind 256 Bytes). Ich bevorzuge nur externen Speicher, da er mehr R / W-Zyklen dauert und weil Sie ihn ändern können, wenn er nicht mehr funktioniert.
Stefa168

Der Widder wird nicht gelöscht. Die globalen Variablen werden gemäß dem 'c'-Standard auf Null gesetzt. Der nicht verwendete RAM behält seinen Wert während eines Zurücksetzens bei.
Jot

Ja, du hast recht. Ich dachte an einen Stromausfall, der zu einem Datenverlust im RAM führt (und eine Neuinitialisierung erforderlich macht).
Fuenfundachtzig

Was ist mit SD-Kartenleser zu verwenden. ist nicht so teuer und SD-Karte wird viel Zeit leben.
m3nda


2

Der EEPROM-Speicher funktioniert, wie bereits erwähnt, wenn nichtflüchtig ist. Sie haben sich jedoch nicht qualifiziert, ob es nicht flüchtig sein muss oder nicht. Wenn nicht, können Sie ein __attribute__ verwenden, um den Variablenraum zu definieren, der nicht initialisiert werden soll. Da der SRAM auf den ATmega's nicht durch Reset oder Power Cycle gelöscht wird. Der Compiler initialisiert sie standardmäßig. Wo dies pro Variable wie im folgenden Beispiel deaktiviert werden kann:

//non-initialized value
union configUnion{
  uint8_t    byte[6]; // match the below struct...
  struct {
    uint16_t value1;
    uint16_t value2;
    uint16_t chksum;
  } val ;
} config  __attribute__ ((section (".noinit")));

void setup() {
  uint16_t sum; 
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // prints title with ending line break
  Serial.print("Out of Reset -");
  sum = getchksum();
  printValues();

  if (sum != config.val.chksum) {
    config.val.chksum = sum;
    Serial.print("chksum is incorrect setting config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
  }

  config.val.value1++;
  config.val.value2++;
  Serial.print("setup new values - ");
  printValues();
  config.val.chksum = getchksum();
  Serial.print("updating chksum config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

int counter = 0;

void loop() {
  if (counter < 200) {
    Serial.print("after a while - ");
    printValues();
    Serial.println();
    while (true) {
      continue;
    }
  }
  counter++;
}

void printValues() {
  Serial.print(" value1 = 0x"); Serial.print(config.val.value1, HEX);
  Serial.print(", value2 = 0x"); Serial.print(config.val.value2, HEX);
  Serial.print(", sum = 0x"); Serial.print(getchksum(), HEX);
  Serial.print(", chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

uint16_t getchksum() {
  int sum = 0;
  for (int position = 0; position < (sizeof(config) - sizeof(config.val.chksum)); position++) {
    sum = sum + config.byte[position];
  }
  return sum;
}

Die Ausgabe des obigen Codes ist unten. Beachten Sie, dass der erste Ausgang das Ergebnis des Einschaltens der UNO bei gedrückter Reset-Taste war und nach dem Start des Monitorfensters wieder freigegeben wurde. Andernfalls wäre der Druck "Falsche Einstellung" übersehen worden, bevor das Monitorfenster gestartet werden kann.

Out of Reset - value1 = 0xBFED, value2 = 0xD2F9, sum = 0x377, chksum = 0xF457
chksum is incorrect setting config.val.chksum = 0x377
setup new values -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x377
updating chksum config.val.chksum = 0x379
after a while -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379

Out of Reset - value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379
setup new values -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x379
updating chksum config.val.chksum = 0x37B
after a while -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B

Out of Reset - value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B
setup new values -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37B
updating chksum config.val.chksum = 0x37D
after a while -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37D

Damit bleiben Ihre Variablen beim Zurücksetzen erhalten. Solange die Energie nicht verloren geht. Beachten Sie, dass Sie zu Beginn zufällige Daten erhalten.

Wenn Sie entweder EEPROM oder .noinit verwenden, würde ich empfehlen, dass Sie Ihren persistenten Variablenbereich während des Setups auf die Prüfsumme prüfen. Wenn dies nicht korrekt ist, können Sie eine Warnung initialisieren oder ausgeben.


1

Wenn Sie Ihr NVRAM wirklich häufig aktualisieren müssen, schauen Sie sich FRAM (Ferroelectric Random Access Memory) an, das eine Schreiblebensdauer von 10 ^ 13 Zyklen beansprucht (das sind ~ 318.000 Jahre, wenn Sie einmal pro Sekunde schreiben!). Sie sind 8 KB groß und bei 20 MHz (SPI) schneller als Flash oder EEPROM.

Adafruit (in den USA) verkauft sie auf einem Breakout-Board für etwa 6 US-Dollar in Onesies. Oder Sie können die nackten Chips bei den üblichen Lieferanten für etwa 1,30 US-Dollar kaufen, nicht jedoch DIP, sondern nur SOP8-Pakete.


0

Wenn Sie offen für eine Off-Chip-Lösung sind, ist es nicht allzu schwierig, einen SD-Kartenleser zu kaufen / zu bauen.


1
Bitte versuchen Sie, eine gründlichere Antwort zu geben: Stellen Sie Links zu solchen SD-Kartenlesern bereit, veröffentlichen Sie einen Beispielcode zum Lesen / Schreiben von Variablen und erwähnen Sie, wie besser es als EEPROM ist.
jfpoilpret

Guter Vorschlag. SD verwendet eine reguläre SPI-Schnittstelle. Alles, was Sie brauchen, ist eine Konvertierung auf Logikebene. Außerdem verdrahten Sie sie direkt mit einem Arduino. Löten Sie einfach einige Drähte an einen Micro-SD-zu-SD-Adapter.
Gerben

+ jfpoilpret IMHO SD-Kartenleser sind allgegenwärtig und sollten keine Beispiele oder Zitate benötigen. Der Code ist abhängig von der Marke des Lesers, daher macht es keinen Sinn, beliebigen Code bereitzustellen. Ich habe erwähnt, dass es besser ist als EEPROM, es ist nicht zu schwierig zu kaufen oder zu bauen.
Linhartr22
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.