Skocz do zawartości

Micropython na ESP8266


deshipu

Pomocna odpowiedź

Poprowadziłem ostatnio warsztaty z programowania modułów ESP8266 za pomocą Micropythona i pomyślałem, że być może czytelnicy tego forum także chętnie by się z tym tematem zapoznali, zatem publikuję tutaj swoje notatki.

Chip ESP8266, wykorzystywany w całej rodzinie modułów, pierwotnie miał służyć jako prosty i tani (poniżej trzech dolarów) sposób na połączenie innych urządzeń (takich jak Arduino) poprzez sieć WiFi. Dlatego też domyślnie wgrany firmware pozwala na sterowanie modułem poprzez port szeregowy za pomocą komend AT, podobnych do tych używanych w modemach czy modułach Bluetooth. Jednak zmieniło się to kiedy hobbyści zdali sobie sprawę z tego, że domyślny firmware łatwo można wymienić na swój własny kod, a mikrokontroller potrzebny do obsługi protokołów sieci bezprzewodowej jest wielokrotnie silniejszy od tego w Arduino. Powstała cała gama alternatywnych firmware-ów, od prostych modyfikacji dodających tylko nowe komendy AT, poprzez interpretery pozwalające na programowanie modułów w Lua, Pythonie czy JavaScript-cie, aż do rdzenia Arduino, pozwalającego na pisanie programów przy użyciu tego popularnego IDE i "języka".

Micropython, to maszyna wirtualna i interpreter Pythona, które napisane zostały specjalnie na mikrokontrolery, które jak wiemy mają znacząco mniej zasobów, niż komputery osobiste i serwery, na których zwykliśmy zazwyczaj uruchamiać nasze programy w Pythonie. Projekt ufundowany został na Kickstarterze wraz z pierwszą płytką, na której działał -- PyBoard. Jednak nie jest to jedyna platforma, na której on działa -- istnieją porty na Teensy 3.1, cc3200, a nawet 16-bitowe mikrokontrolery PIC i trwają prace nad dalszymi portami. Jednym z nich jest wersja dla ESP8266, która co prawda na dzień dzisiejszy nadal jest w stadium eksperymentalnym, nie pozwalającym na poważne użycie, ale powoli rozwija się i stabilizuje.

Aby móc pobawić się Micropythonem na ESP8266 potrzebować będziemy dowolny z dostępnych modułów, konwerter USB2TTL pracujący z napięciem 3.3V oraz kilka kabelków i może jakąś diodę świecącą z pasującym do niej opornikiem. Dla wygody warto też zaopatrzyć się w płytkę-adapter, ma którą możemy wlutować nasz moduł i łatwo do niego podłącząć nasze kabelki, bo większość modułów ma dość niestandardowe odstępy pomiędzy wyprowadzeniami.

Uruchomienie modułu jest proste. Zasilanie podłączamy do nóżki VCC oraz (najlepiej przez opornik 10kΩ) do CH_PD, masę łączymy z nóżką GND oraz (znowu najlepiej przez opornik) z GPIO15. Nóżki TX i RX łączymy na krzyż z tymi na naszym USB2TTL -- to znaczy RX podłączamy do TX, a TX do RX. Dodatkowo, aby wgrać nowy firmware, musimy zabootować moduł w trybie flashowania poprzez podłączenie nóżki GPIO0 do masy -- połączenie to usuniemy gdy firmware będzie już wgrany i będziemy chcieli, aby moduł wykonywał nasz program.

Do wgrania firmware-u polecam narzędzie esptool.py, które działa zarówno pod Linuksem, Maczkiem jak i Windowsem. Ale zanim będziemy mogli go wgrać, to musimy nasz firmware skompilować. Zamiast się powtarzać, odeślę po prostu do doskonałego tutoriala opisanego na Adafruit. Co prawda przykłady użycia na końcu są już nieaktualne, ale instrukcje kompilacji i wgrania firmware-u jak najbardziej działają. Jeśli ktoś jest leniwy, to może skorzystać z firmware-u, który sam skompilowałem do warsztatów, aczkolwiek niedługo będzie on już nieaktualny. Wgrać go możemy następującą komendą (użytkownicy Windowsa i Maka muszą podać tu inną nazwę portu szeregowego, tak jak jest on wykrywany na ich komputerach):

python esptool.py --port /dev/ttyUSB0 write_flash 0x0 firmware-combined.bin

Następnie odłączamy moduł od komputera, usuwamy kabelek łączący GPIO0 z masą, podłączamy ponownie i uruchamiamy konsolę na porcie szeregowym:

screen /dev/ttyUSB0 115200

Po naciśnięciu entera powinniśmy zobaczyć prompt pythonowej konsoli, czyli ">>>". Możemy wykonać nasz pierwszy pythonowy program:

print("Hello world!")

No dobra, ale skoro to jest moduł sieci bezprzewodowej, to fajnie by było móc się do jakiejś sieci podłączyć. Możemy to zrobić następującym kodem:

import esp
import network

esp.wifi_mode(esp.STA_MODE)
wlan = network.WLAN()
wlan.connect('ssid', 'pass')

