DIY

Bitmap Photo Frame Using Raspberry Pi Pico

Photo frame with a raster image using Raspberry Pi Pico  Bitmap photo frame using Raspberry Pi Pico In this short article, we'll learn how to make a photo frame using a Raspberry Pi LCD. Images stored in the Raspberry Pi's internal memory are displayed on the LCD screen. The Raspberry Pi uses Python to implement file reading and bitmap processing functions.
To make a photo frame, the following materials are required:
-Raspberry Pi Pico; -3.5-inch (320×480) LCD HVGA TFT (ILI9488); – Development board; -Connecting wires; -Computer; -Micro USB cable; < br> Photo frame with a bitmap with using Raspberry Pi Pico About Raspberry and LCDs < br>The Raspberry Pi Pico is a small, fast and versatile board built using the RP2040, equipped with a dual-core Arm Cortex-M0 + processor with 264KB internal RAM and support for up to 16MB of external flash. It provides a wide range of I/O options including I2C, SPI, and unique programmable I/O (GPIO) pins.
Nowadays, beautiful TFT LCD screens are getting cheaper and their use in embedded design makes them more user-friendly. This guide explains how to connect a 3.5 inch TFT LCD 320×480 with ILI9488 driver and SPI interface to Raspberry Pi Pico.
Wiring Diagram
LCD easily connects to the bus RPi Pico SPI, and requires a minimum of four digital I/O lines.
ILI9488 LCD controller is a 16.7MB SoC single-chip Si-TFT LCD driver with 320 (RGB) x 480 dots resolution.
ILI9488 consists of 960-channel source driver, 480-channel gate driver, 345,600 bytes of built-in GRAM for 320 (RGB) (H) x 480 (V) x 18 dots graphic data.
LCD works at logic voltage 3.3 V.
ILI9488 supports 8-color display and sleep mode power management functions. It is ideal for portable devices where battery saving is required, such as digital cell phones, smartphones, MP3 players, personal media players and similar devices with color graphic displays.
RPi Pico SPI port connects to LCD (GPIO6 – SCLK and GPIO7 – MOSI).
RPi Pico pins GPIO GPIO0, GPIO1 and GPIO2 connect to CS, RST and DC RS pins of TFT LCD.
 Bitmap photo frame using Raspberry Pi Pico Bitmap header and image file management
