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!");
}
}
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.
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.
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();
}
}
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
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....