Wyświetlanie obrazów Pixel Art na matrycy LED | ESP8266

Typ_projektu
microPython
Zdjecie główne
Krótki opis projektu

Celem projektu było umożliwienie wyświetlania niewielkich obrazów Pixel Art na matrycy LED 16x16 za pośrednictwem płytki ESP 8266. Napisany program umożliwia również wyświetlanie niewielkich plików GIF  - ruchomych obrazów utworzonych przez wyświetlania kolejnych klatek animacji.

Niezbędne elementy

1. ESP8266 (NodeMCU)

2. płytka stykowa

3. przewody

4.Matryca LED 16x16 pikseli

5. komputer PC z Thonny

6. *opcjonalna obudowa 

Opis projektu

Celem projektu było umożliwienie wyświetlania niewielkich obrazów Pixel Art na matrycy LED 16x16 za pośrednictwem płytki ESP 8266. Napisany program umożliwia również wyświetlanie niewielkich plików GIF  - ruchomych obrazów utworzonych przez wyświetlania kolejnych klatek animacji.

Pierwotnym założeniem projektu było zapisywanie obrazów .jpg w pamięci płytki oraz wyświetlanie ich na matrycy. Ze względu na ograniczenia wykorzystywanego urządzenia (niewielki zasoby pamięci podręcznej) konieczną okazała się zmiana formatu plików na bmp -  format pliku z grafiką bitmapową, do którego odczytu wymagany jest mniej skomplikowany proces, co z kolei pozawala na wykorzystanie mniejszych bibliotek. Operację tą wykonano za pomocą programu uruchamianego na komputerze. 

Obsługa programu:

W celu wyświetlenia wcześniej przygotowanych i wgranych na płytkę obrazów należy wywołać funkcją "jpg" lub "obrazek". Pierwsza z nich jako argument przyjmuje nazwą obrazu, który chcemy wyświetlić, druga natomiast wymaga podania nazwy z prawidłowym formatem. Należy pamiętać, że nazwy podaje się w cudzysłowach (np. "motylek"/"motylek.bmp"). Inną funkcjonalnością jest wyświetlanie gif-ów. Podobnie jak w poprzednim przypadku należy najpierw wgrać na płytkę przygotowane pliki (każdy gif to jeden folder zawierający kilka obrazów bmp). W celu wywołania funkcji gif należy podać nazwę gif-a (folderu) oraz liczbę reprezentującą ile razy ma być wyświetlona sekwencja obrazów. Dodatkową opcją (wymagającą edycji kodu) jest zmiana jasności z jaką są zapalane diody  - odpowiada za to funkcja increase_saturation.

Działanie programu:

W celu przygotowanie plików do wyświetlania należy najpierw uruchomić na komputerze program obraz (dla plików jpg) lub gif (dla plików gif). W pierwszym przypadku należy wywołać funkcję convert_jpg_to_bmp, która jako argumenty przyjmuje nazwy pliku pierwotnego i oczekiwanego (przy założeniu, że obraz znajduje się w tej samej lokalizacji co program). W drugim przypadku należy wywołać funkcję gif_to_bmp, która przyjmuje takie same argumenty.

Funkcje głównego programu:

  • kart  - jej zadaniem jest wyświetlanie zadanego koloru przez diodę wskazaną za pomocą współrzędnych kartezjańskich. argumenty: współrzędna x, współrzędna y, składowa czerwona, składowa zielona, składowa niebieska
  • read_bmp - funkcja pomocnicza wykorzystywane do odczytu danych z pliku bmp. argumenty: nazwa odczytywanego pliku
  • increase_saturation - funkcja zmieniająca jasność wyświetlanego obrazu. argument: składowa czerwona, składowa zielona, składowa niebieska, współczynnik jasności
  • obrazek - funkcja pozwalająca na wyświetlenie obrazu na matrycy. argumenty: nazwa obrazu (z rozszerzeniem) -po uwzględnieniu ścieżki umożliwia wyświetlanie pojedynczych klatek plików gif
  • jpg - to samo co funkcja obrazek (nazwa nie zawiera formatu pliku).
  • display_bmp - lekko zmodyfikowana funkcja obrazek wykorzystywana w procesie wyświetlania gif-ów
  • gif  -funkcja umożliwiająca wyświetlanie gif-ów. argumenty: nazwa gif-a (bez rozszerzenia), ilość powtórzeń animacji

 

