Zwischenpufferung von Daten und Log-Informationen im RTC slow memory des ESP32

Wir hatten schon seit Urzeiten das Thema Zwischenspeichung von Messungen auf der Agenda. Daten sollen nicht sofort wegschickt werden, sondern erst mal auf dem node gesammelt und dann als bulk zum Server geschickt werden. Das

  • spart Energie / Batterie, da der stromhunrige Sendeprozess seltener nötig ist und
  • Reduziert die Belastung mit GSM / WLAN-Funk der Bienen , von dem wir noch nicht genau wissen wie er die Bienen beeinflusst.
  • spart Kosten z.B. bei der Übertragung per GSM / LTE, wenn mit Mindestblockgrößen abgerechnet wird (die wir mit einer einzelnen Übertragung nie erreichen)

Drüben bei Zwischenpufferung von Daten und Log-Informationen auf SD-Karte ist die Zwischenspeicherung auf SD-Karte Thema, hier schauen wir, ob es vielleicht auch im Speicher des ESP32 geht.

Dafür sollen wir dann den Deep Sleep opfern, es soll also in solchen Szenarien nur mit “always on” gehen?

Ist auf dem BOB-HAT denn kein Slot für eine SD-Karte vorgesehen?

Nein, da wir gerade damit Strom sparen wollen muss das Szenario auch zusammen mit dem deep sleep funktionieren.

Beim deep sleep verliert der ESP32 leider immer noch alle nicht besonders behandelten Variableninhalte, was mir vom 8266 ja kennen, hatte da ursprünglich auf etwas Innovation gehofft. Der gute alte Arduino konnte sich Dinge über den deep sleep Zyklus hinaus merken. Der “RTC-Speicher” des 32 hat aber 4x so viel Speicher wie der alte Uno gesamt, wäre das eine Option?

SD ist alleine mechanisch anfällig und wie ist das mit den Schreibzyklen, heute noch ein Problem? Weiter braucht die gerade wieder viel Strom!

Schwumms

Gut, das hätte mich sonst auch gewundert.

Hier sehe ich keinen Grund, uns über irgendetwas neu zu wundern, was wir schon immer wissen. Dein Erklärungsversuch hinsichtlich “fehlender Innovation” greift hier zu kurz bzgl. des ESP32. Es geht hier vor allem um MicroPython, das noch keine komfortable API dafür bereitstellt. Grundsätzlich funktionieren sollte das alles.


Ausblick

Wir könnten jedoch schauen, ob wir die 8 kbyte im RTC memory erschlossen bekommen. Da das u.a. für den Datenaustausch zwischen dem ESP32-Core und der ULP-Einheit vorgesehen ist und vielleicht auch im Deep Sleep seinen Inhalt nicht verliert.

Macht das für alle Interessierten und die die sich auskennen Sinn?

A post was merged into an existing topic: Externer Speicher zur Zwischenspeicherung von Daten

Investigating RTC slow memory usage

Introduction

On https://wolfpaulus.com/micro-python-esp32/ tells us that the ESP32 has…

ESP32 power reduction for battery powered - MicroPython Forum (Archive) also tells us that

State of the onion

ESP-IDF

The relevant documentation section of the ESP-IDF is Loading Data Into RTC Memory.

User space / C++

:warning: We might want to explicitly use RTC_SLOW_ATTR here – just for better safe than sorry.

ULP / Assembler

An example how to sample the ADC from the ULP and store the outcome in a last_result slot into RTC slow memory: measure: in adc.S

Seitenblicke

Obviously, others are doing this very thing from the C++ level successfully.

No avail to MPY?

However, we haven’t been able to get hold of any interface description or code example about how to actually use the RTC slow memory from MicroPython.

Die einzigen beiden Referenzen auf RTC_DATA_ATTR im Pycom Universum finden sich bei:

State of the onion with RTC slow memory on ESP32 from Pycom MicroPython

2016

2017

2018

2019

Bottom line

1 Like

Trüffel-schnüffel … das hier riecht interessant:

Scheint ne machine-imlementation in C von nem Individualisten zu sein, aus der Doku:

rtc.write(pos, value)

Write integer (32-bit) value to the position pos in RTC memory.
Return True on success, False if failed.

rtc.read(pos)

