kuahmelcher:
Außerdem habe ich durch die Umstellung von UTF8 auf Binärdaten festgestellt, dass das Grafikformat "BMP" nichts anderes ist als ein kurzer Dateiheader gefolgt von RGB-Daten. Es spricht also nun tatsächlich nichts mehr dagegen den PHP-Teil einzusparen und direkt von einer BMP-Datei zu belichten.
Verstehe. Ja, das unkomprimierte BMP-Datenformat für 24-Bit RGB-Bilder besteht im Prinzip aus einem Header und danach den RGB-Daten zeilenweise.
kuahmelcher:
Das direkte Abspielen einer BMP-Datei direkt von einer SD-Karte würde für das RGB-Drucker-Projekt einen Quantensprung in Punkto Komfort bedeuten!!!
Das könnte man ggf. in einen AVR-Sketch einbauen: Header überlesen und dann die RGB-Daten auslesen. Das einzige Handycap ist wohl, dass die RGB-Zeilen immer an einer durch 4 teilbaren Bytegrenze ausgerichtet werden. D.h. bei 59 Bytes*3=177 Bytes müßten tatsächlich immer 180 Bytes (durch 4 teilbar) eingelesen werden, wovon 177 Bytes zum Setzen der LEDs verwendet werden.
kuahmelcher:
// ************************
// BINÄRDATEN S C H R E I B E N :
// ************************
// ist eigentlich nicht notwendig, kann aber evtl. DOCH notwendig
// werden, weil nämlich das Grafikformat BMP von der linken
// unteren Ecke ZEILENWEISE aufgebaut ist. Das muss ich
// wahrscheinlich noch aufbereiten, weil ich ja SPALTENWEISE abspiele
Normalerweise ist es nicht notwendig, die Datei gesondert aufzubereiten, wenn Du das Bild in einem Grafikprogramm entsprechend abspeicherst: Du kannst ein im falschen Zeilen/Spalten-Format vorliegendes Bild durch Drehen um 90 oder 270 Grad immer so hinbekommen, dass die Spalten/Zeilen passen. Unter Windows ab WIN7 kann das mit dem Drehen sogar die "Bildanzeige" erledigen, so dass gar kein richtiges Grafikprogramm dafür starten braucht..
kuahmelcher:
Was ich jetzt noch NICHT gemacht habe ist deinen Vorschlag bezüglich mehrerer Puffer anzugehen. Wenn du da ein paar Denkanstöße hättest wäre ich dankbar.
Das mit dem Einlesen der Puffer muß in der loop gemacht werden. Deklaration bei mir:
#define BUF_SIZE 177 // 59 x 3 Bytes RGB
byte buffers[8][BUF_SIZE];
volatile byte bufferstatus=0b00000000; // eight bits for eight buffers
File file;
Ich habe 8 Puffer a 177 Bytes und eine Statusvariable "bufferstatus", die ich als "volatile" deklariert habe.
Jedes einzelne Bit in bufferstatus steht für den Zustand eines 177-Byte Puffers ("0=Bytes gelesen", "1=LEDs gesetzt").
Das Lesen der Puffer erfolgt in der loop (und ist etwas holperig/unregelmäßig).
Das Setzen der LEDs in einem Timer-Interrupt (exakt alle 2 Millisekunden).
Die Puffer werden in der loop eingelesen, und jedes Bit in "bufferstatus" steht für den Status eines Puffers, wobei ich es so handhabe: Sobald in der loop ein Puffer eingelesen wird, wird das entsprechende Statusbit in bufferstatus auf "0" gesetzt. D.h. wenn alle acht Puffer eingelesen sind, ist bufferstatus=0b00000000;
Das Abspielen der Pufferinhalte erfolgt in einer Timer-Interruptroutine, daher ist bufferstatus auch "volatile" deklariert: Der Timer-Interrupt wird programmiert, dass er alle 2 Millisekunden läuft. Immer wenn ein Timerinterrupt auftritt, wird einer der Puffer verwendet, um die 59 LEDs zu setzen, und danach wird das zu diesem Puffer gehörende Bit in bufferstatus auf "1" gesetzt.
Die loop kann nun ihrerseits erkennen, welche Bits nacheinander alle auf "1" wechseln und macht nun während des Abspielens nichts anderes als: Wenn ein Bit in der Variablen bufferstatus auf "1" wechselt, lade den Puffer neu und lösche das Bit des dazugehörenden Puffers wieder auf "0". So lange, bis die Datei zuende abgespielt ist.
Nachtrag:
Ich habe mal etwas mit dem Einlesen von 24-Bit BMP-Bilddateien experimentiert.
Also das direkte einlesen unkomprimierter 24-Bit RGB BMPs in Arduino funktioniert.
Wie von Dir schon geschrieben, entsprechen die ersten gelesenen Bytes einer BMP-Datei "links unten" im Bild, die letzten Bytes in der Datei "rechts oben". D.h. Du müßtest Deine BMP-Datei einmal um 90 Grad nach links drehen, damit sie in der gewünschten Reihenfolge abgespielt werden kann. Also statt z.B. Bildgröße 1000 59 (BreiteHöhe) das Bild einmal um 90 Grad nach links drehen auf 591000 (BreiteHöhe), dann passt es.
Als Anhang ein experimenteller Code zum Einlesen von 59 Pixel breiten 24-Bit RGB BMP-Dateien.
Das ist nur Proof-of-Concept Code, es sind noch keine Timer-Interrupts drin, sondern nur ein Test zum Auslesen.
Da BMP-Bildzeilen immer auf vollen 4-Byte Grenzen gespeichert werden, wird ein 59 Pixel breites RGB-Bild (177 RGB-Bytes) immer in 180 Bytes breiten Zeilen gespeichert (180 ist die nächste durch 4 teilbare Zahl).
Als Dateipuffer habe ich ein "union" angelegt, das gleichermaßen zum Einlesen
- des Datei-Headers
- des BMP-Headers
- der Bildzeilen
dienen kann. Von den acht deklarierten Puffern für Bildzeilen wird in diesem Programm nur der erste genutzt.
So wie ich den Code drangehängt habe, wird beim Auslesen nur ein Geschwindigkeitstest gemacht und Du kannst die maximale Leserate ermitteln.
Wenn Du die Kommentarstriche vor
// if (bildbuffers.buffers[0][start+2]==255) digitalWrite(13,true); else digitalWrite(13,false);
entfernst, kannst Du sehen, wie die Geschwindigkeit einbricht, wenn mit den gelesenen Daten etwas gemacht wird, z.B. per digitalWrite eine LED ein- und ausschalten. Die Leserate bricht mit digitalWrite sofort weit unter 90 kB/s ein. D.h. wenn Du LEDs mit 90 kB/s setzen möchtest, müßtest Du dafür eine Möglichkeit (Fast SPI?) haben, die deutlich(!) schneller ist als digitalWrite.
Wenn Du die Kommentarstriche vor
// #define DEBUG
entfernst, werden alle Bytes mit ausgelesen und über Serial angezeigt.
(Dann wird's trotz Baudrate von 11520 richtig langsam, weil die Datenrate der seriellen Schnittstelle bremst.)
Wie setzt Du denn die LEDs auf ihre RGB-Werte, wie schnell ist das?
Mit welchem Datendurchsatz kannst Du die LEDs einstellen, wenn nichts aus Datei gelesen werden muß?
Du müßtest auf jeden Fall die 59 LEDs in weniger als einer Millisekunde auf ihre RGB-Werte setzen können, sonst reicht es von der Geschwindigkeit her nicht.
BMPread.ino (5.46 KB)