Zdjęcia
kod programu
import time
import os
from machine import Pin
from neopixel import NeoPixel
from time import sleep


pin = Pin(2, Pin.OUT)
np = NeoPixel(pin, 16*16)
# Funkcja do odczytu pliku BMP 16x16
def kart(x, y, r, g, b):
    if y%2!=1:
        z=x+16*y
        np[z] = (r, g, b) 
    else:
        z=15+16*y-x
        np[z] = (r, g, b)
    

def read_bmp(filename):
    with open(filename, "rb") as f:
        # Pomijamy nagłówek BMP (54 bajty)
        f.seek(54)
        
        # Odczytujemy dane pikseli 16x16 (3 bajty na piksel)
        data = f.read(16 * 16 * 3)  # 16x16 pikseli, każdy ma 3 bajty (RGB)
        
        return bytearray(data)  # Zwracamy kopię danych jako bytearray

# Funkcja zwiększająca nasycenie kolorów
def increase_saturation(r, g, b, factor):
    r = min(int(r * factor), 255)  # Zwiększamy nasycenie, ale ograniczamy do 255
    g = min(int(g * factor), 255)
    b = min(int(b * factor), 255)
    return r, g, b



def obrazek(nazwa):
    # Ładujemy dane BMP z pliku

    
    bmp_data = read_bmp(nazwa)

    # Pętla po pikselach i wyświetlanie na pasku LED
    for i in range(16):
        for j in range(16):
            # Indeks w danych BMP (3 bajty na piksel)
            index = (i * 16 + j) * 3
        
            # Pobieramy kolory RGB (24 bity)
            r = bmp_data[index + 2]  # Czerwony (najpierw R w BMP)
            g = bmp_data[index + 1]  # Zielony
            b = bmp_data[index]      # Niebieski
        
            # Zwiększ nasycenie kolorów
            r, g, b = increase_saturation(r, g, b, factor=1)  # Możesz zmieniać factor
        
            # Wyświetlamy kolor na pasku LED
            kart(i, j, r, g, b)
        
            # Dla debugowania (można usunąć później)
            #print(f"Pixel ({i}, {j}) - R: {r}, G: {g}, B: {b}")
    np.write()
   
    
def jpg(nazwa):
    nazwa=nazwa+".bmp"
    print(nazwa)
    obrazek(nazwa)
    
    
def display_bmp(bmp_data):
    for i in range(16):
        for j in range(16):
            # Indeks w danych BMP (3 bajty na piksel)
            index = (i * 16 + j) * 3
        
            # Pobieramy kolory RGB (24 bity)
            r = bmp_data[index + 2]  # Czerwony (najpierw R w BMP)
            g = bmp_data[index + 1]  # Zielony
            b = bmp_data[index]      # Niebieski
        
            # Zwiększ nasycenie kolorów
            r, g, b = increase_saturation(r, g, b, factor=1)  # Możesz zmieniać factor
        
            # Wyświetlamy kolor na pasku LED (funkcja `kart` obsługuje wyświetlanie na pasku LED)
            kart(i, j, r, g, b)
    np.write()
    
    
    
    
    
def gif(folder_path, ile):
    for i in range(ile):
        # Pobierz listę plików BMP w folderze, posortowaną alfabetycznie
        files = sorted([f for f in os.listdir(folder_path) if f.endswith(".bmp")])
    
        if not files:
            print("Brak plików BMP w podanym folderze.")
            return

        for file_name in files:
            file_path = folder_path + "/" + file_name
            print(f"Wyświetlam: {file_name}")
        
            # Załaduj dane pikseli z pliku BMP
            bmp_data = read_bmp(file_path)
        
            # Wyświetl obraz na pasku LED
            display_bmp(bmp_data)
        
            # Opóźnienie między klatkami
            time.sleep(0.1)
            del bmp_data
            

Youtube
Tagi
ESP8266, LED, matryca, gif, jpg