(Oczywiście 'ssid' zastępujemy nazwą naszej sieci, a 'pass' hasłem do niej.) Status połączenia możemy sprawdzić przy pomocy:

wlan.status()

Liczba 5 oznacza poprawne połączenie. Kod ten wykonać musimy tylko raz, gdyż nasz moduł zapamiętuje do 5 ostatnich sieci, do których był podłączony i łączy się z nimi ponownie przy uruchomieniu. Spróbujmy teraz połączyć się z jakimś serwerem i pobrać z niego dane. Wykorzystamy lekko zmodyfikowany przykład z Adafruit:

import esp

socket = esp.socket()
socket.onrecv(print)
socket.connect(('207.58.139.247', 80))
socket.send('GET /testwifi/index.html HTTP/1.0\r\n\r\n')

Powinniśmy zobaczyć zawartość strony, wypisaną na konsoli przez funkcję "print", którą podłączyliśmy jako callback. Oczywiście jeślibyśmy chcieli zrobić coś bardziej sensownego z tymi danymi, to podłączylibyśmy tam własną funkcję.

Spróbujmy teraz sprzętowego odpowiednika "hello world", czyli migania diodą świecącą. Odłączamy nasz moduł od komputera i podłączamy do niego diodę świecącą w szeregu z opornikiem, pomiędzy nóżkami GND a GPIO4. Następnie podłączamy ponownie, uruchamiamy konsole i wpisujemy:

import pyb

pin = pyb.Pin(4, pyb.Pin.OUT_PP)
for i in range(10):
   pin.value(1)
   pyb.delay(500)
   pin.value(0)
   pyb.delay(500)

Nasza dioda powinna zamrugać dziesięc razy. Zatem możemy użyć naszego modułu do sterowania prostymi urządzeniami.

Następny krok to uruchomienie serwera czekającego na połączenia. Żeby to zrobić, najpierw napiszemy sobie prostego klienta sieciowego, podobnego do linuksowego narzędzia "nc". Zapiszmy następujący kod do pliku "nc.py":

import select
import socket
import sys

def console(sock):
   sock.setblocking(False)
   poll = select.poll()
   poll.register(sock, select.POLLIN)
   poll.register(sys.stdin, select.POLLIN)
   while True:
       for ready, event in poll.poll():
           if ready == sock.fileno():
               while True:
                   try:
                       buffer = sock.recv(4096)
                   except IOError:
                       break
                   if not buffer:
                       return
                   sys.stdout.write(buffer)
           else:
               sock.sendall(sys.stdin.readline())

if __name__ == '__main__':
   if len(sys.argv) == 2:
       server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       server.bind(('0.0.0.0', int(sys.argv[1])))
       server.listen(1)
       sock, address = server.accept()
       print "Connection from {}.".format(address)
   elif len(sys.argv) == 3:
       sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       sock.connect((sys.argv[1], int(sys.argv[2])))
       print "Connected to {}:{}.".format(*sock.getpeername())
   else:
       print "Usage: {} [address] port".format(sys.argv[0])
   console(sock)

Bez zbędnego wnikania w szczegóły, nasze narzędzie pozwala otworzyć nam socket i wpisywać oraz odbierać dane interaktywnie. Uruchamiamy je w trybie nasłuchiwania na porcie 4242:

python nc.py 4242

A następnie łączymy się z nim z naszego modułu:

import esp

socket = esp.socket()
socket.onrecv(print)
socket.connect(('tutaj.adres.naszego.komputera', 4242))
socket.send('hello\n')

Powinniśmy zobaczyć informację o połączeniu, oraz być w stanie wysyłać dane w obie strony. Zamknijmy teraz połączenie od strony modułu za pomocą komendy:

socket.close()

Uruchomimy teraz na naszym module serwer:

import esp

def recv(socket, data):
   print(data)

socket = esp.socket()
socket.onconnect(lambda s: s.onrecv(recv))
socket.bind(('0.0.0.0', 4242))
socket.listen(1)

A następnie połączymy się z nim z naszego komputera:

python nc.py tutaj.adres.naszego.modulu 4242

I tak jak poprzednio, znowu możemy przesyłać dane. Ale jakie dane mielibyśmy przesyłać? Prawdopodobnie dane z czujników. Zróbmy zatem serwer, który powie nam czy coś jest podłączone do nóżki GPIO4, czy nie:

import esp
import pyb

pin = pyb.Pin(4, pyb.Pin.PULL_UP)

def recv(socket, data):
   if pin.value():
       socket.send('disconnected')
   else:
       socket.send('connected')

socket = esp.socket()
socket.onconnect(lambda s: s.onrecv(recv))
socket.bind(('0.0.0.0', 2323))
socket.listen(1)

Teraz odłączając i podłączając diodę swięcącą (albo po prostu kabelek) do nóżki GPIO4 łączymy się z naszym serwerem i dostajemy informację o jej aktualnym stanie.

To tyle materiału, jeśli chodzi o te warsztaty. Niestety port ESP8266 jest dziś na tyle ubogi, że niewiele więcej da się zrobić -- do poważniejszych zastosowań polecam firmware nodemcu lub programowanie za pomocą Arduino. Mam jednak nadzieję, że pobudziłem ciekawość i zachęciłem do dalszych eksperymentów.

