Arduino Uno Wärmebildkamera (Fehler: Zu wenig Arbeitsspeicher)

Hey, ich muss für meine Techniker fortbildung eine Wärmebildkamera mit dem Arduino Uno, MLX 90640 Sensor und ein display bauen. Ich habe ehrlich gesagt nicht viel Ahnung von der Programmierung eines Arduinos. Ich habe mein Sketch ( von ChatGpt ) hochgeladen, dann hat er zu mir gesagt, dass ich zu wenig arbeitsspeicher habe. Woran kann es liegen?

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_MLX90640.h>

// Pins für das Display
#define TFT_CS     10
#define TFT_RST    8
#define TFT_DC     9

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// MLX90640 Sensor
Adafruit_MLX90640 mlx;
float frame[32 * 24]; // Temperaturwerte des Sensors (32x24 Auflösung)

void setup() {
  // Serieller Monitor
  Serial.begin(9600);

  // Display initialisieren
  tft.initR(INITR_BLACKTAB);  // Display-Typ
  tft.setRotation(1);        // Orientierung des Displays
  tft.fillScreen(ST77XX_BLACK);

  // MLX90640 initialisieren
  if (!mlx.begin(0x33, &Wire)) { // Standard I2C-Adresse: 0x33
    Serial.println("MLX90640 nicht gefunden! Überprüfe die Verkabelung.");
    while (1);
  }
  mlx.setMode(MLX90640_INTERLEAVED); // Interleaved-Modus
  mlx.setResolution(MLX90640_ADC_18BIT); // Höchste Genauigkeit
  mlx.setRefreshRate(MLX90640_8_HZ); // 8 Hz Aktualisierungsrate

  Serial.println("Setup abgeschlossen!");
}

void loop() {
  // Sensor-Daten auslesen
  if (mlx.getFrame(frame)) {
    // Daten auf dem Display darstellen
    tft.fillScreen(ST77XX_BLACK); // Display leeren

    for (int y = 0; y < 24; y++) {     // Sensor hat 24 Zeilen
      for (int x = 0; x < 32; x++) {   // Sensor hat 32 Spalten
        float temp = frame[y * 32 + x]; // Temperaturwert an Position (x, y)
        
        // Farbskala berechnen (einfache Visualisierung)
        uint16_t color = tft.color565(
          min(255, max(0, (temp - 20) * 12)), // Rot: abhängig von Temperatur
          0,                                 // Grün: aus (für Blautöne)
          255 - min(255, max(0, (temp - 20) * 12)) // Blau: invers zu Rot
        );
        
        // Pixel zeichnen
        tft.drawPixel(x, y, color);
      }
    }
    delay(125); // Aktualisierung alle 125 ms (entspricht 8 Hz)
  } else {
    Serial.println("Fehler beim Auslesen der Daten!");
  }
}

Na, eine float Variable benötigt 4Byte. Dein Float Array (frame) benötigt drei Kilobyte Ram. Der Uno hat aber nur zwei.

Lies da mal.

Gruß

Pucki

ps. : Ich glaube die KI macht die Leute dümmer. :wink:

1 Like

Ich danke dir, ich habe mir vorsichtshalber jetzt den Arduino Mega geholt.

Ich wäre eher auf ein ESP32 gegangen.

Allein schon wenn ich an den ca. 3 fachen Preis ein Mega denke.

Gruß

Pucki

Hätte, hätte, Fahradkette.
Da hängt u.a. noch ein wenig 5V Peripherie dran.

Na und.

Für sowas gibt es level shifter.

Dafür hab ich mehr als genug Speicher, und falls ich will Wlan.
Was bedeutet das ich in deinen Fall es so programmieren würde, das ich die Daten notfalls in ein Wölkchen o.ä. schicken kann.

Gruß

Pucki

Denkt ihr mit dem Elegoo Mega R3 funktioniert alles? Ich habe mir dazu dann noch ein größeres Display gekauft, ein Li-Ionen Akku damit ich es auch mobil benutzen kann, ein Mini step up Spannungswandler, und ein batterieladungsmodul.

Ich versuche mich dann wieder erst an die Programmierung und hoffe es funktioniert. Ich halte euch auf dem laufenden.

Wie lange denn?

Je nach dem. 4-6 Stunden

Eine pauschale Aussage ist nicht möglich.

Das muss man Ausrechnen. Verbrauch der Geräte, Leistung der Akkus und vor allen Dingen ist das auch eine Frage der Planung und der Programmierung.

Wenn man das Teil schlafen legt, verbraucht es kaum was. Ob man die Kamera schlaffen legen kann weiss ich nicht.

Aber 4-6 Std. permanente Aufzeichnung und Analyse würde nicht einmal ein modernes Handy durchhalten.

Gruß

Pucki

danke dir erstmal Pucki.

Heute kam mein Elegoo Mega an. Ich habe den Sensor mit dem Elegoo verbunden und wollte den über simpletest testen. Der vorgegebene Code verbraucht anscheinend wieder zu Viel Arbeitsspeicher. Ich lese immer man soll sich eine andere Bibliothek herunterladen aber ich weiß nicht genau welche.

das ist der vorgegebene Code:

#include <Adafruit_MLX90640.h>

Adafruit_MLX90640 mlx;
float frame[32*24]; // buffer for full frame of temperatures

// uncomment *one* of the below
//#define PRINT_TEMPERATURES
#define PRINT_ASCIIART