All integer values ​​in a bitmap file are stored in big endian format. The first 2 bytes of the BMP file format are the ASCII character “B” followed by the “M” character.
The next 4 bytes (0x02 to 0x05) of the BMP file indicate the file size. The next 4 bytes (0x05 to 0x09) of the BMP file are reserved.
4 bytes (0x0A to 0x0D) BMP file, contains the offset, that is, the starting byte address in which the bitmap data (pixel array) can be found. 4 bytes (0x0E to 0x11) of the BMP file provide the header size. < br> The next 2 bytes (0x12 to 0x13) of the BMP file contain the width of the BMP image in pixels. 2 bytes (0x14 to 0x15) provide the height of the BMP image in pixels.
2 bytes (0x16 to 0x17) of the file contain the number of color planes.
The next 2 bytes (0x18 to 0x19) of the BMP file contain the number of bits per pixel. Since TFT 320×480 (ILI9488) supports RGB565 and flash memory is limited, you need to convert BMP files to RG565 (16-bit format) and resize the image to 480 in width, 320 in height or less.
Approximate BMP file size with a 480×320 image – 300 KB. (480x320x2 = 307200 bytes + header size)
RPi Pico provides 2 MB of disk space. MicroPython uses about 600KB. 1.4 MB of flash memory is available for storing bitmap files.
You can use GIMP to convert the file.
Processing bitmap files
Open RPi Pico as a disk and then copy the bitmap files to the root directory.
timer_one is initialized and invokes a “BlinkLED” callback to toggle the built-in LED with a duration of 500 ms. (frequency = 1)
The TFT LCD class provides basic firmware functions such as Init, ResetDevice, WriteDevice, WriteDataToDevice, WriteBlock, and FillRectangle.
The python program initializes the ILI9433 TFT LCD with the SPI interface.
The python program reads the bitmap files and views one by one at 3 second intervals.
 Bitmap photo frame using Raspberry Pi Pico The code with comments can be downloaded below.

 & # 39; & # 39; & # 39; Demonstrates the use of 320x480 HVGA TFT (ILI9488) TFT, initialization and internal flash photo frame application Draw Bitmap files (BMP) on screen * The Raspberry Pi Pico pin connections for TFT is given below & # 58; # TFT Power Pins * TFT VCC pin to 3V3 * TFT GND pin to GND # TFT SPI Pins * TFT SCLK pin to GPIO6 * TFT MOSI pin to GPIO7 * TFT CS pin to GPIO0 # TFT Control Pins * TFT RST pin to GPI01 * TFT RS  DC pin to GPIO2 Name & # 58; - M.Pugazhendi Date & # 58; - 24thAug2021 Version & # 58; - V0.1 e-mail & # 58; - [email protected] & # 39; & # 39; & # 39;  

  from micropython import const from machine import Pin, SPI import time, os, ustruct  

 READ_DISPLAY = const (0x0f); SLEEP_OUT = const (0x11); GAMMA_SET = const (0x26); DISPLAY_ON = const (0x29) COLUMN_ADDRESS_SET = const (0x2a); P_ADDRESS_SETAGE = const (0x2b = const); RAM_WITE2b = const const (0x2e) MEMORY_ACCESS_CONTROL = const (0x36); VER_SCROLL_ADDRESS = const (0x37); NEG_GAMMA_CONTROL = const (0xe1) PIXEL_FORMAT_SET = const (0x3a); POWER_CONTROL_bCA = const (0x3a); POWER_CONTROLx_CA = const ; DRIVER_TIMING_CONTROL_B = const (0xea); POWER_ON_CONTROL = const (0xed) PUMP_RATIO_CONTROL = const (0xf7); POWER_CONTROL_1 = const (0xc0); POWER_CONTROL_2 = const (0xc1) VCOM_CONTROL_1 = const (0xc5); VCOM_CONTROL_2 = const (0xc7); FRAME_RATE_CONTROL = const (0xb2) DISPLAY_FUNCTION_CONTROL = const (0xb6); ENABLE_3G = const (0xf2); POS_GAMMA_CONTROL = const (0xe0)  

 MEMORY_BUFFER = const (1024) # SPI Write Buffer  

 class ILI9488 & # 58; def __init __ (self, spi, cs, dc, rst, w, h, r) & # 58; self.spi = spi; self.cs = cs; self.dc = dc; self.rst = rst self.init_width = w; self.init_height = h self.width = w; self.height = h; self.rotation = r self.cs.init (self.cs.OUT, value = 1); self.dc.init (self.dc.OUT, value = 0) self.rst.init (self.rst.OUT, value = 0) self.ResetDevice () self.Init () self.buffer = bytearray (MEMORY_BUFFER * 2) self.color_map = bytearray (b & # 39;  x00  x00  xFF  xFF & # 39;) #default white foregraound, black background self .screen_x = 0; self.screen_y = 0 def SetPosition (self, x, y) & # 58; self.screen_x, self.screen_y = x, y  

 def Init (self) & # 58; for command, data in ((READ_DISPLAY, b & # 34;  x03  x80  x02 & # 34;), (POWER_CONTROL_B, b & # 34;  x00  xc1  x30 & # 34;), (POWER_ON_CONTROL, b & # 34;  x64  x03  x12  x81 & # 34;), (DRIVER_TIMING_CONTROL_A, b & # 34;  x85  x00  x78 & # 34;), (POWER_CONTROL_A, b & # 34;  x39  x2c  x00  x34  x02 & # 34; ), (PUMP_RATIO_CONTROL, b & # 34;  x20 & # 34;), (DRIVER_TIMING_CONTROL_B, b & # 34;  x00  x00 & # 34;), (POWER_CONTROL_1, b & # 34;  x23 & # 34;), (& POWER_CON # 34;  x10 & # 34;), (VCOM_CONTROL_1, b & # 34;  x3e  x28 & # 34;), (VCOM_CONTROL_2, b & # 34;  x86 & # 34;)) & # 58; self.WriteDevice (command, data)  

 if self.rotation == 0 & # 58; # 0 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  x48 & # 34;) self.width, self.height = self.init_height, self.init_width elif self.rotation == 1 & # 58; # 90 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  x28 & # 34;) self.width, self.height = self.init_width, self.init_height elif self.rotation == 2 & # 58; # 180 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  x88 & # 34;) self.width, self.height = self.init_height, self.init_width elif self.rotation == 3 & # 58; # 270 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  xE8 & # 34;) self.width, self.height = self.init_width, self.init_height elif self.rotation == 4 & # 58; # Mirrored + 0 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  xC8 & # 34;) self.width, self.height = self.init_height, self.init_width elif self.rotation == 5 & # 58; # Mirrored + 90 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  x68 & # 34;) self.width, self.height = self.init_width, self.init_height elif self.rotation == 6 & # 58; # Mirrored + 180 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  x08 & # 34;) self.width, self.height = self.init_height, self.init_width elif self.rotation == 7 & # 58; # Mirrored + 270 deg self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  xA8 & # 34;) self.width, self.height = self.init_width, self.init_height else & # 58; self.WriteDevice (MEMORY_ACCESS_CONTROL, b & # 34;  x08 & # 34;)  

 for command, data in ((PIXEL_FORMAT_SET, b & # 34;  x55 & # 34;), (FRAME_RATE_CONTROL, b & # 34;  x00  x18 & # 34;), (DISPLAY_FUNCTION_CONTROL, b & # 34;  x02  x02  x3B & # 34;), (ENABLE_3G, b & # 34;  x00 & # 34;), (GAMMA_SET, b & # 34;  x01 & # 34;), (POS_GAMMA_CONTROL, b & # 34;  x0f  x31  x2b  x0c  x0e  x08  x4e  xf1  x37  x07  x10  x03  x0e  x09  x00 & # 34;), (NEG_GAMMA_CONTROL, b & # 34;  x00  x0e  x14  x03  x11  x07  x31  xc1  x48  x08  x0f  x0c  x31  x36  x0f & # 34;)) & # 58; self.WriteDevice (command, data) self.WriteDevice (SLEEP_OUT) time.sleep_ms (120) self.WriteDevice (DISPLAY_ON)  

  def ResetDevice (self) & # 58; self.rst (0); time.sleep_ms (50); self.rst (1); time.sleep_ms (50)  

  def WriteDevice (self, command , data = None) & # 58; self.dc (0) self.cs (0) self.spi.write (bytearray (& # 91; command & # 93;)) self.cs (1) if data is not None & # 58; self.WriteDataToDevice (data)  

 def WriteDataToDevice (self, data) & # 58; self.dc (1); self.cs (0); self.spi.write (data); self.cs (1)  

  def WriteBlock (self , x0, y0, x1, y1, data = None) & # 58; self.WriteDevice (COLUMN_ADDRESS_SET, ustruct.pack (& ​​# 34; & gt; HH & # 34 ;, x0, x1)) self.WriteDevice (PAGE_ADDRESS_SET, ustruct.pack (& ​​# 34; & gt; HH & # 34 ;, y0, y1 )) self.WriteDevice (RAM_WRITE, data)  

 def FillRectangle (self, x, y, w, h, color = None) & # 58; x = min (self.width - 1, max (0, x)); y = min (self.height - 1, max (0, y)) w = min (self.width - x, max (1, w )); h = min (self.height - y, max (1, h)) if color & # 58; color = ustruct.pack (& ​​# 34; & gt; H & # 34 ;, color) else & # 58; color = self.color_map & # 91; 0 & # 58; 2 & # 93; #background for i in range (MEMORY_BUFFER) & # 58; self.buffer & # 91; 2 * i & # 93; = color & # 91; 0 & # 93 ;; self.buffer & # 91; 2 * i + 1 & # 93; = color & # 91; 1 & # 93; chunks, rest = divmod (w * h, MEMORY_BUFFER) self.WriteBlock (x, y, x + w - 1, y + h - 1, None) if chunks & # 58; for count in range (chunks) & # 58; self.WriteDataToDevice (self.buffer) if rest! = 0 & # 58; mv = memoryview (self.buffer) self.WriteDataToDevice (mv & # 91; & # 58; rest * 2 & # 93;) #Initialize the onboard LED as output led = machine.Pin (25, machine.Pin.OUT)  

  # Toggle LED funtionality def BlinkLED (timer_one) & # 58; led.toggle ()  

 # https & # 58; //forum.micropython.org/viewtopic.php?t=1420 Roberthh @ micropython.asm_thumb def reverse (r0, r1) & # 58; # bytearray, len (bytearray) b (loopend) label (loopstart) ldrb (r2, & # 91; r0, 0 & # 93;) ldrb (r3, & # 91; r0, 1 & # 93;) strb (r3, & # 91; r0, 0 & # 93;) strb (r2, & # 91; r0, 1 & # 93;) add (r0, 2) label (loopend) sub (r1, 2) # End of loop? bpl (loopstart)  

  SCR_WIDTH, SCR_HEIGHT, SCR_ROT = const (480), const (320), const (5)  

< br>

  TFT_CLK_PIN, TFT_MOSI_PIN, TFT_MISO_PIN, TFT_CS_PIN = const (6), const (7), const (4), const (0) TFT_RST_PIN, TFT_DC_PIN = const (1), const (2)  

 spi = SPI (0, baudrate = 40000000, miso = Pin (TFT_MISO_PIN), mosi = Pin (TFT_MOSI_PIN), sck = Pin (TFT_CLK_PIN)) display = ILI9488 (spi, cs = Pin (TFT_CS_PIN), dc_DCPINPIN) , rst = Pin (TFT_RST_PIN), w = SCR_WIDTH, h = SCR_HEIGHT, r = SCR_ROT)  

  display.SetPosition (0,0); display.FillRectangle ( 0,0,480,320,0xBDF7)  

  # Read files. bitmap_image_files = os.listdir (& # 34;/& # 34;)  

 #Initialize timer_one. Used for toggling the on board LED timer_one = machine.Timer () #Timer one initialization for on board blinking LED at 500mS interval timer_one.init (freq = 1, mode = machine.Timer.PERIODIC, callback = BlinkLED)  

 # Opens bitmap file. Displays the file @ 3 Sec interval while True & # 58; for x in range (len (bitmap_image_files)) & # 58; # Open file f = open (bitmap_image_files & # 91; x & # 93;, & # 39; rb & # 39;) # Check if it bitmap file if f.read (2) == b & # 39; BM & # 39; & # 58; #header dummy = f.read (8) #file size (4), creator bytes (4) offset = int.from_bytes (f.read (4), & # 39; little & # 39;) hdrsize = int.from_bytes ( f.read (4), & # 39; little & # 39;) width = int.from_bytes (f.read (4), & # 39; little & # 39;) height = int.from_bytes (f.read (4) , & # 39; little & # 39;) MEM_SIZE = 5 * 1024 x = (SCR_WIDTH/2) - (width/2) y = (SCR_HEIGHT/2) - (height/2) if ((width * height * 2) & gt; MEM_SIZE) & # 58; no_of_read_buffer, balance_memory_size = (width * height * 2)/MEM_SIZE, (width * height * 2)% MEM_SIZE else & # 58; no_of_read_buffer = 0 balance_memory_size = (width * height * 2) x = int (x) y = int (y) no_of_read_buffer = int (no_of_read_buffer) balance_memory_size = int (balance_memory_size)  

 if (no_of_read_buffer == 0) & # 58; display.WriteBlock (x, y, x + width - 1, y + height - 1, None) dummy = f.seek (offset) buf = f.read (width * height * 2) reverse (buf, width * height * 2) display.WriteDataToDevice (buf) time.sleep (5) else & # 58; if (width% 2 == 0x00) & # 58; display.WriteBlock (x, y, x + width-1, y + height - 1, None) else & # 58; display.WriteBlock (x, y, x + width, y + height - 1, None)  

 for i in range (no_of_read_buffer) & # 58; p = offset + (i * MEM_SIZE) dummy = f.seek (p) buf = f.read (MEM_SIZE) reverse (buf, MEM_SIZE) display.WriteDataToDevice (buf) p = offset + (no_of_read_buffer * MEM_SIZE) dummy = f. seek (p) buf = f.read (balance_memory_size) reverse (buf, balance_memory_size) display.WriteDataToDevice (buf) time.sleep (3) # Close file f.close () display.FillRectangle (0,0,480,320,0xBDF7)  

Photo frame with a bitmap using Raspberry Pi Pico  Bitmap photo frame using Raspberry Pi Pico

Source:

usamodelkina.ru

Show More

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button