Hallo zusammen,
ich habe hier einen STM32 und ein SPI Display (ILI9341).
Ich betreibe es mit folgender Lib:
https://github.com/afiskon/stm32-ili9341
Darauf möchte ich gern ein oder zwei Grafiken anzeigen (Skalen für
Messwerte). Damit das ganze halbwegs schön aussieht, würde ich die
Skalen in GIMP designen und dann in ein Array umwandeln wollen, so wie
das beiligende Testbild. Das Anzeigen des Testbilds funktioniert
einwandfrei (siehe Anhang).
Mein Problem:
Ich finde keinen Converter, der dass passende Format ausgibt.
Kenn ihr einen? Mir ist klar das das Bild welches ich wandeln will, die
passende Dimension haben muss (320x240px). Die Online Converter wie:
https://notisrac.github.io/FileToCArray/
bieten zwar eine Reihe von Einstellmöglichkeiten, aber leider nicht die
Option ein Array zu erstellen.
Viele Grüße
Albi
erklehr behr schrieb:> Albi schrieb:>> testimg.h>> Code und Daten tut man nicht in eine *.h Datei hinein tun,> nein das ist böse, nein das tut man nicht!
Allgemein heißt das: keine Definitionen in Header-Dateien, sondern nur
Deklarationen.
erklehr behr schrieb:> Code [und Daten] tut man nicht in eine *.h Datei hinein tun,> nein das ist böse, nein das tut man nicht!
Doch, tut man. Wenn's notwendig ist.
Oder wo würdest Du eine static inline Funktion hintun?
Gunnar F. schrieb:> GIMP kann direkt in ein c-array exportieren.
Das wäre ja super, ich habe GIMP 2.10.32. Da finde ich keine Option den
Export oder das Speichern in c auszuwählen, nur .xcf. Gibt es das in den
neuen Versionen nicht mehr?
Wilhelm M. schrieb:> Nimm `xxd` (`xxd -i`) oder nimm einen Compiler, der schon das C23> feature `#embed` unterstützt (clang mit P1967).
Ich habe grade man danach gegoogelt, aber ich verstehe es leider
trotzdem noch nicht. Ist "xxd" ein Programm? Und nennt man C23 das
Format dieser Bilddatei? Ähnlich wie png, jpg und co bei Bildern?
So lang das Bild bei, ich hab es jetzt erstmal genommen.
Wenn ich das .h in .c ändere und ein neues .h file erstelle, meckert der
Compiler. Ich hänge die beiden Dateien mal mit an. Was mache ich falsch?
Also laut Compiler gibt es eine Mehrfach Definition, aber wie macht man
es richtig?
ili9341/testimg.h:5: multiple definition of `test_img_240x240';
./Core/Src/main.o:...../ili9341/testimg.h:5: first defined here
Danke für eure Antworten!
Albi
Albi schrieb:> ili9341/testimg.h:5: multiple definition of `test_img_240x240';> ./Core/Src/main.o:...../ili9341/testimg.h:5: first defined here
Im header fehlt ein 'extern'.
Albi schrieb:> Also laut Compiler gibt es eine Mehrfach Definition, aber wie macht man> es richtig?
Genau.
Das hatte ich oben geschrieben: keine Definitionen in Header-Dateien.
Du musst die Variablen-Definitionsanweisung in eine Deklaration ändern.
Bei Variablen brauchst Du dazu dann `extern`. Andernfalls verletzt Du
die ODR.
Albi schrieb:> Wilhelm M. schrieb:>> Nimm `xxd` (`xxd -i`) oder nimm einen Compiler, der schon das C23>> feature `#embed` unterstützt (clang mit P1967).>> Ich habe grade man danach gegoogelt, aber ich verstehe es leider> trotzdem noch nicht. Ist "xxd" ein Programm? Und nennt man C23 das> Format dieser Bilddatei?
Nein, mit C23 ist hier der neue C-Standard C23 gemeint.
wenn der Zeiger über die Skalenelemnte schreibt, dann bekommt man beim
Pixelbasierten Löschen und Zeichnen flackernde Anzeigen. Das machen
Objetbasierte Grafiklibs besser, siehe z.B. lvgl. Es hängt dann vom
verwendeten STM32 ab, das braucht schon etwas mehr RAM und Flash.
Albi schrieb:> Damit das ganze halbwegs schön aussieht, würde ich die> Skalen in GIMP designen und dann in ein Array umwandeln wollen,...
Also das Thema "Grafiken auf dem µC" ist schon fast uralt und dazu hat
es hier in diesem Forum auch schon ellenlange Beiträge gegeben. Auch von
mir.
Naja, zeichnen kannst du sowas mit einem recht beliebigen Programm,
solange du ein übliches Dateiformat damit erzeugen kannst. Die Frage ist
eher, wie du so eine Grafik im µC halten willst. Als einfache Bitmap,
also im Prinzip BMP, wird sowas recht unfänglich. Also wäre es durchaus
angesagt, so eine Grafik komprimiert vorzuhalten, vorausgesetzt, die
Entkomprimierung ist einfach zu erledigen. Also nix mit JPG oder PNG,
die sind für den µC nicht die erste Wahl.
Siehe mal da:
Beitrag "Bildformat für Farb-LCD"
W.S.
J. S. schrieb:> Im header fehlt ein 'extern'.Wilhelm M. schrieb:> Du musst die Variablen-Definitionsanweisung in eine Deklaration ändern.> Bei Variablen brauchst Du dazu dann `extern`. Andernfalls verletzt Du> die ODR.
Das war es. Danke!
Wilhelm M. schrieb:> Nein, mit C23 ist hier der neue C-Standard C23 gemeint.
OK, aber kann ich das überhaupt einstellen? Ich nutze die Cube IDE von
STM. Ist da nicht immer "der aktuellste Stand" drin? So oft wie die IDE
ein Update machen will gehe ich davon mal aus :D.
J. S. schrieb:> wenn der Zeiger über die Skalenelemnte schreibt, dann bekommt man beim> Pixelbasierten Löschen und Zeichnen flackernde Anzeigen.
Das wäre unschön. Dann muss ich den Zeiger einkürzen, sodass er nur
unter der Zahl lang wischt....oder:
J. S. schrieb:> Objetbasierte Grafiklibs besser, siehe z.B. lvgl.
darauf wechseln:
Ich verwende einen F303CC, meint ihr der schafft die lvgl?
https://lvgl.io/demos Das Thermostat UI wäre sowas in der Richtung was
ich anstrebe, dass sieht schon nett aus. Der Vorteil von lvgl wäre
natürlich auch der Font und Image Converter, passend zur lib.
Ich hatte mich eigentlich schon mit Touch GFX versucht, aber das war mir
zu aufgebläht. Jede Variable die ich anzeigen lassen wollte, musste ich
durch mehrere Files durchreichen und der Speicherverbrauch war auch
recht hoch.
Danke für die Antworten!
Albi
Albi schrieb:> Ich verwende einen F303CC, meint ihr der schafft die lvgl?
Sollte schon passen.
lvgl braucht nicht den ganzen Bildschirminhalt im RAM vorhalten, sondern
kommt mit einem Buffer über ein paar Zeilen aus.
Optional aber empfehlenswert: einen zweiten Buffer und DMA für den
Display-Treiber. Dann kann der zweite Buffer vor-gerendert werden,
während der erste noch über SPI rausgeht.
Albi schrieb:> Ich finde keinen Converter, der dass passende Format ausgibt.
Du brauchst gar keinen Konverter - jedenfalls, wenn Du den GNU Linker ld
verwendest. Der kann beliebige Dateien in Objektdateien umwandeln, die
man direkt im Linkprozess einsetzen kann (der "Umweg" über C-Code ist
also nicht notwendig).
Wenn Du dein Bild in "img" hast:
1
ld -r -b binary -o binary.o img
ld erzeugt dann die Symbole (aus dem Namen der Datei)
1
binary_img_start
2
binary_img_end
3
binary_img_size
Im Programm referenzierst Du auf das Bild einfach so:
1
...
2
externchar*binary_img_start[];
und linkst dein binary.o einfach - wie jede andere Objektdatei - dazu.
Markus F. schrieb:> Du brauchst gar keinen Konverter - jedenfalls, wenn Du den GNU Linker ld> verwendest.
Interessant! Das muss ich mal probieren. Danke für die Erklärung. Falls
die lvgl Sache zu stark in die Performance eingeht, dann wird das wohl
der Weg sein den ich weiter gehen werde.
Allerdings hat mich der Gedanke mit der lvgl nicht mehr losgelassen,
seit ihr mir davon erzählt habt.
Ich habe hier ein Projekt gefunden, was sehr gut auf meine Situation
passt.
https://github.com/Paulo-Pecegueiro/LVGL_DEMOS_STM32
Dieses habe ich in CUBE IDE reingeladen und wollte es einfach mal
kompilieren...6 Errors.
Soweit ich rausgefunden habe, hängt das damit zusammen, dass die header
Dateien an mehreren Stellen im Code eingebunden werden und das geht so
nicht. Es sei denn man macht sowas hier: -fno-common (wobei ich noch
nicht weiß was das genau ist und wo ich das in CUBE IDE finde)
Damit blendet man aber wohl noch weitere Meldungen aus, daher möchte ich
das vermeiden es sei denn das ist der "normale" Weg bei solchen größeren
Projekten. Wie würde man das Problem richtig lösen?
ich habe schon angefangen das mit Mbed und dem F303 zu bauen, das
Robotdyn Board ist da aber kein Standard Target und ich musste das erst
einbauen. Und dann kamen die Nickeligkeiten der neuen toolchain
Installation dazu.
Bei lvgl ist sicher die erste Konfiguration das Aufwändigste. Für die
Includes gibt es zwei Varianten, über ein define gesteuert: simple wenn
alle includes in Suchpfaden vorliegen, oder es wird ein Pfad verwendet
und die includes enthalten die kompletten Pfade.
Das -fno-common ist eine Änderung seit gcc10, da wurde der default
umgekehrt weil die Defintion der Variablen im Header unschön ist. In der
CubeIDE müsste man das in den Compiler Settings angeben.
Beim F303 ist der RAM mit 40 (48?) kB etwas knapp, ich würde da einen
401/411 bevorzugen, die sind ja auch als Blackpill Boards zu bekommen.
Albi schrieb:> Soweit ich rausgefunden habe, hängt das damit zusammen, dass die header> Dateien an mehreren Stellen im Code eingebunden werden und das geht so> nicht.
Das Mehrfacheinbinden sollte normalerweise über Header Guards mit
entsprechend bedingter Kompilierung verhindert werden.
Albi schrieb:> Ich habe hier ein Projekt gefunden, was sehr gut auf meine Situation> passt.> https://github.com/Paulo-Pecegueiro/LVGL_DEMOS_STM32
das benutzt auch noch die ältere Version 7, ich würde unbedingt die V8
nehmen. Es sind viele Dinge inkompatibel und der Squarline Editor
generiert auch Code für die V8, damit kann man das Thermostat Projekt
direkt benutzen.
So ein Programm, um eim Bild in ein passentes programminternes Format zu
konvertieren, kann man sich ganz schnell und einfach in python, C, php,
etc. schreiben. Das geht schneller, als zu fragen.
Und eine Datei einbinden ist mittlerweile (seit c23) extrem einfach
geworden:
Markus F. schrieb:> ld erzeugt dann die Symbole (aus dem Namen der Datei)> binary_img_start> binary_img_end> binary_img_size>> Im Programm referenzierst Du auf das Bild einfach so: ...> extern char *binary_img_start[];
Echt jetzt ? Zeiger auf Zeiger auf char ? Oder ist das Sternchen da
optional, wenn man die eckigen Klammern immer vergisst ?
FOp schrieb:> Oder ist das Sternchen da> optional, wenn man die eckigen Klammern immer vergisst ?
Ich denke das Sternchen ist schlicht falsch, und sollte weg. Und nein,
nur das Sternchen darf es auch nicht sein. Nur die [] und gut.
Die Adresse eines Arrays ist die Selbe wie das seines ernsten Elements,
es hat selbst keinen Speicherplatz, um einen Zeiger zu speichern. Ein
Pointer, hingegen, speichert einen Zeiger. Die Adresse eines Pointers
ist, wo dieser gespeichert ist, und nicht der Inhalt. Beim Linken wird
die Adresse von Symbolen aufgelöst, deshalb geht das hier schief, wenn
es nicht zusammenpasst. Dann würden die ersten paar Elemente als ein
Zeiger interpretiert.
Die Bytes von so einem Bild sind doch auch höchstwahrscheinlich
vorzeichenlos, oder ?
Wenn man einfach nur char schreibt, stehen die Chancen einen
vorzeichenlosen Datentyp zu haben eher schlecht.
Ich habe ja die Headerdatei stdint.h für sowas ins Herz geschlossen. :-)
DPA schrieb:> So ein Programm, um eim Bild in ein passentes programminternes Format zu> konvertieren, kann man sich ganz schnell und einfach in python, C, php,> etc. schreiben. Das geht schneller, als zu fragen.>> Und eine Datei einbinden ist mittlerweile (seit c23) extrem einfach> geworden:>
J. S. schrieb:> ich habe schon angefangen das mit Mbed und dem F303
Aber doch hoffentlich nicht extra wegen meinem Problemen hier, sondern
weil du es selbst gerade brauchst?
J. S. schrieb:> Bei lvgl ist sicher die erste Konfiguration das Aufwändigste.
Wem sagst du das :D.
J. S. schrieb:> über ein define gesteuert: simple wenn> alle includes in Suchpfaden vorliegen
Alle Files liegen doch im Ordner LVGL? Oder ist es das was Wolfgang
schreibt?:
Wolfgang schrieb:> Das Mehrfacheinbinden sollte normalerweise über Header Guards mit> entsprechend bedingter Kompilierung verhindert werden.
Diese Header Guards sind doch überall drin, soweit ich das verstehe und
sehe:
1
#ifndef __ILI9341_H__
2
#define __ILI9341_H__
3
....Inhalt.....
4
#endif // __ILI9341_H__
Der Kompiler beschwert sich ja zum einen über "multiple defines" und im
gleichen Atemzug über "first defined here" (siehe Fehlermeldung, die ich
oben gepostet hab.
J. S. schrieb:> das benutzt auch noch die ältere Version 7, ich würde unbedingt die V8> nehmen.
Hmm, ich würde ja erstmal gern die V7 hier zum laufen bringen, einen
F411 hab ich als BlackPill da zum testen. Es hängt aber immer noch an
den Fehlermeldungen. Der F303 sitzt auf einer Platine, da würde ich gern
das Display nachrüsten. Der Umstieg auf V8 ist doch hoffetlich bloß das
austusche des LVGL Ordners, oder :)? Aber Sinn würde es schon machen, da
hast du natürlich recht.
Gruß
Albi
Albi schrieb:> J. S. schrieb:>> Bei lvgl ist sicher die erste Konfiguration das Aufwändigste.>> Wem sagst du das :D.
Hab ich nicht als so komplex in Erinnerung.
Verwende das aber mit platformio als Build-System, nicht in der CubeIDE.
LVGL ziehe ich da einfach per lib_deps = lvgl/lvgl@^8.3.0 rein,
die Konfiguration mache ich (ohne lv_conf.h) rein über defines in den
build_flags:
FOp schrieb:> Die Bytes von so einem Bild sind doch auch höchstwahrscheinlich> vorzeichenlos, oder ?
Du wirst es kaum glauben: Die Hardware interessiert sich kein bissel für
das Vorzeichen. Der ist es scheißegal, mit einen Array welchen
Datentypes das in C deklariert/definiert ist. Hauptsache, die Bitmuster
stimmen.
signed char -1 und unsigned char 255 und uint8_t 0xff z.B. haben alle
exakt das gleiche Bitmuster (jedenfalls auf allen neuzeitlichen
Systemen).
Nur das C-Gelumpe braucht "Datentypen". Echte Männer und echte Hardware
brauchen die nicht.
Albi schrieb:> Der Kompiler beschwert sich ja zum einen über "multiple defines" und im> gleichen Atemzug über "first defined here" (siehe Fehlermeldung, die ich> oben gepostet hab.
Die Struktur Disp ist mehrfach vorhanden, im Modul für den ILI und ST.
Wenn nur das ILI verwendet wird, dann das ST löschen oder umbenennen
damit es nicht mitkompiliert wird.
Vielleicht sollten mal beide Display gleichzeitig angesteuert werden,
das kann lvgl ja auch. Dann muss man das mit dem Disp aber besser lösen.
Albi schrieb:> Aber doch hoffentlich nicht extra wegen meinem Problemen hier, sondern> weil du es selbst gerade brauchst?
den F303 hatte ich gerade beim Aufräumen in der Hand und wollte den auch
mal nutzbar machen. lvgl habe ich schon für mehrere Controller
eingebaut, auch direkt über git in das Projekt eingebaut.
J. S. schrieb:> Wenn nur das ILI verwendet wird, dann das ST löschen oder umbenennen> damit es nicht mitkompiliert wird.
Das bringt leider nichts, es verschwindet nur ein Fehler. Ich steh auf
dem Schlauch, wie kann man das Problem beheben?
Der Kollege wird doch kein Projekt hochgeladen haben welches NICHT geht?
Beim https://github.com/lvgl/lv_port_stm32f429_disco siehts auch nicht
besser aus. Reinladen und kompilieren-->Fehler.
Das kann doch nicht im Sinne des (der) Erfinders sein?
VG Albi
Albi schrieb:> Hat keiner einen Rat oder ist es einfach untergeganen in den vielen> Beiträgen?Albi schrieb:> Beim https://github.com/lvgl/lv_port_stm32f429_disco siehts auch nicht> besser aus. Reinladen und kompilieren-->Fehler.>> Das kann doch nicht im Sinne des (der) Erfinders sein?
Tja, das kommt davon, wenn man ein Ziel anvisiert und es ohne eigenes
Verstehen des Ganzen erreichen will. Allerdings räume ich ein, daß
gerade bei dem großen Müllhaufen namens GIT gar vieles dabei ist, was
so, wie es dort steht, nur unter ganz bestimmten Bedingungen überhaupt
funktionabel ist - was dank des besonders geringen Dokumentationseifers
der Autoren auch nirgendwo zu lesen steht. Man geht da eben davon aus,
daß jeder Leser bereits alles darüber von selbst weiß.
Ich kann dir hier nur die folgenden recht allgemeinen Ratschläge geben:
1. mach dir klar, wieviel Flash dein µC hat und wieviel davon du für
Grafiken verwenden willst. Grafiken brauchen relativ viel Platz und du
mußt ja auch noch Platz haben für die eigentliche Firmware, die davon
Gebrauch machen soll und obendrauf auch noch irgend eine Nutzfunktion
haben soll.
2. mach dir klar, wieviele Grafiken in welcher Größe und welcher
Farbauflösung und welcher Codierungsart du in dem angedachten Platz
unterbringen kannst. Wenn das mit gewöhnlicher Bitmap-Codierung (also
quasi überhaupt keiner) geht, dann bist du fein raus, denn dann brauchst
du nur die Bytes der Grafik(en) unterzubringen und fertig. Wie du diese
dann in dein Display schaufelst, solltest du selber wissen. Wenn du
aber mit dem Platz nicht auskommst (was ich stark vermute), dann mußt du
eine komprimierterer Codierung benutzen. Allerdings brauchst du dann
noch eine Dekomprimierung in deiner Firmware und die kann je nach
Codierung der Grafik recht aufwendig sein. Ich schrieb ja schon, daß JPG
und PNG für die Verwendung auf einem µC nicht so günstig sind.
3. wenn du für deine Grafiken Komprimierung brauchst, dann fängt genau
HIER das Lernen und Nachdenken für dich an. Ratschläge und Tips dazu
findest du hier im Forum genug, sofern du mal danach suchst.
W.S.
lvgl läuft auf dem F303, aber man kommt schon schnell in Speichernot.
Neben dem Framebuffer braucht man noch Speicher für die Objekte, und das
läppert sich auch auf mehrere kB. Dazu macht lvgl noch einiges dynamisch
und braucht dafür auch Speicher, ich hatte einige Hardfaults zur
Laufzeit und musste einge der Demoscreens rauswerfen. Ein µC mit mehr
Resourcen ist da schon besser.
Das war jetzt eine Demo die beim SquareLine Studio dabei ist. Das
Thermostat Projekt fehlt da leider, bzw. in einer einfachen Form
vorhanden. Ich habe mal angefragt wo die Quellen sind, das interessiert
mich auch.
Die Ausgabe läuft flüssig, es werden aber auch nur kleine
Speicherbereiche bewegt. Wenn es ruckelt dann weil ich frei Hand gefilmt
habe... Mein Treiber ist minimal ohne DMA mit einem Framebuffer. Mit DMA
geht es nochmal deutlich fixer, macht aber vor allem Sinn wenn man genug
Speicher für zwei FB hat, dann kann beim Schaufeln ins Display schon der
nächste Bereich von der CPU berechnet werden.
J. S. schrieb:> lvgl läuft auf dem F303
Sieht gut aus :).
Das ist ja schon mal gut zu wissen, nur bei mir eben noch nicht so wie
sie soll :D.
Ich habe jetzt die V8 runtergeladen, der lvgl Ordner in mein Projekt
eingefügt, die Pfade verlinkt etc. Mein bisheriges Projekt braucht ca.
25% des RAMs...wenn ich jetzt die lvgl einbinde und die "lv_init"
aufrufe, bekommt ich die Meldung das ich 17KB über dem RAM Limit bin. In
der Config hab ich schon alles mögliche versucht abzuschalten, aber
gefühlt bringt es keine Verbesserung.
Wie viel Speicher RAM und Flash verbraucht deine DEMO bei dir?
Danke für den Support und beste Grüße
Albi
Albi schrieb:> wenn ich jetzt die lvgl einbinde und die "lv_init"> aufrufe, bekommt ich die Meldung das ich 17KB über dem RAM Limit bin.
Das hängt von den Einstellungen in lv_conf.h ab. Man muss eine aus dem
template erstellen und sich mal durch die Einstellungen hangeln, default
wird nicht passen.
Ich habe vom F303 bisher nur die 40 kB genutzt, die 8 kB CCM gerade erst
eingebaut und teste da noch weiter. Man kann ein Logging einschalten um
den dynamischen Speicherbedarf zu kontrollieren. Für diese Demo musste
ich schon Screens rauswerfen, das braucht schon einiges.
Touch habe ich auch noch nicht drin, dafür ist der Aufbau mit Dupont
Kabeln auch zu wackelig.
Mein Projekt ist auf github, aber noch sehr WIP. Für den F303CC war die
RAM größe noch falsch und das muss im mbed-os repo noch gefixt werden.
https://github.com/JojoS62/mbed-ce-lvglhttps://github.com/JojoS62/mbed-ce-lvgl/blob/main/app-thermostat/lv_conf.h