Link do komentarza
Share on other sites

Trochę wody upłynęło od kiedy napisałem ten artykuł i trochę się od tego czasu pozmieniało.

Na początku roku autorzy Micropythona urządzili kampanię na Kickstarterze, w czasie której zebrali fundusze na przepisanie i ulepszenie portu dla ESP8266. Od tego czasu trwają prace nad nową wersją i zostało wprowadzonych bardzo dużo ulepszeń. Wydana niedawno wersja 1.8.1 nadaje się już w zasadzie dla każdego robotyka.

Co jest dostępne możemy zobaczyć w dokumentacji na http://micropython.org/resources/docs/en/latest/esp8266/esp8266/quickref.html

Mamy zatem obsługę sieci WiFi zarówno w trybie stacji jak i punktu dostępowego, wraz z autoryzacją WEP i WPA. Mamy sockety działające tak jak na "dużych" komputerach, bez callbacków. Obsługa HTTP i HTTPS.

Są timery, PWM, zegar czasu rzeczywistego (wraz z obsługą NTP), usypianie, konwerter analogowo-cyfrowy, software-owe I2C, OneWire i SPI (sprzętowe SPI powinno pojawić się wkrótce).

Do tego mamy wbudowane biblioteki do obsługi DHT11/22, Neopixeli (czyli WS2812 i APA102), wyświetlaczy OLED (SSD1306) i wielu innych.

Nic tylko brać i montować w robotach!

Link do komentarza
Share on other sites

Zainteresowałem się ostatnio micropythonem dla ESP, udało mi się wrzucić firmware, ładnie po COMie odpowiada i działa. Tylko mam problem z wrzuceniem własnych skryptów do ESP, na stałe.

Wiem, że powinny być w plikach boot.py lub main.py, ale nie wiem jak je tam umieścić na stałe.

Nie wiem czy dobrze rozumiem dokumentacje. Jakieś wskazówki?

Może ktoś to robił z powodzeniem?

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

No i właśnie po komendzie

ampy --port COM9 put main.py

wyskakuje:

Traceback (most recent call last):
 File "C:\Users\Piotrek\AppData\Local\Programs\Python\Python36-32\Scripts\ampy-script.py", line 11, in <module>
   load_entry_point('adafruit-ampy==1.0.3', 'console_scripts', 'ampy')()
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\click\core.py", line 722, in __call__
   return self.main(*args, **kwargs)
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\click\core.py", line 697, in main
   rv = self.invoke(ctx)
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\click\core.py", line 1066, in invoke
   return _process_result(sub_ctx.command.invoke(sub_ctx))
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\click\core.py", line 895, in invoke
   return ctx.invoke(self.callback, **ctx.params)
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\click\core.py", line 535, in invoke
   return callback(*args, **kwargs)
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\ampy\cli.py", line 213, in put
   board_files.put(remote, infile.read())
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\ampy\files.py", line 137, in put
   self._pyboard.exec_("f = open('{0}', 'wb')".format(filename))
 File "c:\users\piotrek\appdata\local\programs\python\python36-32\lib\site-packages\ampy\pyboard.py", line 265, in exec_
   raise PyboardError('exception', ret, ret_err)
ampy.pyboard.PyboardError: ('exception', b'', b'Traceback (most recent call last):\r\n  File "<stdin>", line 1, in <module>\r\nOSError: [Errno 1] EPERM\r\n')
Link do komentarza
Share on other sites

Na "niebudowlanym systemie" to samo. Na Raspbianie bo w chwili obecnej nic innego nie mam.

Jak więc zdobyć prawa dostępu do ESP? Najnowszy bin po wgraniu krzaczy w terminalu na każdych nawet bardziej nietypowych prędkościach. Na poprzednim wsadzie działa ale wyskakuje EPERM.

Link do komentarza
Share on other sites

Panowie ( i Panie ale tu niema to samo Panowie )

Próbowałem pod Windowsem bo mam Arduino i trochę na kadziłem 🙂 w Pythonie i chciałem te umiejętności połączyć w jedną całość bo idzie

W środowisku Arduino mam wszystko działające jeśli chodzi o programowanie Wemos d1 miniv3.0 (w cpp  )

czyli:

Cytat

C:\Users\Nieprawdziwa_nazwa_użytkownika\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2/tools/upload.py --chip esp8266 --port COM8 --baud 115200 --trace version --end --chip esp8266 --port COM8 --baud 115200 --trace write_flash 0x0 C:\micropython\esp8266-20190125-v1.10.bin --end

Wgrywam i miga mi dioda a w Programie Terminal na porcie  COM8 mam same krzaczki. ( wygląda na to że tak ma być ) ( odpowiada to "uruchamiamy konsolę na porcie szeregowym:")

Płytka ma w sobie programator czyli nie musiałem "moduł w trybie flashowania poprzez podłączenie nóżki GPIO0 do masy"

Co dalej ? 

Ps Kod mi zadziałał tylko raz za drugim razem mam takie krzaczki że szuka mi pythona i td ..

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.