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.
1. 2 płytki ESP8266
2. matryca led 16x16
3. 6 guzików
4. 2 kable USB typu b
5. 2 PowerBanki (opcjonalnie)
komputer
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.
#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)