Read integer (32-bit) from the position pos in RTC memory.
Returns None if no value has not been written to the RTC integer memory yet or the RTC memory was corrupted (bad CRC), otherwise returns the integer written to the position or 0 (default value).

rtc.write_string(text)

Write the string text to RTC memory.
Return True on success, False if failed.

rtc.read_string()

Read the string from RTC memory.
Returns None if no string has been written to the RTC string memory yet or the RTC memory was corrupted (bad CRC), otherwise returns the string written .

1 Like

Das hier von manningt (Tom Manning) · GitHub im micropython-repo ebenfalls:

I added the RTC memory implementation to machine_rtc.c, as per the attached file.
The RTC memory is preserved through deepsleep. Not sure if this could be added to the pull.
machine_rtc.c.zip

aus:

1 Like

Das LTE-Modem hat nicht-volatilen (NV)-RAM

Möglw. noch viel besser, weil is schon fertig! Der ist für Zertifikate und Private-Keys gedacht, hat jeweils nen Speicherbereich mit Pages dafür. Ich konnt noch keine Aussagen zur Größe finden.

Ist in der AT-Kommando-Referenz vom Sequans-Modem ab Seite 311 (Kapitel 14) beschrieben.

Hab erstmal nur reingeguckt, noch nix geschrieben:

    # LTE: get AT+SQNSNVR="certificate"
    print("[LTE   ] getting AT+SQNSNVR=\"certificate\" ... (LED light green)")
    pycom.rgbled(0x000500)
    try:
      SQNSNVR = lte.send_at_cmd("AT+SQNSNVR=\"certificate\"")
      print("[LTE   ]   ... done: " + SQNSNVR)
    except:
      CGPIAF_at="-999.0"
      print("[LTE   ]   ... failed: " + SQNSNVR)

    # LTE: get AT+SQNSNVR="privatekey"
    print("[LTE   ] getting AT+SQNSNVR=\"privatekey\" ... (LED light green)")
    pycom.rgbled(0x000500)
    try:
      SQNSNVR = lte.send_at_cmd("AT+SQNSNVR=\"privatekey\"")
      print("[LTE   ]   ... done: " + SQNSNVR)
    except:
      CGPIAF_at="-999.0"
      print("[LTE   ]   ... failed: " + SQNSNVR)

Output:

[LTE   ] getting AT+SQNSNVR="certificate" ... (LED light green)
[LTE   ]   ... done: 
+SQNSNVR: "certificate",0,"/CN=root/OU=Service Platform Development department/O=SoftBank Corp./L=Minato-ku/C=JP","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","/CN=root/OU=Service Platform Development department/O=SoftBank Corp./L=Minato-ku/C=JP","18/02/26 01:33:37","19/02/26 01:33:37","sha256ECDSA","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","sha1","38db2b4bde4278b9f460cd175ec4c04f88fbc9b8"
+SQNSNVR: "certificate",0,"/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5","000000000000000000000000000000000000000000000000","/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5","06/11/08 00:00:00","36/07/16 23:59:59","sha1RSA","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","sha1","fdf579b4c78c21872f52909c4282a1a0f4253a95"
+SQNSNVR: "certificate",0,"/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority","00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority","96/01/29 00:00:00","28/08/01 23:59:59","md2RSA","00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","sha1","2142321057ede4c9d432fe974835194c2c52d652"

ERROR

[LTE   ] getting AT+SQNSNVR="privatekey" ... (LED light green)
[LTE   ]   ... done: 
OK

Macht jetz nicht den Eindruck, als ob so nen “Null-Zertifikat” wichtig wär, oder was denken dieGelehrten? Die private-keys sehen jedenfalls sehr leer aus.

Ah, im ESP32 Port von Boris Lovosevic (@loboris) [1] – exzellent! Vielen Dank für dieses Fundstück.


  1. Siehe auch MicroPython quo vadis. ↩︎

Auch wenn das LTE-Modem NV-RAM hat sollten wir – falls es für uns taugt – eher das des ESP nehmen, dann funktioniert die Zwischenspeicherung auch mit WiPys, LoPys usw.

2 Likes

Release Notes:

Added Feautures:

  • Added RTC memory support

New Features:
[…]

  • Added support for RTC memory operations Read/Write
3 Likes

