Forum: Compiler & IDEs Fehlermeldung Arduino C++


von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Hallo Forum,

ich hacke gerade ein bisschen an der TFT Lib vom Arduino, weil das Laden 
eines 24 Bit BMP mit 160x128 ca. 3s dauert.

Anyway, folgender Fehler ist mir vollkommen unklar. Von C++ hab ich 
keine Ahnung, ich mach nur C&P ;-)

In file included from C:\Programme\Arduino\libraries\TFT\src/TFT.h:6:0,
                 from TFTBitmapLogo.ino:25:
C:\Programme\Arduino\libraries\TFT\src/utility/Adafruit_GFX.h: In member 
function 'void Adafruit_GFX::image(PImage&, uint16_t, uint16_t)':
C:\Programme\Arduino\libraries\TFT\src/utility/Adafruit_GFX.h:297:37: 
error: 'setAddrWindow' was not declared in this scope
     setAddrWindow(x, y, x+w-1, y+h-1);
                                     ^
Fehler beim Kompilieren.

Siehe Anhang.

Meine andere, selbstgestrickte Funktion

void Adafruit_ST7735::drawFastHblock(uint8_t *data, uint16_t cnt) {

funktioniert anscheinend. Zumindest erkennt sie der Compiler.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Naja, wo kommt denn "setAddrWindow" her? Das ist eine Memberfunktion der 
Klasse Adafruit_ST7735, die von Adafruit_GFX abgeleitet ist.

Woher aber soll die Basisklasse von dieser Funktion wissen?

von Falk B. (falk)


Lesenswert?

@ Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite

>Naja, wo kommt denn "setAddrWindow" her? Das ist eine Memberfunktion der
>Klasse Adafruit_ST7735, die von Adafruit_GFX abgeleitet ist.

So in etwa.

>Woher aber soll die Basisklasse von dieser Funktion wissen?

Na ich dacht mit dem Eintrag

drawFastHblock(uint8_t *data, uint16_t cnt),

in Adafruit_ST7735.h

Siehe unten.
1
class Adafruit_ST7735 : public Adafruit_GFX {
2
3
 public:
4
5
  Adafruit_ST7735(uint8_t CS, uint8_t RS, uint8_t SID, uint8_t SCLK,
6
    uint8_t RST);
7
  Adafruit_ST7735(uint8_t CS, uint8_t RS, uint8_t RST);
8
9
  void     initB(void),                             // for ST7735B displays
10
           initG(void),                             // for ILI9163C displays
11
           initR(uint8_t options = INITR_GREENTAB), // for ST7735R
12
           setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1),
13
           pushColor(uint16_t color),
14
           fillScreen(uint16_t color),
15
           drawPixel(int16_t x, int16_t y, uint16_t color),
16
           drawFastHblock(uint8_t *data, uint16_t cnt),

OK, falsch gedacht. Wo muss die Deklaration noch rein (jaja, aber 
wirklich, ich habe KEINE Ahnung von C++, hab nur mal vor Jahren ein C++ 
Buch durchgeblättert, ich weiß, C++ Buch kaufen und durcharbeiten).

von Falk B. (falk)


Lesenswert?

OK, mit C&P hat es dann doch geklappt. ;-)
1
class Adafruit_GFX : public Print {
2
 public:
3
4
  Adafruit_GFX(int16_t w, int16_t h); // Constructor
5
6
  // This MUST be defined by the subclass
7
  virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
8
  virtual void setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) = 0;
9
  virtual void drawFastHblock(uint8_t *data, uint16_t cnt) =0;

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

So liebe Leute, hier mal mein Ergebnis. Wie gesagt, ich spiel im Moment 
mit dem Arduino TFT rum, die Lib kann BMP Bilder direkt von SD-Karte auf 
den TFT kopieren, allerdings ist das etwas langsam. Darum hab ich die 
Funktionen etwas aufgebohrt, jetzt werden auch direkt 16 Bit BMPs 
gelesen, was schon 7mal so schnell ist, ausserdem kann man Bilder in den 
Flash legen und von dort direkt anzeigen, was nochmal ca. doppelt so 
schnell ist!
1
Datei (B x H x Bits) Ladezeit / ms
2
48x48x24                 351   
3
1260x128x24             2930
4
48x48x16                  47 
5
160x128x16               414 
6
48x48x16 (Flash)          19
7
80x128x16 (Flash)         84

