Bonjour à tous,
Je suis complètement débutant dans le monde de l'Arduino.
On m'a donné une Arduino Uno et un LCD 2,4"TFT LCD SHIELD. Etant maquettiste, je me suis dit que je pourrais fixer la carte et son écran à l’intérieur d'un socle de maquette pour faire défiler des photos du montage de la maquette.
L'idée est sympa, mais alors la réalisation...........
Après plusieurs heures et essais de diverses librairies, l'écran fonctionne avec la librairie MCUFRIEND_kbv.
J'ai donc testé plusieurs programmes exemples d'affichage, sympa ce que peux afficher cette petite carte.
Puis j'ai collé 2 ou 3 photo BMP sur la SD et téléversé le programme showbmp_kbv_uno (programme exemple trouvé dans la bibliothèque MCUFRIEND), mais aucun affichage. L'écran passe au bleu et ne bouge plus ( j'ai essayé de vous coller le programme, mais il est trop long pour le poster. Cela bloque la publication du message).
Et quand je clique su la petite loupe en haut à droite j'obtient cela :
Show BMP files on TFT with ID:0x9341
cannot start SD
En espérant que vous pourrez m'aider
MErci
En espérant que vous pourrez résoudre mon problème.
Merci bien
Tu as testé avec une autre carte SD, ou reformaté la carte ?
Christian_R:
Tu as testé avec une autre carte SD, ou reformaté la carte ?
Oui, testé vec une autre SD et formaté en fat16 et Fat32
Merci.
Le programme : je le coupe en deux que que le message soit publié
// MCUFRIEND UNO shields have microSD on pins 10, 11, 12, 13
// The official <SD.h> library only works on the hardware SPI pins
// e.g. 11, 12, 13 on a Uno (or STM32 Nucleo)
//
// copy all your BMP files to the root directory on the microSD with your PC
// (or another directory)
#include <SPI.h> // f.k. for Arduino-1.5.2
//#define USE_SDFAT
#include <SD.h> // Use the official SD library on hardware pins
#include <Adafruit_GFX.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#define SD_CS 10
#define NAMEMATCH "" // "" matches any name
//#define NAMEMATCH "tiger" // *tiger*.bmp
#define PALETTEDEPTH 0 // do not support Palette modes
//#define PALETTEDEPTH 8 // support 256-colour Palette
char namebuf[32] = "/"; //BMP files in root directory
//char namebuf[32] = "/bitmaps/"; //BMP directory e.g. files in /bitmaps/*.bmp
File root;
int pathlen;
void setup()
{
uint16_t ID;
Serial.begin(9600);
Serial.print("Show BMP files on TFT with ID:0x");
ID = tft.readID();
Serial.println(ID, HEX);
if (ID == 0x0D3D3) ID = 0x9481;
tft.begin(ID);
tft.fillScreen(0x001F);
tft.setTextColor(0xFFFF, 0x0000);
bool good = SD.begin(SD_CS);
if (!good) {
Serial.print(F("cannot start SD"));
while (1);
}
root = SD.open(namebuf);
pathlen = strlen(namebuf);
}
void loop()
{
char *nm = namebuf + pathlen;
File f = root.openNextFile();
uint8_t ret;
uint32_t start;
if (f != NULL) {
#ifdef USE_SDFAT
f.getName(nm, 32 - pathlen);
#else
strcpy(nm, (char *)f.name());
#endif
f.close();
strlwr(nm);
if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH) != NULL) {
Serial.print(namebuf);
Serial.print(F(" - "));
tft.fillScreen(0);
start = millis();
ret = showBMP(namebuf, 5, 5);
switch (ret) {
case 0:
Serial.print(millis() - start);
Serial.println(F("ms"));
delay(5000);
break;
case 1:
Serial.println(F("bad position"));
break;
case 2:
Serial.println(F("bad BMP ID"));
break;
case 3:
Serial.println(F("wrong number of planes"));
break;
case 4:
Serial.println(F("unsupported BMP format"));
break;
case 5:
Serial.println(F("unsupported palette"));
break;
default:
Serial.println(F("unknown"));
break;
}
}
}
La suite du programme :
else root.rewindDirectory();
}
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL 20
uint16_t read16(File& f) {
uint16_t result; // read little-endian
f.read(&result, sizeof(result));
return result;
}
uint32_t read32(File& f) {
uint32_t result;
f.read(&result, sizeof(result));
return result;
}
uint8_t showBMP(char *nm, int x, int y)
{
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24, 16, 8, 4, 1)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
uint8_t bitmask, bitshift;
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
uint32_t pos; // seek position
boolean is565 = false; //
uint16_t bmpID;
uint16_t n; // blocks read
uint8_t ret;
if ((x >= tft.width()) || (y >= tft.height()))
return 1; // off screen
bmpFile = SD.open(nm); // Parse BMP header
bmpID = read16(bmpFile); // BMP signature
(void) read32(bmpFile); // Read & ignore file size
(void) read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
(void) read32(bmpFile); // Read & ignore DIB header size
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
n = read16(bmpFile); // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
pos = read32(bmpFile); // format
if (bmpID != 0x4D42) ret = 2; // bad ID
else if (n != 1) ret = 3; // too many planes
else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
else {
bool first = true;
is565 = (pos == 3); // ?already in 16-bit format
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
if (bmpHeight < 0) { // If negative, image is in top-down order.
bmpHeight = -bmpHeight;
flip = false;
}
w = bmpWidth;
h = bmpHeight;
if ((x + w) >= tft.width()) // Crop area to be loaded
w = tft.width() - x;
if ((y + h) >= tft.height()) //
h = tft.height() - y;
if (bmpDepth <= PALETTEDEPTH) { // these modes have separate palette
bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
bitmask = 0xFF;
if (bmpDepth < 8)
bitmask >>= bmpDepth;
bitshift = 8 - bmpDepth;
n = 1 << bmpDepth;
lcdbufsiz -= n;
palette = lcdbuffer + lcdbufsiz;
for (col = 0; col < n; col++) {
pos = read32(bmpFile); //map palette to 5-6-5
palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
}
}
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
uint8_t r, g, b, *sdptr;
int lcdidx, lcdleft;
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; ) { //pixels in row
lcdleft = w - col;
if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
uint16_t color;
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
r = 0;
}
switch (bmpDepth) { // Convert pixel from BMP to TFT format
case 24:
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
color = tft.color565(r, g, b);
break;
case 16:
b = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
if (is565)
color = (r << 8) | (b);
else
color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
break;
case 1:
case 4:
case 8:
if (r == 0)
b = sdbuffer[buffidx++], r = 8;
color = palette[(b >> bitshift) & bitmask];
r -= bmpDepth;
b <<= bmpDepth;
break;
}
lcdbuffer[lcdidx] = color;
}
tft.pushColors(lcdbuffer, lcdidx, first);
first = false;
col += lcdidx;
} // end cols
} // end rows
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
ret = 0; // good render
}
bmpFile.close();
return (ret);
}
pepe:
Bonjour
Le problème survient dès le début du programme. L'Arduino ne parvient pas à communiquer avec la carte SD.
Il faudrait commencer par vérifier le câblage du lecteur de carte SD et sa correspondance avec le programme (entrée CS sur la sortie 10 de l'Arduino, d'après le code).
Ok, je vais essayer de regarder cela.
Existe t-il un moyen pour connaitre le câblage du lecteur SD ?
Et merci
pepe:
Le matériel que tu utilises devrait être accompagné d'une documentation technique qui indique son brochage, voire d'un schéma électrique.
On ne sait rien de précis sur ta configuration, sinon qu'elle ne correspond pas à une carte Arduino officielle (puisqu'Arduino ne propose ni de shield LCD 2.4" TFT ni de lecteur SD seul), et on trouve de nombreuses cartes avec des caractéristiques différentes dans le commerce.
En particulier, on ne sait pas s'il s'agit d'un lecteur SD séparé ou intégré au module LCD, ni si le l'écran partage l'interface SPI du lecteur ou s'il utilise une autre interface (I2C ou parallèle, notamment).
Aurais-tu des références plus précises de ton matériel ?
Merci de ton aide,
le lecteur Sd est bien intégré au LCD. Le PCB est rouge :
Voici un lien de mon écran : https://www.mudah.my/Arduino+tft+lcd+touch+screen+shield+2+4+inch-56335188.htm
Je ne connais pas la marque, mais la mienne est identique au niveau aspect.
Pour la Arduino, il est indiqué UNO en gros sur le dessus.
le lien : Arduino UNO R3 died.. ? - IDE 1.x - Arduino Forum
Merci encore
pepe:
J'ai tenté de trouver une documentation technique du module LCD/SD en partant du lien que tu as donné, en m'aidant la plupart du temps de l'outil de traduction chinois-français de Google, sans succès.
Toutefois, la photo du produit suggère que l'interface du lecteur SD et celle de l'écran sont bien séparées, et que la broche de sélection SPI du lecteur SD est bien la 10, comme dans ton programme.
On voit également une puce qui s'apparente à un régulateur de tension qui suggère que le lecteur SD possède sa propre alimentation de 3,3V.
En revanche, le fait que les connexions de l'interface SPI aillent directement du connecteur Arduino au réceptacle métallique du lecteur SD soulève une interrogation quant à la présence ou l'absence d'un circuit de conversion (absolument nécessaire) entre les signaux logiques en 5V de l'Arduino et ceux en 3,3V des cartes mémoire SD.
Côté Arduino, il s'agit d'un clone d'une carte Uno SMD, avec une interface USB à base de CH340/341. Puisque tu arrives à la programmer, elle devrait en principe exécuter les applications comme une carte Uno R3 officielle.
Le problème avec les cartes électroniques chinoises bon marché, c'est que les spécifications complètes nécessaires à leur mise en œuvre sont généralement absentes, que la plupart du temps il n'y a pas de contrôle qualité de la production de sorte que le risque d'acheter un produit déjà en panne est élevé, et que les circuits souffrent quelquefois de gros problèmes de conception qui font qu'ils tombent en marche mais finissent à plus ou moins long terme par tomber en panne ou par provoquer des incidents (voire des accidents) chez les clients.
Dans ton cas, le programme s'arrête normalement sur un échec d'initialisation de la carte SD. Ce symptôme semble indiquer :
- soit un défaut matériel (panne, défaut de fabrication ou défaut de conception) sur le clone Arduino ou sur le module LCD/SD,
- soit un problème de compatibilité entre la bibliothèque logicielle SD et le type de formatage ou le modèle de la carte SD utilisée.
Comme ça, de loin et sans matériel de test spécifique, je ne peux malheureusement pas en dire plus.
Pas de chance pour moi.
Pourrais tu me conseiller le même produit "fiable" (Carte + écran) dans une boutique sérieuse.
Et encore merci 