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.
1. ESP8266 (NodeMCU)
2. płytka stykowa
3. przewody
4.Matryca LED 16x16 pikseli
5. komputer PC z Thonny
6. *opcjonalna obudowa
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
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