Das kann sich schon mal sehen lassen.
Es gibt dabei folgende Begrenzungen.

1.) Ein einzelnes Bild im Flash darf max. 32767 Bytes groß sein, denn 
hier greift leider die maximale Größe eines einzelnen char[] Arrays. 
D.h. man kann nicht ganz die vollen 160x128 in ein Bild packen. Wenn man 
das will, muss man es zweiteilen.
2.) Die Gesamtanzahl an Bilddaten darf 64kB nicht übersteigen, auch 
nicht auf dem MEGA256, weil auch hier wieder die Grenze der Pointer im 
avr gcc mit 64 kB greift. Ausserdem scheint das Programm gar nicht erst 
loszulaufen, wenn deutlich mehr als 64kB Flashgröße erzeugt werden (Bug 
im avr gcc, wenn der Einsprung vom Resetvektor >64kB?, Problem im 
Bootloader?)

Auf dem DUE mit dem ARM sollten diese Begrenzungen nicht greifen. Kann 
ich mangels Hardware aber nicht testen.

Beim Laden von Bildern vom Flash gibt es keine Größenbegrenzung.

Wenn man ein Bild in den Flash legen will, muss man

-das Bild mit einem Grafikprogramm wie GIMP o.ä. als 16 Bit BMP 
speichern, wobei es als Top-Down gespeichert werden muss!
- mit dem Tool bin2c in C-Quelltext umwandeln und per include einfügen.

auf der Kommandozeile z.B. so

bin2c bild.bmp >bild.c

- die Kopfzeile muss man manuell anpassen, siehe Beispiel.
- in sketch mittels der neuen Methode TFTscreen.loadImageFlash() 
"laden", dabei wird der Header dekodiert.
- Die Anzeige auf dem TFT erfolgt mit der bekannten Methode 
TFTscreen.image(), welche erweitert wurde.

Das Archiv TFT.zip muss in C:\Programme\Arduino\libraries, es enthält 
die erweiterten Methoden für den TFT
Das Archiv TFTBitmapLogo.zip enthält das sketch und die includes für die 
Bilder sowie das tool. Im sketch muss man die Pfade der Bilder anpassen, 
irgendwie mag Arduino keine relativen Pfade im Projektverzeichnis, oder?

Ach ja, das Pinout für den TFT/SD-Shield hab ich passend für meinen 
Lochrasterausbau gewählt, kann man aber leicht mit den #defines am 
Anfang ändern, ist glaube ich selbsterklärend.

Viel Spaß damit
Falk

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Hier noch die Bilder für die SD-Karte, damit das Beispiel funktioniert.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Falk Brunner schrieb:
> Ein einzelnes Bild im Flash darf max. 32767 Bytes groß sein, denn hier
> greift leider die maximale Größe eines einzelnen char[] Arrays.

Wieso sollte es da eine Begrenzung geben? Könnte es sein, daß Du einen 
ungünstigen Datentyp als Index zum Arrayzugriff verwendest?

von Falk B. (falk)


Lesenswert?

@ Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite

>> Ein einzelnes Bild im Flash darf max. 32767 Bytes groß sein, denn hier
>> greift leider die maximale Größe eines einzelnen char[] Arrays.

>Wieso sollte es da eine Begrenzung geben?