ich bin mir nich so sicher… aber ich glaube eher das ist kein eeprom sondern ein flash. bei beidem sind die schreibzyklen beschraenkt. ich faende ja einen kleinen supercap backed ram oder andre nonvolatile speicher mit ohne viel verschleiss besser fuer daten die man >1x am tag schreibt.

This got me curious and we found the reason for not finding it at the first hand. While the documentation matching the stable firmware [1] version does not tell us anything about the RTC memory, the documentation for the development version [2] does.

Now, let’s hope it’s really the RTC slow memory, which will hold its contents while the device is in deep sleep. [3]


  1. Pycom Firmware & API Reference » RTC module » stable firmware ↩︎

  2. Pycom Firmware & API Reference » RTC module » development firmware ↩︎

  3. ESP32 – Internal Memory

    • 8 KBytes SRAM in RTC, which is called RTC SLOW Memory and can be accessed by the co-processor during the Deep-sleep mode.
    • 8 KBytes SRAM in RTC, which is called RTC FAST Memory and can be used for data storage; it is accessed by the main CPU during RTC Boot from the Deep-sleep mode.

    Overview of ESP32 features. What do they practically mean? - Tutorials ↩︎

1 Like

Proof

Data stored in RTC slow memory is preserved during deep sleep.

# Before deep sleep
import machine
machine.RTC().memory('Hello World')

# Invoke deep sleep
machine.deepsleep()

# After deep sleep
import machine
machine.RTC().memory()
b'Hello World'

How large is it?

A: The software-addressable RTC slow memory is 2048 bytes in size.

>>> machine.RTC().memory('a' * 2049)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: buffer too long

Notes

The ULP [1] also has access to this memory and can use it actively while the main MCU is in deep sleep mode.


  1. PRU und ULP und deren Programmierung ↩︎

2 Likes

Super, dass es funktioniert und unterstützt wird! Schade, dass es nur 2 kB sind!

Mal ein paar Einschätzungen von unseren beelogger-Kollegen:
https://beelogger.de/?page_id=199005

  • sie verwenden standardmäßig das 4 kB des EEPROM der RTC, die sie auch verbaut haben
  • die 1 kB des Atmel 328p sind ihnen auch zu wenig
  • sie empfehlen ein externes EEPROM oder F-RAM

Bei den beelogger-Datensätzen schreiben sie

erlaubt ein 4kByte EE-Prom mit 5 Minuten Intervall die Speicherung der Daten über 4 Stunden

und

Bei einer täglich einmaligen Datenübertragung mit einem Intervall von 5 Minuten wird ein EE-Prom mit 32kByte (256kbit) benötigt;

Bei meinen open hive-Daten komme ich auf ca. 7 kB Daten pro Tag wenn ich 20minütig messe. 2 kB sind hier ca. 20 Datensätze, allerdings CSV ohne jegliche Metainformation wie Variablenname o.ä.:

2016/08/28 06:21:00,  -0.002, 21.3, 72.5, 21.5, 67.9, 21.0, 21.2, 21.4, 21.4, 21.5, 4.23
2016/08/28 06:41:00,  -0.000, 21.0, 71.6, 21.2, 67.5, 20.8, 21.3, 21.4, 21.4, 21.6, 4.23
2016/08/28 07:01:00,   0.003, 21.0, 70.6, 21.3, 66.5, 21.1, 21.4, 21.5, 21.6, 21.6, 4.23

Wie viele Datensätze können wir bei einem Standard-BOB-System (Waage, 1x BME, 5x DS18B20) speichern ohne großartige andere Daten wie RSSI oder System-Parameter? Vielleicht 10 bis 12 ohne viel Optimierungsarbeit?

Hmmm, ganz subjektiv überlege ich gerade, ob sich der Implementierungs-Aufwand für RTC-Memory lohnt?

Eine xz-Kompression könnte das um den Faktor 5 schrumpfen lassen.

Das micropython boardmittel uzlib kann wohl nur decompress, in diesem thread hat jemand in C nen pendant gehackt:
https://forum.micropython.org/viewtopic.php?t=5893

1 Like

Wir könnten wohl langsam mal ne inoffizielle Liste von Dingen starten, welche C-Extensions wir beizeiten gerne mit im Programm hätten. Bliebe die Frage, wer sie uns reinhacken kann ;].