jeudi 13 avril 2023

Mini écrans : affichage d'images

 Les essais avec les écrans se poursuivent avec cette fois-ci le grand modèle 3.5 pouces 320 * 480 HD qui s'insère directement sur un Arduino MEGA2560. Avec cela l'affichage des images c'est du sérieux!

 

Vue de l'écran monté sur l'Arduino MEGA2560

Aucune difficulté de montage ni de risque de se tromper dans le branchement. Au dos de l'écran on trouve un lecteur de carte SD intégré.

Il est très important de bien préparer les images avec le bon outil et surtout au bon format. Sans cela aucun affichage...

Pour cet écran, les images sont à retailler en 320 * 480 px et à sauvegarder en bitmap (.bmp) 24 bits.

Faites aussi attention de bien inverser l'image car le programme affiche en miroir!

Exemple de préparation de fichier image

 Le nommage des images doit être cohérent des noms dans le code ci-après (01.bmp à 04.bmp).


Le code: 

Le code de cette démonstration est issu de LCDWIKI (à consulter car beaucoup d'informations intéressantes ici) avec notre adaptation. Le nombre de fichiers peut être facilement augmenté en modifiant le nombre de fichiers (en rouge ci-après) et ajoutant des instructions dans le setup().
 
[code]
// IMPORTANT: LCDWIKI_KBV LIBRARY MUST BE SPECIFICALLY
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.

//This program is a demo of how to show a bmp picture from SD card.

//Set the pins to the correct ones for your development shield or breakout board.
//the 16bit mode only use in Mega.you must modify the mode in the file of lcd_mode.h
//when using the BREAKOUT BOARD only and using these 16 data lines to the LCD,
//pin usage as follow:
//             CS  CD  WR  RD  RST  D0  D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15
//Arduino Mega 40  38  39  /   41   37  36  35  34  33  32  31  30  22  23  24   25   26   27   28   29

//Remember to set the pins to suit your display module!

#include <SD.h>
#include <SPI.h>
#include <LCDWIKI_GUI.h> //Core graphics library
#include <LCDWIKI_KBV.h> //Hardware-specific library

//the definiens of 16bit mode as follow:
//if the IC model is known or the modules is unreadable,you can use this constructed function
LCDWIKI_KBV my_lcd(ILI9486,40,38,39,-1,41); //model,cs,cd,wr,rd,reset

#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define PIXEL_NUMBER  (my_lcd.Get_Display_Width()/4)
#define FILE_NUMBER 4
#define FILE_NAME_SIZE_MAX 20

uint32_t bmp_offset = 0;
uint16_t s_width = my_lcd.Get_Display_Width();  
uint16_t s_heigh = my_lcd.Get_Display_Height();
//int16_t PIXEL_NUMBER;

char file_name[FILE_NUMBER][FILE_NAME_SIZE_MAX];

uint16_t read_16(File fp)
{
    uint8_t low;
    uint16_t high;
    low = fp.read();
    high = fp.read();
    return (high<<8)|low;
}

uint32_t read_32(File fp)
{
    uint16_t low;
    uint32_t high;
    low = read_16(fp);
    high = read_16(fp);
    return (high<<8)|low;   
 }
 
bool analysis_bpm_header(File fp)
{
    if(read_16(fp) != 0x4D42)
    {
      return false;  
    }
    //get bpm size
    read_32(fp);
    //get creator information
    read_32(fp);
    //get offset information
    bmp_offset = read_32(fp);
    //get DIB infomation
    read_32(fp);
    //get width and heigh information
    uint32_t bpm_width = read_32(fp);
    uint32_t bpm_heigh = read_32(fp);
    if((bpm_width != s_width) || (bpm_heigh != s_heigh))
    {
      return false;
    }
    if(read_16(fp) != 1)
    {
        return false;
    }
    read_16(fp);
    if(read_32(fp) != 0)
    {
      return false;
     }
     return true;
}

void draw_bmp_picture(File fp)
{
  uint16_t i,j,k,l,m=0;
  uint8_t bpm_data[PIXEL_NUMBER*3] = {0};
  uint16_t bpm_color[PIXEL_NUMBER];
  fp.seek(bmp_offset);
  for(i = 0;i < s_heigh;i++)
  {
    for(j = 0;j<s_width/PIXEL_NUMBER;j++)
    {
      m = 0;
      fp.read(bpm_data,PIXEL_NUMBER*3);
      for(k = 0;k<PIXEL_NUMBER;k++)
      {
        bpm_color[k]= my_lcd.Color_To_565(bpm_data[m+2], bpm_data[m+1], bpm_data[m+0]);
        m +=3;
      }
      for(l = 0;l<PIXEL_NUMBER;l++)
      {
        my_lcd.Set_Draw_color(bpm_color[l]);
        my_lcd.Draw_Pixel(j*PIXEL_NUMBER+l,i);
      }    
     }
   }    
}

void setup()
{
    Serial.begin(9600);
   my_lcd.Init_LCD();
   my_lcd.Fill_Screen(BLUE);
   //s_width = my_lcd.Get_Display_Width();  
   //s_heigh = my_lcd.Get_Display_Height();
   //PIXEL_NUMBER = my_lcd.Get_Display_Width()/4;
   if(PIXEL_NUMBER == 60)
   {
       strcpy(file_name[0],"flower.bmp");
       strcpy(file_name[1],"tiger.bmp");
       strcpy(file_name[2],"tree.bmp");
       strcpy(file_name[3],"RedRose.bmp");
   }
   else
   {
       strcpy(file_name[0],"01.bmp");
       strcpy(file_name[1],"02.bmp");
       strcpy(file_name[2],"03.bmp");
       strcpy(file_name[3],"04.bmp");

   }
  //Init SD_Card
   pinMode(53, OUTPUT);
   
    if (!SD.begin(53))
    {
      my_lcd.Set_Text_Back_colour(BLUE);
      my_lcd.Set_Text_colour(WHITE);    
      my_lcd.Set_Text_Size(1);
      my_lcd.Print_String("SD Card Init fail!",0,0);
    }
}

void loop()
{
    int i = 0;
    File bmp_file;

    my_lcd.Set_Rotation(1);
    my_lcd.Set_Text_Mode(0);
    my_lcd.Set_Text_colour(RED);
    my_lcd.Set_Text_Back_colour(BLACK);
    my_lcd.Set_Text_Size(1);
    my_lcd.Print_String("a b c d e f g h i j k l m n o p q r s t u v w x y z", 87, 10);
    my_lcd.Print_String("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z", 87, 20);

    my_lcd.Set_Text_colour(GREEN);
    my_lcd.Set_Text_Size(2);
    my_lcd.Print_String("a b c d e f g h i j k l m", 90, 40);
    my_lcd.Print_String("n o p q r s t u v w x y z", 90, 60);
    my_lcd.Print_String("A B C D E F G H I J K L M", 90, 80);
    my_lcd.Print_String("N O P Q R S T U V W X Y Z", 90, 100);
 
    my_lcd.Set_Text_colour(BLUE);
    my_lcd.Set_Text_Size(3);
    my_lcd.Print_String("a b c d e f g h i j k l m", 15, 130);
    my_lcd.Print_String("n o p q r s t u v w x y z", 15, 160);
    my_lcd.Print_String("A B C D E F G H I J K L M", 15, 190);
    my_lcd.Print_String("N O P Q R S T U V W X Y Z", 15, 220);
 
    my_lcd.Set_Text_colour(CYAN);
    my_lcd.Set_Text_Size(1);
    my_lcd.Print_String("0 1 2 3 4 5 6 7 8 9", 183, 255);
    my_lcd.Set_Text_colour(WHITE);
    my_lcd.Set_Text_Size(2);
    my_lcd.Print_String("0 1 2 3 4 5 6 7 8 9", 126, 265);
    my_lcd.Set_Text_colour(MAGENTA);
    my_lcd.Set_Text_Size(3);
    my_lcd.Print_String("0 1 2 3 4 5 6 7 8 9", 69, 285);  
    //display 1 times string
    delay(2000);
    my_lcd.Set_Rotation(0);
    my_lcd.Fill_Screen(0x0000);
    my_lcd.Set_Text_colour(RED);
    my_lcd.Set_Text_Back_colour(BLACK);
    my_lcd.Set_Text_Size(1);
    my_lcd.Print_String("EXPO LPT!", 0, 0);
    my_lcd.Print_Number_Float(01234.56789, 2, 0, 8, '.', 0, ' ');  
    my_lcd.Print_Number_Int(0xDEADBEF, 0, 16, 0, ' ',16);
    //my_lcd.Print_String("DEADBEF", 0, 16);
 
    //display 2 times string
    my_lcd.Set_Text_colour(GREEN);
    my_lcd.Set_Text_Size(2);
    my_lcd.Print_String("EXPO LPT!", 0, 40);
    my_lcd.Print_Number_Float(01234.56789, 2, 0, 56, '.', 0, ' ');  
    my_lcd.Print_Number_Int(0xDEADBEF, 0, 72, 0, ' ',16);
    //my_lcd.Print_String("DEADBEEF", 0, 72);
 
    //display 3 times string
    my_lcd.Set_Text_colour(BLUE);
    my_lcd.Set_Text_Size(3);
    my_lcd.Print_String("EXPO LPT!", 0, 104);
    my_lcd.Print_Number_Float(01234.56789, 2, 0, 128, '.', 0, ' ');  
    my_lcd.Print_Number_Int(0xDEADBEF, 0, 152, 0, ' ',16);
   // my_lcd.Print_String("DEADBEEF", 0, 152);
 
    //display 4 times string
    my_lcd.Set_Text_colour(WHITE);
    my_lcd.Set_Text_Size(4);
    my_lcd.Print_String("EXPO LPT!", 0, 192);
 
    //display 5 times string
    my_lcd.Set_Text_colour(YELLOW);
    my_lcd.Set_Text_Size(5);
    my_lcd.Print_String("EXPO LPT!", 0, 224);
 
    //display 6 times string
    my_lcd.Set_Text_colour(CYAN);
    my_lcd.Set_Text_Size(6);
    my_lcd.Print_String("EXPO LPT!", 0, 266);
 
    //display 7 times string
    my_lcd.Set_Text_colour(RED);
    my_lcd.Set_Text_Size(7);
    my_lcd.Print_String("EXPO LPT!", 0, 315);
 
    //display 8 times string
    my_lcd.Set_Text_colour(MAGENTA);
    my_lcd.Set_Text_Size(8);
    my_lcd.Print_String("EXPO LPT!", 0, 372);
    delay(2000);
    my_lcd.Fill_Screen(0x0000);

    
    for(i = 0;i<FILE_NUMBER;i++)
    {
       bmp_file = SD.open(file_name[i]);
       if(!bmp_file)
       {
            my_lcd.Set_Text_Back_colour(BLUE);
            my_lcd.Set_Text_colour(WHITE);    
            my_lcd.Set_Text_Size(1);
            my_lcd.Print_String("didnt find BMPimage!",0,10);
            while(1);
        }
        if(!analysis_bpm_header(bmp_file))
        {  
            my_lcd.Set_Text_Back_colour(BLUE);
            my_lcd.Set_Text_colour(WHITE);    
            my_lcd.Set_Text_Size(1);
            my_lcd.Print_String("bad bmp picture!",0,0);
            return;
        }
          draw_bmp_picture(bmp_file);
         bmp_file.close();
         delay(2000);
     }
}
[/code]


Une petite vidéo pour illustrer:



A vous de jouer!