void setup() {
  while (!Serial) delay(10);
  Serial.begin(115200);
  delay(100);

  Serial.println("Adafruit MLX90640 Simple Test");
  if (! mlx.begin(MLX90640_I2CADDR_DEFAULT, &Wire)) {
    Serial.println("MLX90640 not found!");
    while (1) delay(10);
  }
  Serial.println("Found Adafruit MLX90640");

  Serial.print("Serial number: ");
  Serial.print(mlx.serialNumber[0], HEX);
  Serial.print(mlx.serialNumber[1], HEX);
  Serial.println(mlx.serialNumber[2], HEX);

  //mlx.setMode(MLX90640_INTERLEAVED);
  mlx.setMode(MLX90640_CHESS);
  Serial.print("Current mode: ");
  if (mlx.getMode() == MLX90640_CHESS) {
    Serial.println("Chess");
  } else {
    Serial.println("Interleave");
  }

  mlx.setResolution(MLX90640_ADC_18BIT);
  Serial.print("Current resolution: ");
  mlx90640_resolution_t res = mlx.getResolution();
  switch (res) {
    case MLX90640_ADC_16BIT: Serial.println("16 bit"); break;
    case MLX90640_ADC_17BIT: Serial.println("17 bit"); break;
    case MLX90640_ADC_18BIT: Serial.println("18 bit"); break;
    case MLX90640_ADC_19BIT: Serial.println("19 bit"); break;
  }

  mlx.setRefreshRate(MLX90640_2_HZ);
  Serial.print("Current frame rate: ");
  mlx90640_refreshrate_t rate = mlx.getRefreshRate();
  switch (rate) {
    case MLX90640_0_5_HZ: Serial.println("0.5 Hz"); break;
    case MLX90640_1_HZ: Serial.println("1 Hz"); break;
    case MLX90640_2_HZ: Serial.println("2 Hz"); break;
    case MLX90640_4_HZ: Serial.println("4 Hz"); break;
    case MLX90640_8_HZ: Serial.println("8 Hz"); break;
    case MLX90640_16_HZ: Serial.println("16 Hz"); break;
    case MLX90640_32_HZ: Serial.println("32 Hz"); break;
    case MLX90640_64_HZ: Serial.println("64 Hz"); break;
  }
}

void loop() {
  delay(500);
  if (mlx.getFrame(frame) != 0) {
    Serial.println("Failed");
    return;
  }
  Serial.println("===================================");
  Serial.print("Ambient temperature = ");
  Serial.print(mlx.getTa(false)); // false = no new frame capture
  Serial.println(" degC");
  Serial.println();
  Serial.println();
  for (uint8_t h=0; h<24; h++) {
    for (uint8_t w=0; w<32; w++) {
      float t = frame[h*32 + w];
#ifdef PRINT_TEMPERATURES
      Serial.print(t, 1);
      Serial.print(", ");
#endif
#ifdef PRINT_ASCIIART
      char c = '&';
      if (t < 20) c = ' ';
      else if (t < 23) c = '.';
      else if (t < 25) c = '-';
      else if (t < 27) c = '*';
      else if (t < 29) c = '+';
      else if (t < 31) c = 'x';
      else if (t < 33) c = '%';
      else if (t < 35) c = '#';
      else if (t < 37) c = 'X';
      Serial.print(c);
#endif
    }
    Serial.println();
  }
}

Kennst Du diese Seite? Da ist ein Beispiel für ESP32 dabei.

Gruß Tommy

Gib bei google "mlx90640 arduino library" ein.

Da bekommst du einige angeboten.

Davon abgesehen, Adafruits ist nicht gerade für sparsame Programmierung bekannt.
Habe ich bei meinen Display bemerkt.

Gruß

Pucki

Was genau zeigt Dir die IDE denn an, wenn der Code kompiliert ist? Zumindest der statische RAM und Flashspeicherverbrauch wird angezeigt....

data section exceeds available space in boardDer Sketch verwendet 20566 Bytes (8%) des Programmspeicherplatzes. Das Maximum sind 253952 Bytes.

Globale Variablen verwenden 11781 Bytes (143%) des dynamischen Speichers, -3589 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.
Not enough memory; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing your footprint.

//-> Fürn MEGA

Nachtrag: Bei Anwendung des F()-Makros genau 300 bytes weniger

Ok .. krass … naja frame 3Kb + float t = frame[h*32 + w]; das frisst wohl alles weg….

Genau.
Ich hatte gestern überlegt, ob man das auf 1 NK Stelle abkürzen könnte und einfach einen int aus dem float macht und das Ganze mit 10 hochrechnet und zur Ausgabe wieder mit 10 runter, aber das war mir zu dick um das mal kurz zu bauen.
Würde aber mindestens 6 byte pro Element sparen....

Auch mit uint könnte es noch knapp auf dem UNO werden.
man müsste wissen, in welchem Bereich sich die Pixelwerte bewegen. Evtl. kommt man mit 256 Werten (Byte) hin, mit verringerter Auflösung.

Was von mir in #14 verlinkte Wiki geht auch nur auf Beispiele mit Raspi, ESP32 und STM32 ein.

Gruß Tommy

Edit: Das Datenblatt sagt:

  • Target temperature: -40℃~300℃
  • Resolution: ±1℃

Da ist float übertrieben und wenn man den Anwendungsfall in den Grenzen z.B. von 0 bis 250 °C lässt, kommt man mit 1 Byte pro Pixel hin. Wenn geringe - Werte, dann mit konstantem Offset arbeiten.
Da muss aber @galle2212 mal konkret was zum Einsatzbereich sagen oder einen ESP32 benutzen.

Wenn ich mehr Zeit hätte...
Vielleicht ginge ja auch das gar nicht in einem riesen Frame zu speichern, sondern "onTheFly" die Darstellung (sind ja nur Pixel) auf den Display zu schreiben....