Gra na NeoPixel 16x16

Typ_projektu
microPython
Krótki opis projektu

Projekt zrealizowany w ramach zaliczenia przedmiotu "techniki mikroprocesorowe 2" na 5 semestrze studiów na kierunku Robotyki i Automatyki, wydziału Mechanicznego Energetyki i Lotnictwa Politechniki Warszawskiej.

Autor: Stanisław Walczak

Projekt obejmuje sterowanie 6 guzikami za pomocą jednej płytki, obliczanie i wyświetlanie gry za pomocą drugiej oraz łączność pomiędzy tymi dwoma płytkami za pomocą espnow.

Projekt realizowany w języku micropython.

Niezbędne elementy

1. 2 płytki ESP8266

2. matryca led 16x16

3. 6 guzików

4. 2 kable USB typu b

5. 2 PowerBanki (opcjonalnie)

Sprzęt

komputer

Opis projektu

Gra polega na unikaniu różnego rodzaju obiektów: piorunów, śnieżek i serii pocisków.
Gracz steruje pixelem w kolorze magenta za pomocą przycisków lewo, prawo góra, dół.
Za pomocą przycisku B można zrestartować grę, natomiast za pomocą przycisku A zacząć grę.

Największym problemem jaki napotkałem podczas projektu było przesyłanie informacji o wciśnięciu przycisków pomiędzy płytkami esp8266 za pomocą espnow.


Dużą pomocą okazała się strona "Arduino dla strasznych lamerów" (1. odnośnik w odnośnikach zewnętrznych) oraz pomoc sztucznej inteligencji.
Należy wiedzieć tutaj o kilku bardzo ważnych rzeczach.
Po pierwsze: w linijce 15 dla nadajnika należy wpisać adres mac odbiornika.
W tym celu należy na odbiorniku odpalić następujący program:

 

import network # Utwórz obiekt interfejsu Wi-Fi w trybie stacji (STA)
sta_if = network.WLAN(network.STA_IF)

# Upewnij się, że tryb Wi-Fi jest aktywny

if not sta_if.active():
    sta_if.active(True)

# Pobierz adres MAC
mac = sta_if.config('mac')

# Wyświetl adres MAC w formacie czytelnym dla człowieka
print('Adres MAC:', ':'.join(['{:02X}'.format(b) for b in mac]))

 

Jesli otrzymany adres mac będzie przykładowo:

bb:bb:bb:bb:bb

To do nadajnika należy wpisać adres mac w formacie:

\xbb\xbb\xbb\xbb\xbb\xbb

 

Po drugie: należy się upewnić, że nadajnik i odbiornik łączą się z tą samą siecią. W tym celu należy na odbiorniku i na nadajniku jednorazowo odpalić następujący program:

wlan = network.WLAN(network.STA_IF)
wlan.config(channel=1) # Ustaw kanał na 1 (lub inny)

 

Po trzecie: żeby wysyłać i odbierać stany 6 przycisków, należy użyć funkcji list()

button_states = list(msg)

Gdzie msg to odebrana informacja od nadajnika, a button_states to nazwa własna zmiennej, może być dowolna inna.

Stany guzików należy wysyłać w postaci bytes(data), gdzie data to stany guzików.

 

Kolejnym problemem okazało się  wysyłanie stanu jednego z guzików.
Okazuje się, że jeden z guzików jest na stałe przylutowany do pinu 16, kótry obsługuje wbudowaną diodę led.
Oznacza to tyle, że nie można odczytać jej stanu za pomocą funkcji:

machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)

Można natomiast sprawdzić, czy wbudowana w płytkę dioda jest zapalona, czy zgaszona, za pomocą funkcji:

machine.Pin(16, machine.Pin.OUT)


Ostatnim problemem, o którym chciałbym wspomnieć, był problem z resetowaniem programu. Próbowałem robić grę w jednej wielkiej pętli, jednak po każdym resecie gra wyraźnie zwalniała. Próbowałem funkcji resetującej program zaproponowanej przez A.I. jednak z tym samym skutkiem.

Rozwiązaniem okazało się użycie funkcji machine.reset(), który resetuje płytkę i przy okazji od nowa odpala program boot.py (w którym jest napisana gra).
Nie jest to najładniejsze rozwiązania, ale przede wszystkim działa.

kod programu
#boot.py nadajnika

# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
import os, machine
#os.dupterm(None, 1) # disable REPL on UART(0)
import gc
#import webrepl
#webrepl.start()
gc.collect()

import network
import espnow
import time

buttons = [2, 12, 14, 13, 0]

# Inicjalizacja pinów jako wejścia z pull-up
button_pins = [machine.Pin(pin, machine.Pin.IN, machine.Pin.PULL_UP) for pin in buttons]
led_pins= [machine.Pin(16, machine.Pin.OUT)]
# Inicjalizacja interfejsu Wi-Fi
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect()

# Inicjalizacja ESPNow
esp_now = espnow.ESPNow()
esp_now.active(True)

# Adres MAC odbiornika
receiver_mac = b'\x34\x94\x54\x95\x8b\xa0'

# Dodanie odbiornika
esp_now.add_peer(receiver_mac)

# Wysyłanie danych
esp_now.send(receiver_mac, "Starting...")

for i in range(100):
    esp_now.send(receiver_mac, str(i) * 20, True)
    time.sleep(0.1)

esp_now.send(receiver_mac, b'end')


def read_buttons():
    # Odczyt stanu przycisków (0 = naciśnięty, 1 = nienaciśnięty)
    return [1 - pin.value() for pin in button_pins ]

while True:
    # Odczyt stanów przycisków (0 = naciśnięty, 1 = nie naciśnięty)
    button_states = [1 - pin.value() for pin in button_pins]  # Odwrócenie logiki

    # Odczyt stanów diod (0 = zgaszona, 1 = zapalona)
    led_states = [1-pin.value() for pin in led_pins]

    # Połącz stany przycisków i diod w jedną listę
    data = button_states + led_states
    print("Wysyłam:", data)
    
    # Wysyłanie danych do odbiorcy
    esp_now.send(receiver_mac, bytes(data))

    time.sleep(0.1)
Youtube
Tagi
espnow micropython python neopixel esp8266
Odnośniki zewnętrzne
1. https://arduino.net.pl/index.php/esp-now-i-micropython/