Weil dass der gcc auspuckt.
1
In file included from TFTBitmapLogo.ino:28:0:
2
D:\Projekte\Arduino\TFT\TFTBitmapLogo\a\che.c:1:12: error: size of variable 'che' is too large
3
 const char che[] PROGMEM = {

Das Array ist ~40kB.

http://www.avrfreaks.net/forum/sizet

> Könnte es sein, daß Du einen
>ungünstigen Datentyp als Index zum Arrayzugriff verwendest?

Nö, er meckert über die Definition. Da gibt es noch dar keinen Index.

von Falk B. (falk)


Lesenswert?

Ein paar Links zum Thema.

http://www.avrfreaks.net/forum/maximum-size-progmem-array

http://www.avrfreaks.net/forum/sizet

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_PROGMEM_und_pgm_read

Bisschen runter, Variablenzugiff > 64kB. (ich kann keinen direkten Link 
erzeugen, doofe Formatierung).

Was am Ende zu der Aussage führt, dass der ArduinoMEGA256 mit seinem 
großen Speicher nutzlos ist, denn der avr gcc kann damit nicht direkt 
umgehen. Ein typischer Aduinouser kann und will nicht mit den Makros und 
den Linkeroptionen rumeiern, ich auch nur bedingt. Also Leute, kauft 
euch besser einen Arduino DUE oder andere ARMs, die können ihren 
Speicher ohne Handstände voll ausnutzen.
Der einzige Vorteil des MEGA256 sind mehr Pins und IO Module (UARTs, 
SPI, Timer, PWM, etc).

von Walter S. (avatar)


Lesenswert?

Falk Brunner schrieb:
> Bisschen runter, Variablenzugiff > 64kB.

da steht eigentlich RAM>64K und flash>128K
und bei dir sind es 40K im PROGMEM, muesste also so und so passen,
aber natürlich glaube ich Dir dass die Meldung kommt

von chris_ (Gast)


Lesenswert?

Viel weiss ich auch nicht darüber, aber mir würde spontan die Wahl des 
Memory-Modells als Option des AVR-GCC einfallen. Wahrscheinlich muss man 
irgendwo "large" angeben.

von chris_ (Gast)


Lesenswert?

Die AVR-Freaks behandeln das Thema ausführlich. Wenn ich es richtig 
verstehe, gibt es beim AVR-GCC eine Limitierung auf 32k :
http://www.avrfreaks.net/forum/maximum-size-progmem-array

Einer schlägt vor, größere Arrays in eine .s Datei zu packen.

von Oliver S. (oliverso)


Lesenswert?

chris_ schrieb:
> ich es richtig
> verstehe, gibt es beim AVR-GCC eine Limitierung auf 32k :
> http://www.avrfreaks.net/forum/maximum-size-progmem-array

Die Diskussion gab es doch hier auch schon mal. Der Index ist halt per 
Definition ein (signed) int, und der ist beim avr-gcc 16 bit breit. Da 
ist bei 32k Arrayelementen Schluss.

Oliver

von frischling (Gast)


Lesenswert?

Naive gefragt, warum signed ?

Zur Adressierung braucht es doch keine negativen Zahlen ?

von Oliver S. (oliverso)


Lesenswert?

Weil das halt so im C-Standard steht.

Hier einer der älteren Threads zum Thema (da gibt's noch mehr von)

Beitrag "Arrays können max 32768 Byte groß sein. Warum nicht 65534?"

Oliver

von frischling (Gast)


Lesenswert?

Ich dachte es gäbe eine "logische" Erklärung.
Irgend einen Hintergrund technischer Natur.

von Markus F. (mfro)


Lesenswert?

frischling schrieb:
> Ich dachte es gäbe eine "logische" Erklärung.
> Irgend einen Hintergrund technischer Natur.

Wie Vieles: weil's schon immer so war und jetzt kann's keiner mehr 
ändern.

Die Definition erlaubt aber auch negative Indizes (und Compiler können 
damit umgehen, obwohl's keiner benutzt). Mit
1
    char *p, *arr;
2
    int i;
3
4
    p = malloc(64 * 1024L);
5
    arr = p + 32 * 1024L;
6
7
    for (i = -32 * 1024; i < 32 * 1024 - 1; i++)
8
        arr[i] = 'A';
(mag sein, daß da noch ein "um eins daneben" Fehler drinsteckt, hab' ich 
jetzt aus der Hüfte geschossen) kannst Du deswegen auch mit 16-Bit 
signed ints 64k Arrays beackern.

von Rolf M. (rmagnus)


Lesenswert?

frischling schrieb:
> Naive gefragt, warum signed ?
>
> Zur Adressierung braucht es doch keine negativen Zahlen ?

Pointer-Arithmetik erlaubt die Bildung der Differenz der Adressen zweier 
Elemente eines Arrays. Da diese Differenz auch negativ sein kann, wird 
ein vorzeichenbehafteter Wert benötigt.

Beispiel:

Ich will in einem String die Zahl an Zeichen vom ersten e bis zum ersten 
a ermitteln:
1
const char* text = "Hallo Welt";
2
3
const char* e = strchr(text, 'e');
4
const char* a = strchr(text, 'a');
5
int diff = a - e;
Da das a vor dem e liegt, ist das Ergebnis hier negativ.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.