Raspberry Pi Pico W tutorial komponentów dla początkujących
Ten samouczek dotyczący komponentów Raspberry Pi Pico W dla początkujących nauczy Cię, jak współdziałać z mikrokontrolerem w celu interakcji z prostymi komponentami, takimi jak diody LED, czujniki ultradźwiękowe i wiele innych elementów znajdujących się w zestawie dla początkujących.
Jeśli jesteś kompletnym początkującym, ten samouczek pomoże ci zrozumieć MicroPython, abyś mógł czytać, pisać i modyfikować kod. Dzięki tej wiedzy możesz połączyć kod i komponenty, aby stworzyć coś, co ma rzeczywisty przypadek użycia.
Jeśli korzystasz z Pico, ten samouczek nauczy Cię, jak sterować Pico W bezprzewodowo. Wcześniej interakcja z Pico była możliwa tylko za pomocą przełącznika, przycisku lub innego fizycznego urządzenia. Już nie! Teraz możesz sterować komponentami za pomocą telefonu lub komputera.
Przepływ samouczka
Wstęp
Samouczek Hello World dla Pico W
Jeden krok w górę
Podstawowe sposoby przesyłania danych z czujnika
- Czujnik ultradźwiękowy Pico W i HC-SR04
- Przesyłanie strony internetowej z danymi czujnika
- Zmniejszanie obciążenia za pomocą AJAX
- Pimoroni Phew usprawnia kodowanie punktów końcowych
Łączenie się z narzędziami internetowymi
- Rejestrowanie danych klimatycznych z czujnika DHT22 w Arkuszach Google za pomocą IFTTT
- Zbuduj pilota Spotify z funkcjami odtwarzania/pauzy/przeskakiwania
Sterowanie GPIO bez użycia kodu za pomocą PiCockpit
- Super prosta instalacja PiCockpit na Pico W
- Proste sterowanie diodami LED za pomocą PiCockpit i Pico W
- Pico W, wentylator 5V i tranzystor, sterowane przez PiCockpit
MQTT
Spis treści
Podsumowanie celów samouczka
- Dowiedz się, jak współdziałać z podstawowymi komponentami tworzącymi większe projekty.
- Kontroluj wszystko bezprzewodowo - bez przełączników, przycisków lub innych urządzeń interakcyjnych.
- Lepsze zrozumienie mocnych stron Pico W
Ważne linki
Github repo dla kodu samouczka (z wyjątkiem secrets.py)
Błędy, sugestie, komentarze? Zostaw komentarz w polu komentarzy poniżej, napisz do mnie lub Tweetuj mnie.
OSError: [Errno 98] EADDRINUSE
Jeśli pojawi się ten błąd, po prostu odłącz i podłącz Raspberry Pi Pico.
Można to również zrobić, wpisując te polecenia w powłoce Thonny:
import machine
machine.reset()
Wynik:
Lutowanie pinów nagłówka
Kiedy kupujesz Raspberry Pi Pico W, może on nie być wyposażony w nagłówki, które pozwolą Ci podłączyć komponenty do Pico.
W chwili pisania tego tekstu, Pico WH (H dla nagłówków) nie został jeszcze wydany. Nasz mega-artykuł o Pico W śledzi jego premierę.
Jeśli jednak uda ci się znaleźć Pico W z fabrycznie przylutowanymi złączami, radziłbym ci go kupić.
Niemniej jednak, dla reszty z nas, lutowanie nagłówków na Pico W jest prostą rzeczą do zrobienia. Potrzebne będą:
- Tablica ogłoszeń
- Lutownica i lut
- Nagłówki
Kiedy kupujesz nagłówki, upewnij się, że kupujesz takie, które są przeznaczone dla Pico W. W przeciwieństwie do nagłówków dla Raspberry Pi serii Zero, nagłówki na Pico W nie znajdują się obok siebie. Znajdują się one na przeciwległych końcach płytki.
Piny mają dłuższą i krótszą stronę. Dłuższe piny powinny znajdować się po tej stronie, po której widoczne są etykiety GPIO (GP0, GP1, GND, VBUS, VSYS itp.).
Dlatego należy włożyć dłuższe kołki do płytki prototypowej. Potrzebne będą cztery otwory i odstępy między nimi. Jeśli nie masz pewności, przetestuj z Pico W.
Lutowanie jest łatwe. Upewnij się, że lutownica jest gorąca i upewnij się, że używasz końcówki lutownicy.
Najskuteczniejsze okazało się zbliżenie grotu lutownicy do pinu, dotknięcie grotu lutownicą i obserwowanie, jak lut spływa po pinie, tworząc połączenie.
Po lutowaniu upewnij się, że nie ma żadnych obcych lutów, które mogłyby łączyć ze sobą dwa piny GPIO lub resztki zużytego lutowia, które znajdują się na płytce.
Użyj Thonny jako edytora kodu
Thonny pozostaje najłatwiejszym sposobem programowania Raspberry Pi Pico W.
Jeśli korzystasz z systemu operacyjnego Raspberry Pi, masz go już zainstalowanego.
Jeśli jednak korzystasz z systemu Windows lub Mac, będziesz musiał go pobrać i skonfigurować.
Oto przewodnik, który przeprowadzi Cię przez kolejne kroki.
Upewnij się również, że zapoznaj się z przewodnikiem na temat przesyłania plików do Pico W.
Zaktualizuj oprogramowanie sprzętowe, wgrywając najnowszą wersję UF2
Kupując Pico W, możesz mieć już nieaktualne oprogramowanie sprzętowe.
Wiele zmian pojawi się w Pico W, więc idealnie jest zaktualizować oprogramowanie sprzętowe już teraz.
Niektóre zmiany, które widziałem od dnia premiery, to ulepszenia funkcji punktu dostępu WLAN, a przyszłe aktualizacje mogą odblokować funkcję Bluetooth na płycie.
Aktualizacja już teraz! Oto przewodnik w naszym mega-artykule.
1. Wyświetl stronę internetową z napisem "Hello World" na urządzeniu Pico
Jednym z najbardziej podstawowych projektów we wszystkich samouczkach programowania jest projekt "Hello World".
Komunikat "Hello World" mikrokontrolera zwykle obejmuje miganie diody LED. To bardzo proste. Oto jak to zrobić.
Ponieważ jednak Pico W może obsługiwać strony internetowe, zacznijmy od nauki obsługi strony internetowej z komunikatem "Hello World".
Zastosowana tutaj konfiguracja będzie stanowić najbardziej podstawowy element składowy dla reszty samouczków.
Istnieją dwa sposoby połączenia się z Pico W. Można połączyć się z siecią WiFi lub można rozgłaszanie hotspotu SoftAP podobnego do tego, co robi smartfon. Jeśli chcesz spróbować tego drugiego, kliknij ten link. Jednak dla zachowania spójności w tym samouczku zawsze będziemy łączyć się z siecią Wi-Fi, a nie rozgłaszać ją z Pico W.
Tak więc, zasadniczo, kroki związane z obsługą strony internetowej obejmują:
- Podłączenie do WiFi
- Napisanie kodu do wyświetlania index.html każdemu, kto połączy się z adresem IP Pico W.
Skonfigurujmy kilka plików. Zapisz je i prześlij do swojego Raspberry Pi Pico W. Oto jak przesyłać pliki, na wypadek gdybyś to przegapił.
wifi.py
wifi.py to szablon, który ma pomóc w połączeniu się z siecią WiFi. Utworzenie oddzielnego pliku i zaimportowanie go do main.py pomoże zmniejszyć bałagan w kodzie.
Pamiętaj, że powinieneś zmienić kod swojego kraju w linii rp2.country('DE') jeśli Twoim krajem nie są Niemcy.
import rp2
import network
import ubinascii
import machine
import urequests as requests
import time
from secrets import secrets
def init_wifi():
# Set country to avoid possible errors
rp2.country('DE')
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Load login data from different file for safety reasons
ssid = secrets['ssid']
pw = secrets['pw']
wlan.connect(ssid, pw)
# Wait for connection with 10 second timeout
timeout = 10
while timeout > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
timeout -= 1
print('Waiting for connection...')
time.sleep(1)
# Define blinking function for onboard LED to indicate error codes
def blink_onboard_led(num_blinks):
led = machine.Pin('LED', machine.Pin.OUT)
for i in range(num_blinks):
led.on()
time.sleep(.2)
led.off()
time.sleep(.2)
wlan_status = wlan.status()
blink_onboard_led(wlan_status)
if wlan_status != 3:
raise RuntimeError('Wi-Fi connection failed')
else:
print('Connected')
status = wlan.ifconfig()
print('ip = ' + status[0])
sekrety.py
wifi.py import sekrety.pygdzie przechowywane są informacje o sieci WiFi.
sekrety.py to prosty plik JSON zawierający identyfikator SSID i hasło sieci Wi-Fi.
secrets = {
'ssid': 'SM-A520W9371',
'pw': 'starting',
}
serve_webpage.py
Jak sama nazwa wskazuje, ta strona obsługuje witryny internetowe dla użytkowników, którzy łączą się z Pico W.
Po otrzymaniu połączenia Pico W znajduje plik o nazwie index.html i wysyła ją do połączonego klienta, jak widać w wierszu response = get_html('index.html').
import socket
def serve_webpage():
#Function to load in html page
def get_html(html_name):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
return html
# HTTP server with socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
response = get_html('index.html')
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
Na koniec musimy utworzyć index.html który zostanie wysłany do połączonego klienta.
<!DOCTYPE html>
<html>
<head>
<title>Pico W</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Jest to prosty szablon HTML z dwiema zmianami: jedną do <title>który wyświetla "Pico W" jako tytuł i znacznik <h1>, który mówi "Hello World".
main.py
Ponieważ umieściliśmy cały kod w innym miejscu, nasz main.py wystarczy zaimportować i wywołać te funkcje, aby wyświetlić stronę Hello World.
Jak widać, najpierw inicjalizujemy WiFi przed wyświetleniem strony internetowej.
from wifi import init_wifi
from serve_webpage import serve_webpage
init_wifi()
serve_webpage()
Już prawie!
Odnosząc się do poniższego zrzutu ekranu, upewnij się:
- Do Raspberry Pi Pico W wgrano pięć plików (patrz lewa dolna czerwona ramka)
- Upewnij się, że interpreter jest ustawiony na MicroPython (Raspberry Pi Pico) (patrz ramka w prawym dolnym rogu)
- Następnie podświetl main.py w edytorze kodu i kliknij zielony przycisk uruchamiania (lewe górne czerwone pole).
- Po uruchomieniu programu w powłoce pojawi się adres IP użytkownika. Przejdź do przeglądarki i wpisz ten adres, a zobaczysz stronę internetową Hello World.
- Jeśli powłoka nie jest otwarta, przejdź do Widok -> Powłoka.
Jeśli wszystko się powiedzie, zobaczysz poniższą stronę.
2. Bezprzewodowe sterowanie diodą LED
Teraz, gdy masz już skonfigurowane podstawy, przejdźmy o krok do przodu.
Jednym z najbardziej podstawowych projektów Raspberry Pi jest miganie diodą LED.
Podnieśmy to jeszcze wyżej, sterując diodą LED bezprzewodowo. Chcemy mieć możliwość migania, włączania i wyłączania diody LED.
W tym celu należy skonfigurować obwód i serwer sieciowy z trzema przyciskami - ON, OFF, BLINK.
Do tego projektu potrzebna będzie dioda LED, rezystor 330 omów, jeden przewód połączeniowy i płytka prototypowa.
Użyjemy czerwonej diody LED, ponieważ większość zestawów jest w nią wyposażona. Należy pamiętać, że w przypadku użycia diody LED w innym kolorze konieczne będzie dostosowanie rezystora.
Oto jak podłączyć komponenty
- GPIO 2 -> Długa nóżka diody LED (anoda/dodatnia)
- GND -> rezystor 330 omów -> krótka nóżka diody LED (katoda/ujemna)
Kod do sterowania diodą LED na Pico W
Oprzyjmy się na tym, co zrobiliśmy w poprzednim samouczku. Jedyne dwa pliki, które będziemy musieli zmodyfikować to index.html aby dodać przyciski i main.py do interakcji z diodą LED w oparciu o dane wejściowe z index.html.
Pogrubione części oznaczają nowe linie, które zostały dodane do index.html. Dodają trzy przyciski i akapit, który mówi "Kontroluj diodę LED".
<!DOCTYPE html>
<html>
<head>
<title>Pico W</title>
</head>
<body>
<h1>Pico W</h1>
<p>Control the LED</p>
<a href=\"?led=on\"><button>ON</button></a>
<a href=\"?led=off\"><button>OFF</button></a>
<a href=\"?led=blink\"><button>BLINK</button></a>
</body>
</html>
Po naciśnięciu przycisków pojawi się parametr dodany do adresu IP urządzenia Pico W (np. http://192.168.43.134/%22?led=blink\). Parametry te są przechwytywane przez backend Pico W i sterują diodą LED.
Zamierzamy przenieść serve_webpage.pydo kodu main.py akta.
Oto main.py:
from wifi import init_wifi
import socket
import machine
import time
init_wifi()
#LED controls
led = machine.Pin(2, machine.Pin.OUT)
def blink_led():
led.on()
time.sleep(0.2)
led.off()
time.sleep(0.2)
#Function to load in html page
def get_html(html_name):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
return html
# HTTP server with socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
request = cl.recv(1024)
print(request)
request = str(request)
led_on = request.find('?led=on')
led_off = request.find('?led=off')
led_blink = request.find('?led=blink')
print('led_on = ', led_on)
print('led_off = ', led_off)
print('led_blink = ', led_blink)
if led_on > -1:
print('LED ON')
led.on()
if led_off > -1:
print('LED OFF')
led.off()
if led_blink > -1:
print('LED BLINK')
blink_led()
response = get_html('index.html')
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
Pierwszy i kluczowy segment znajduje się poniżej:
request = cl.recv(1024)
print(request)
request = str(request)
led_on = request.find('?led=on')
led_off = request.find('?led=off')
led_blink = request.find('?led=blink')
print('led_on = ', led_on)
print('led_off = ', led_off)
print('led_blink = ', led_blink)
if led_on > -1:
print('LED ON')
led.on()
if led_off > -1:
print('LED OFF')
led.off()
if led_blink > -1:
print('LED BLINK')
blink_led()
Zmienna "request" po wydrukowaniu wyświetla pierwszy blok tekstu poniżej. Ostatnie trzy linie to instrukcje drukowania, które sprawdzają, czy dioda LED jest włączona, wyłączona lub miga:
b'GET /%22?led=blink\\%22 HTTP/1.1\r\nHost: 192.168.43.134\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nReferer: http://192.168.43.134/%22?led=on\\%22\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: en-US,en;q=0.9,es;q=0.8,zh-TW;q=0.7,zh-CN;q=0.6,zh;q=0.5\r\n\r\n'
led_on = 456
led_off = -1
led_blink = 10
Powyższy kod spróbuje wyszukać określone ciągi znaków, takie jak "led=on". Jeśli istnieje, wartość będzie większa niż -1, co spowoduje uruchomienie odpowiedniej funkcji jeśli oświadczenie.
Na przykład, jeśli led=on istnieje w parametrach, to zmienna led_on będzie większa niż -1, a zatem if led_on > -1 wywołuje i uruchamia instrukcję led.on();
Jedynym skomplikowanym elementem jest tutaj led_blink która uruchomi funkcję:
def blink_led():
led.on()
time.sleep(0.2)
led.off()
time.sleep(0.2)
Wreszcie, oto jak zainicjować GPIO 2 do obsługi diody LED:
import machine
import time
#LED controls
led = machine.Pin(2, machine.Pin.OUT)
Importujemy maszynę do interakcji z pinem GPIO. Jak widać w zmiennej prowadzony, chcemy, aby Pico W zasilał GPIO 2.
Importujemy czas abyśmy mogli mieć pauzę 0,2 sekundy w blink_led().
3. Dioda LED RGB na Pico W
Aby oświetlić diodę LED RGB, potrzebujesz:
- Trzy rezystory 330 omów
- Jedna dioda LED RGB
- Jeden przewód połączeniowy
Na diodzie LED RGB znajdują się cztery nóżki. Jedna z nich będzie najdłuższa. Jest to katoda (ujemna) lub anoda (dodatnia). Moja dioda LED RGB ma wspólną katodę, więc oto połączenie:
- GPIO 15 -> rezystor 330 omów -> czerwona dioda LED
- GPIO 17 -> rezystor -> zielona dioda LED
- GPIO 16 -> rezystor -> niebieska dioda LED
Oto kilka kodów, aby sprawdzić, czy wszystko działa poprawnie:
import machine
red_led = machine.PWM(machine.Pin(15))
green_led = machine.PWM(machine.Pin(17))
blue_led = machine.PWM(machine.Pin(16))
red_led.duty_u16(65534)
green_led.duty_u16(65534)
blue_led.duty_u16(65534)
W tym przykładzie używamy PWM, który pozwala zmieniać jasność diod LED R, G, B.
Możesz zmienić wartości przekazywane do [color].duty_u16 na wartość od 0 do 65534. Teoretycznie powinieneś być w stanie przekazać 65535, ale jakoś nie wydaje mi się to działać.
Podanie wartości "0" oznacza, że chcesz uzyskać zero procent jasności. Podanie wartości 65534 oznacza jasność na poziomie 100 procent.
Jeśli wykonasz 65534 dla jednego koloru i zero dla pozostałych, będziesz w stanie stwierdzić, czy podłączyłeś właściwe piny GPIO do właściwego koloru diody LED.
Dlaczego więc używamy PWM? Ponieważ pomoże to uzyskać więcej kolorów. Jeśli użyjesz metody "włącz i wyłącz", możesz uzyskać czerwony, zielony, niebieski, białawy i brak światła. Dzięki PWM możesz zmieniać intensywność diod LED R, G, B i tworzyć tyle kolorów, ile możesz sobie wyobrazić.
Teraz stwórzmy coś, co można kontrolować bezprzewodowo!
index.html
Główną zmianą jest posiadanie <form> który ma trzy suwaki. Suwaki te mają wartość od zera do 100.
Używanie wartości od zera do 100 pomaga wizualizować jasność jako wartość procentową. Zmniejsza to również ilość kodu potrzebnego do przeanalizowania wartości z parametrów (widoczne później w sekcji main.py)
Po ustawieniu wartości dla diod LED R, G, B należy nacisnąć przycisk "Wyślij", a dane te zostaną przechwycone przez Pico W.
<!DOCTYPE html>
<html>
<head>
<title>Pico W</title>
</head>
<body>
<h1>Pico W RGB LED</h1>
<form id="form">
<input type="range" min="0" max="100" value="slider_value" name="red" id="red">
<label for="red">R</p>
<input type="range" min="0" max="100" value="slider_value" name="green" id="green">
<label for="green">G</p>
<input type="range" min="0" max="100" value="slider_value" name="blue" id="blue">
<label for="blue">B</p>
<input type="submit" id="submit">
</form>
<script>
submit.addEventListener('click', function () {
form.submit();
}, false);
</script>
</html>
main.py
from wifi import init_wifi
import socket
import machine
import time
init_wifi()
#LED controls
red_led = machine.PWM(machine.Pin(15))
green_led = machine.PWM(machine.Pin(17))
blue_led = machine.PWM(machine.Pin(16))
#Function to load in html page
def get_html(html_name):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
return html
def find_intensity(color, request_str):
index = request_str.find(color) + len(color)
offset = 0
if request_str[index].isdigit():
offset = 1
if request_str[index+1].isdigit():
offset = 2
if request_str[index+2].isdigit():
offset = 3
intensity = int(request_str[index:index+offset])
return intensity
# HTTP server with socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
request = cl.recv(1024)
request_str = str(request)
#find intensity ONLY if the params exist in request
if request_str.find('red') > -1 :
#int = get rid of decimal
#/100*65534 = find_intensity returns something 0 to 100,
# so x/100 = proportion of 65534 that you want to send to LED
# 65534 = max number you can use for PWM
red_intensity = int(find_intensity('red=', request_str) /100 * 65534)
green_intensity = int(find_intensity('green=', request_str) /100 * 65534)
blue_intensity = int(find_intensity('blue=', request_str) /100 * 65534)
#print('r=' + str(red_intensity))
#print('g=' + str(green_intensity))
#print('b=' + str(blue_intensity))
red_led.duty_u16(red_intensity)
green_led.duty_u16(green_intensity)
blue_led.duty_u16(blue_intensity)
response = get_html('index.html')
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
Po naciśnięciu przycisku przesyłania index.html Pico W pobierze parametry i przetworzy je.
Przyjrzyjmy się kilku kluczowym punktom w kodzie, pogrubionym w powyższym bloku kodu.
funkcja find_intensity
Ta funkcja pobiera dwa parametry: kolor oraz request_str. kolor pobiera "czerwony", "zielony" lub "niebieski" i znajduje wartość po znaku równości (=).
Na przykład adres URL po przesłaniu formularza to "http://192.168.1.142/?red=89&green=50&blue=50".
Przekazanie wartości "red" do funkcji find_intensity spowoduje zwrócenie wartości 89.
parser intensywności
Drugi pogrubiony blok kodu reprezentuje kod, który mówi GPIO Pico W, ile jasności chcesz od każdej diody LED.
Po pierwsze, musimy upewnić się, że parametry istnieją w adresie URL. Odbywa się to za pomocą funkcji jeśli oświadczenie request_str.find('red') > -1. Po prostu użyłem 'czerwony' ponieważ parametry będą 100% zawierać ciąg "czerwony", jeśli użyjesz formularza.
Jeśli odwiedzasz adres IP Pico W (np. http://192.168.1.142/) po raz pierwszy, nie będziesz mieć parametrów, więc program ulegnie awarii po uruchomieniu find_intensity.
Jeśli istnieją parametry, znajdujemy intensywność dla każdej diody LED zgodnie z przesłanymi wartościami. Przyjrzyjmy się red_intensity.
red_intensity = int(find_intensity('red=', request_str) /100 * 65534)
...
red_led.duty_u16(red_intensity)
find_intensity zwraca liczbę całkowitą od zera do 100. Dzielimy ją przez 100, aby uzyskać wartość procentową. Ta wartość procentowa dzieli maksymalną wartość, którą zwraca duty_u16 metoda może zostać zastosowana.
Potrzebujemy jednak int funkcja, aby to zawinąć, ponieważ czasami można uzyskać pływak i duty_u16 potrzebuje int. Na przykład, powiedzmy, że chcesz 41% jasności - 41% z 65534 to 26,868.94. Nie można przekroczyć tej wartości, ponieważ program ulegnie awarii.
4. Działanie brzęczyka na Pico W
Brzęczyk jest dość ważnym komponentem dla podstawowych powiadomień, podobnie jak dioda LED może powiedzieć o stanie czegoś, brzęczyk daje powiadomienie dźwiękowe.
Zamiast implementować własny kod, zdecydowałem się użyć Wdrożenie Giuseppe Cassibby. Jeśli uruchomiłeś ten kod na Pico W, usłyszysz sygnały dźwiękowe na brzęczyku.
Ale ponieważ ten kod jest przeznaczony dla Pico, nie będzie miał żadnych funkcji interaktywności bezprzewodowej.
Wyciągnijmy więc widelec!
Najpierw zmodyfikujmy index.html do implementacji przycisków. Miejmy przycisk dla "ON", "OFF", "SCALE", "MUSIC".
Pierwsze dwa przyciski nie wymagają wyjaśnień. Trzeci przycisk odtwarza skalę C, a ostatni odtwarza utwór muzyczny.
<!DOCTYPE html>
<html>
<head>
<title>Pico W</title>
</head>
<body>
<h1>Pico W Buzzer</h1>
<p>Control the buzzer</p>
<a href=\"?buzzer=on\"><button>ON</button></a>
<a href=\"?buzzer=off\"><button>OFF</button></a>
<a href=\"?buzzer=scale\"><button>SCALE</button></a>
<a href=\"?buzzer=music\"><button>MUSIC</button></a>
</body>
</html>
Tak jak poprzednio, tworzymy kilka <button> tagi z <a> otaczające je. Po kliknięciu przycisków adres URL będzie zawierał parametr, taki jak /buzzer=on. Pico W odczytuje to i włącza brzęczyk.
Przyjrzyjmy się teraz kodowi Giuseppe dla Pico:
from machine import Pin, PWM
from time import sleep
buzzerPIN=16
BuzzerObj=PWM(Pin(buzzerPIN))
def buzzer(buzzerPinObject,frequency,sound_duration,silence_duration):
# Set duty cycle to a positive value to emit sound from buzzer
buzzerPinObject.duty_u16(int(65536*0.2))
# Set frequency
buzzerPinObject.freq(frequency)
# wait for sound duration
sleep(sound_duration)
# Set duty cycle to zero to stop sound
buzzerPinObject.duty_u16(int(65536*0))
# Wait for sound interrumption, if needed
sleep(silence_duration)
# Play following notes by changing frequency:
#C (DO)
buzzer(BuzzerObj,523,0.5,0.1)
#D (RE)
buzzer(BuzzerObj,587,0.5,0.1)
#E (MI)
buzzer(BuzzerObj,659,0.5,0.1)
#F (FA)
buzzer(BuzzerObj,698,0.5,0.1)
#G (SOL)
buzzer(BuzzerObj,784,0.5,0.1)
#A (LA)
buzzer(BuzzerObj,880,0.5,0.1)
#B (SI)
buzzer(BuzzerObj,987,0.5,0.1)
#Deactivates the buzzer
BuzzerObj.deinit()
Jego kod odtwarza skalę C, gdy jest uruchamiany przy użyciu funkcji buzzer()która przyjmuje cztery parametry: Obiekt brzęczyka, częstotliwość w hercach, czas trwania dźwięku i czas pauzy przed odtworzeniem kolejnego dźwięku.
Zmodyfikujmy kod, abyśmy mogli aktywować funkcję ON, OFF, SCALE oraz MUZYKA.
Oto jak integrujemy kod Giuseppe z naszą aplikacją main.py:
from wifi import init_wifi
import socket
import machine
import time
init_wifi()
# Buzzer
buzzerPIN = 16
BuzzerObj = machine.PWM(machine.Pin(buzzerPIN))
def buzzer(buzzerPinObject, frequency, sound_duration, silence_duration):
# Set duty cycle to a positive value to emit sound from buzzer
buzzerPinObject.duty_u16(int(65536*0.2))
# Set frequency
buzzerPinObject.freq(frequency)
# wait for sound duration
time.sleep(sound_duration)
# Set duty cycle to zero to stop sound
buzzerPinObject.duty_u16(int(65536*0))
# Wait for sound interrumption, if needed
time.sleep(silence_duration)
# Function to load in html page
def get_html(html_name):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
return html
# HTTP server with socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
request = cl.recv(1024)
request = str(request)
buzzer_on = request.find('?buzzer=on')
buzzer_off = request.find('?buzzer=off')
buzzer_scale = request.find('?buzzer=scale')
buzzer_music = request.find('?buzzer=music')
if buzzer_on > -1:
BuzzerObj.duty_u16(int(65536*0.2))
BuzzerObj.freq(440)
if buzzer_off > -1:
BuzzerObj.duty_u16(0)
if buzzer_scale > -1:
#C (DO)
buzzer(BuzzerObj, 523, 0.5, 0.1)
#D (RE)
buzzer(BuzzerObj, 587, 0.5, 0.1)
#E (MI)
buzzer(BuzzerObj, 659, 0.5, 0.1)
#F (FA)
buzzer(BuzzerObj, 698, 0.5, 0.1)
#G (SOL)
buzzer(BuzzerObj, 784, 0.5, 0.1)
#A (LA)
buzzer(BuzzerObj, 880, 0.5, 0.1)
#B (SI)
buzzer(BuzzerObj, 987, 0.5, 0.1)
BuzzerObj.deinit()
if buzzer_music > -1:
pass
response = get_html('index.html')
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
W powyższej implementacji nie napisaliśmy kodu dla MUZYKA.
Kod jest bardzo podobny do powyższego samouczka czerwonej diody LED, gdzie Pico W przechwytuje parametry po adresie IP Pico W. Jeśli parametr brzęczyk=WŁ, odtworzy dźwięk o częstotliwości 440 Hz. Jeśli buzzer=skala, odtworzy skalę pobraną z kodu Giuseppe.
A co z implementacją muzyki? Implementacja muzyki jest nieco bardziej skomplikowana, więc powinniśmy utworzyć nowy plik o nazwie constants.py i dodać kilka linijek do naszego main.py.
Ten kod jest rozwidleniem kodu Kod Arduino Rowana Packarda.
constants.py
A3F = 208 # 208 Hz
B3F = 233 # 233 Hz
B3 = 247 # 247 Hz
C4 = 261 # 261 Hz MIDDLE C
C4S = 277 # 277 Hz
E4F = 311 # 311 Hz
F4 = 349 # 349 Hz
A4F = 415 # 415 Hz
B4F = 466 # 466 Hz
B4 = 493 # 493 Hz
C5 = 523 # 523 Hz
C5S = 554 # 554 Hz
E5F = 622 # 622 Hz
F5 = 698 # 698 Hz
F5S = 740 # 740 Hz
A5F = 831 # 831 Hz
main.py (dodatki pogrubione)
from wifi import init_wifi
import socket
import machine
import time
from constants import *
init_wifi()
# Buzzer
buzzerPIN = 16
BuzzerObj = machine.PWM(machine.Pin(buzzerPIN))
def buzzer(buzzerPinObject, frequency, sound_duration, silence_duration):
# Set duty cycle to a positive value to emit sound from buzzer
buzzerPinObject.duty_u16(int(65536*0.2))
# Set frequency
buzzerPinObject.freq(frequency)
# wait for sound duration
time.sleep(sound_duration)
# Set duty cycle to zero to stop sound
buzzerPinObject.duty_u16(int(65536*0))
# Wait for sound interrumption, if needed
time.sleep(silence_duration)
# Function to load in html page
def get_html(html_name):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
return html
# HTTP server with socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
request = cl.recv(1024)
request = str(request)
buzzer_on = request.find('?buzzer=on')
buzzer_off = request.find('?buzzer=off')
buzzer_scale = request.find('?buzzer=scale')
buzzer_music = request.find('?buzzer=music')
if buzzer_on > -1:
BuzzerObj.duty_u16(int(65536*0.2))
BuzzerObj.freq(440)
if buzzer_off > -1:
BuzzerObj.duty_u16(0)
if buzzer_scale > -1:
#C (DO)
buzzer(BuzzerObj, 523, 0.5, 0.1)
#D (RE)
buzzer(BuzzerObj, 587, 0.5, 0.1)
#E (MI)
buzzer(BuzzerObj, 659, 0.5, 0.1)
#F (FA)
buzzer(BuzzerObj, 698, 0.5, 0.1)
#G (SOL)
buzzer(BuzzerObj, 784, 0.5, 0.1)
#A (LA)
buzzer(BuzzerObj, 880, 0.5, 0.1)
#B (SI)
buzzer(BuzzerObj, 987, 0.5, 0.1)
BuzzerObj.deinit()
if buzzer_music > -1:
pause = 0.05
# pauses between notes
t = 0.125
# time that music note plays
music_notes = [B4F, B4F, A4F, A4F,
F5, F5, E5F, B4F, B4F, A4F, A4F, E5F, E5F, C5S, C5, B4F,
C5S, C5S, C5S, C5S,
C5S, E5F, C5, B4F, A4F, A4F, A4F, E5F, C5S,
B4F, B4F, A4F, A4F,
F5, F5, E5F, B4F, B4F, A4F, A4F, A5F, C5, C5S, C5, B4F,
C5S, C5S, C5S, C5S,
C5S, E5F, C5, B4F, A4F, A4F, A4F, E5F, C5S, C5S]
rhythm = [1, 1, 1, 1,
3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
1, 1, 1, 1,
3, 3, 3, 1, 2, 2, 2, 4, 8,
1, 1, 1, 1,
3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
1, 1, 1, 1,
3, 3, 3, 1, 2, 2, 2, 4, 8, 4]
for i in range(len(music_notes)):
buzzer(BuzzerObj, music_notes[i], rhythm[i]*t, pause)
response = get_html('index.html')
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
Jak widać, istnieją dwie tablice, music_notes oraz rytm. Następnie należy uruchomić pętlę for, aby umieścić te wartości w pliku buzzer() function. Ponadto w górnej części kodu importujemy wszystkie zmienne z funkcji constants.py.
Strona buzzer() funkcja wykorzystuje również dwie nowe zmienne - t oraz pauza. Te dwie zmienne pomagają dostroić tempo muzyki. t określa, jak długo powinna być odtwarzana każda nuta i pauza określa, jak długa powinna być cisza między nutami.
5. Czujnik ultradźwiękowy Pico W i HC-SR04
W poprzednich samouczkach używaliśmy Pico W do wysyłania poleceń do diod LED i brzęczyków.
Ale co, jeśli używamy Pico W do odbierania informacji?
W tym przypadku mówimy o ultradźwiękowym czujniku odległości HC-SR04.
Po podłączeniu czujnika ultradźwiękowego należy sprawdzić, czy jest to komponent 5 V czy 3,3 V. Podłączyłem moją wersję 5V do pinu 3.3V i nie otrzymałem żadnej odpowiedzi z programu, którą podzielę się poniżej. Po przeniesieniu źródła zasilania na pin 5 V, natychmiast otrzymałem odpowiedź.
Najwyraźniej niektóre nowsze wersje HC-SR04 mogą przyjmować zarówno 3,3 V, jak i 5 V. Być może najlepiej jest najpierw wypróbować pin 3,3 V i sprawdzić, czy uzyskasz wynik. Jeśli nie, spróbuj 5V.
Oto schematy i program, który można uruchomić w Thonny. Jeśli otrzymasz odpowiedź, oznacza to, że podłączyłeś wszystko we właściwy sposób, w tym napięcie.
Okablowanie
Okablowanie z oznaczonych pinów czujników HC-SR04 jest następujące:
- VCC do pinu 3,3 V lub 5 V (w razie wątpliwości należy najpierw wypróbować napięcie 3,3 V).
- TRIG do GPIO 16
- ECHO do GPIO 15
- GND do GND
Program testowy dla HC-SR04
Aby sprawdzić, czy okablowanie jest prawidłowe, wypróbuj ten kod, który wydrukuje odległość na Thonny Shell.
from machine import Pin
import time
trigger = Pin(16, Pin.OUT)
echo = Pin(15, Pin.IN)
def ultrasonic():
trigger.low()
time.sleep_us(1)
trigger.high()
time.sleep_us(10)
trigger.low()
while echo.value() == 0:
signaloff = time.ticks_us()
while echo.value() == 1:
signalon = time.ticks_us()
timepassed = signalon - signaloff
distance = (timepassed * 0.0340) / 2
print("Distance = ",distance,"cm")
while True:
ultrasonic()
time.sleep(1)
Dane wyjściowe powinny wyglądać następująco:
Distance = 9.707001 cm
Distance = 9.707001 cm
Distance = 8.619 cm
Distance = 8.415001 cm
Distance = 8.551001 cm
Distance = 8.551001 cm
Distance = 8.619 cm
Jeśli program uruchamia się i kończy działanie bez żadnego sygnału wyjściowego, prawdopodobnie coś zostało źle podłączone. Kiedy podłączyłem czujnik do pinu 3,3 V zamiast 5 V, program zakończył działanie bez odpowiedzi.
Pobieranie danych wysyłanych do przeglądarki
Przygotujmy pliki, których używaliśmy do obsługi strony internetowej i zmodyfikujmy je tak, abyśmy mogli zobaczyć wartości odległości.
Oto ostateczny kod:
main.py
from wifi import init_wifi
import socket
from machine import Pin
import time
init_wifi()
# ultrasonic sensor pins and functions
trigger = Pin(16, Pin.OUT)
echo = Pin(15, Pin.IN)
def ultrasonic():
trigger.low()
time.sleep_us(1)
trigger.high()
time.sleep_us(10)
trigger.low()
while echo.value() == 0:
signaloff = time.ticks_us()
while echo.value() == 1:
signalon = time.ticks_us()
timepassed = signalon - signaloff
distance = (timepassed * 0.0340) / 2
return distance
# Function to load in html page
def get_html(html_name, distance):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
content = html.replace(
"<h2 id=\"ultrasonic\"></h2>", f"<h2 id=\"ultrasonic\">{distance}cm</h2>")
return content
# HTTP server with socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
request = cl.recv(1024)
print(ultrasonic())
response = get_html('index.html', ultrasonic())
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
index.html
<!DOCTYPE html>
<html>
<head>
<title>Pico W</title>
</head>
<body>
<h1>Pico W Ultrasonic Distance</h1>
<h2 id="ultrasonic"></h2>
<script>
setInterval(() => location.reload(), 500)
</script>
</html>
Przyjrzyjmy się kilku fragmentom kodu, aby zrozumieć, co się dzieje.
Kod do uzyskania odległości ultradźwiękowej
def ultrasonic():
trigger.low()
time.sleep_us(1)
trigger.high()
time.sleep_us(10)
trigger.low()
while echo.value() == 0:
signaloff = time.ticks_us()
while echo.value() == 1:
signalon = time.ticks_us()
timepassed = signalon - signaloff
distance = (timepassed * 0.0340) / 2
return distance
Powyższy blok kodu wyzwala emisję fali ultradźwiękowej. The time.sleep pomiędzy niskimi i wysokimi wartościami są niezbędne do działania czujnika ultradźwiękowego.
Aby zmierzyć czas pomiędzy emisją fali ultradźwiękowej a czasem powrotu fali dźwiękowej, używamy time.ticks_us do pomiaru czasu emisji i czasu wykrycia echa.
time.ticks_us jest dowolną liczbą, więc będziemy musieli odjąć sygnał z wyłączenie sygnału aby upłynął czas.
Aby uzyskać odległość, używamy wzoru distance = (timepassed * speedofsound) / 2. Prędkość dźwięku wynosi 340 m/s, czyli 0,0340.
Powodem, dla którego musimy podzielić ją przez dwa jest to, że fala dźwiękowa przemieszcza się do obiektu i wraca z powrotem.
Kod do wyświetlenia strony internetowej z wartością odległości
def get_html(html_name, distance):
# open html_name (index.html), 'r' = read-only as variable 'file'
with open(html_name, 'r') as file:
html = file.read()
content = html.replace(
"<h2 id=\"ultrasonic\"></h2>", f"<h2 id=\"ultrasonic\">{distance}cm</h2>")
return content
...
response = get_html('index.html', ultrasonic())
Funkcja ta została nieco zmodyfikowana w stosunku do poprzednich samouczków, przyjmując dodatkowy parametr odległośćktóry działa ultrasonic().
Funkcja ta otwiera index.html plik normalnie, ale używa zastąpić aby znaleźć metodę <h2> i wstawia odległość zmienna.
index.html pinguje serwer co 500 ms, aby uzyskać nową wartość
Główna strona internetowa otrzymuje funkcję, która przeładowuje stronę co 500 ms. Każde przeładowanie powoduje pingowanie Pico W w celu uzyskania nowej wartości odległości ultradźwiękowej.
<script>
setInterval(() => location.reload(), 500)
</script>
6. Dane ultradźwiękowe, ale użyjmy AJAX, aby zmniejszyć obciążenie
Poprzedni samouczek działa w ten sposób, że Raspberry Pi Pico W wysyła zupełnie nowy index.html za każdym razem, gdy następuje połączenie.
To działa, ale jest niewiarygodnie nieefektywne, ponieważ całość index.html gdy wymagana jest tylko aktualizacja danych odległości ultradźwiękowej.
Chcemy uzyskać takie same wyniki, jak w poprzednim samouczku, ale bez dużego obciążenia poprzedniej metody.
Musimy więc sprawić, by klient (telefon lub komputer) pingował punkt końcowy, który odpowie tylko danymi ultradźwiękowymi.
Nowa metodologia jest następująca: jeśli ludzie odwiedzą główny adres URL, powiedzmy 192.168.1.119, zostanie im wyświetlony adres index.html.
index.html będzie miał JavaScript, który pinguje /data który uruchamia Pico W, aby uzyskać ultradźwiękowe dane o odległości i odpowiedzieć na nie.
Następnie, index.html otrzyma te dane i zaktualizuje stronę internetową.
Łączenie żądania od klienta
Pamiętaj, że w main.pyzawsze jest linia mówiąca requests = cl.recv(1024). Obiekt żądania wygląda trochę tak:
b'GET /data HTTP/1.1
Host: 192.168.1.119
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.1.119/data
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8,zh-TW;q=0.7,zh-CN;q=0.6,zh;q=0.5
Po pierwsze, musimy odfiltrować tę ścianę tekstu.
Używamy find() aby sprawdzić, czy żądanie zmienna ma wartość "/data". Jeśli tak, należy podać dane dotyczące odległości ultradźwiękowej. Jeśli nie ma "/data", odpowiedz z index.html.
Przed
request = cl.recv(1024)
print(ultrasonic())
response = get_html('index.html', ultrasonic())
Po
request = cl.recv(1024)
request = str(request)
print (request.find('/data'))
if (request.find('/data') > -1):
#if string is found, respond with data.
response = str(ultrasonic())
else:
response = get_html('index.html', ultrasonic())
Jeśli odwiedziłeś /data w przeglądarce, zobaczysz wydrukowaną wartość odległości, jak poniżej.
Wcześniej backend obsługiwał prawie wszystko. Odległość ultradźwiękowa została zmodyfikowana, zanim została zaserwowana jako index.html.
Teraz, index.html pobiera dane czujnika z Pico W, więc musimy wprowadzić pewne zmiany w JavaScript znajdującym się w pliku HTML. Zmiany zostały wyróżnione pogrubioną czcionką.
<!DOCTYPE html>
<html>
<head>
<title>Pico W</title>
</head>
<body>
<h1>Pico W Ultrasonic Distance</h1>
<h2 id="ultrasonic"></h2>
<script>
//instead of hardcoding, use address which browser accessed Pico W.
const PicoAddress = window.location.href
const getData = async () => {
//there is a slash at the end of PicoAddress, so don't use "/data". use "data"
const data = await fetch(`${PicoAddress}data`);
//response is just a string, so use data.text() to decode the Response's body
const distance = await data.text();
//target ultrasonic id and change its inner HTML
ultrasonic.innerHTML = `${distance} cm`;
//run getData() again.
setInterval(getData,100)
//you can run getData() but it seems more optimized if you give it some time to breathe
};
getData();
</script>
</html>
Centralnym elementem kodu jest tutaj Fetch API i najnowsze async/await składnia tutaj.
Funkcja getData() pinguje punkt końcowy /data Pico W, a Pico W odpowiada. Upewniamy się, że program nie przeskoczy do przodu, zanim nie otrzymamy pełnej odpowiedzi z prośbą o czekać.
Fetch staje się obiektem Response, który należy użyć metody Response.text(), aby uzyskać dostęp do treści odpowiedzi. Stąd linie const distance = await data.text();
Po uzyskaniu danych ultradźwiękowych zmieniamy <h2 id="”ultrasonic”"> wewnętrzny HTML elementu, który zaczyna się pusty, z danymi odległości. Można kierować element za pomocą id bezpośrednio bez użycia getElementById() lub querySelector() metody.
Po wykonaniu całego kodu chcemy ponownie uruchomić getData(). Dlaczego użyłem funkcji setInterval aby ustawić interwał 100 ms?
Odkryłem, że jeśli wywołasz getData() bez interwału, otrzymasz więcej przerw między wyjściami. Otrzymasz sekwencję szybkich aktualizacji, a następnie pauzę. Z przerwą 100 ms, Pico W działa nieco lepiej, a aktualizacje wydają się mniej więcej w czasie rzeczywistym.
Jeśli chcesz zrozumieć, co dzieje się pod maską, zapoznaj się z sekcją Dokumentacja interfejsu API pobierania i async/await dokumentacja.
7. Pimoroni Uff za czystszy kod
W ostatniej sekcji omówiliśmy metodę AJAX aktualizacji danych czujnika ultradźwiękowego.
Ale czy jest na to jeszcze lepszy sposób?
Pimoroni's Phew to biblioteka, która pomaga w łatwym nawiązywaniu kontaktów, ponieważ pozwala uniknąć wielu leków.
Cele są takie same:
- Pobieranie danych ultradźwiękowych i wyświetlanie ich na ekranie index.html
- Ładowność powinna być jak najniższa.
Oto jak to zrobić main.py wygląda.
from wifi import init_wifi
from phew import server
from phew.template import render_template
from machine import Pin
import time
init_wifi()
# ultrasonic sensor pins and functions
trigger = Pin(16, Pin.OUT)
echo = Pin(15, Pin.IN)
# Function to load in html page
@server.route("/data", methods=["GET"])
def ultrasonic(request):
trigger.low()
time.sleep_us(1)
trigger.high()
time.sleep_us(10)
trigger.low()
while echo.value() == 0:
signaloff = time.ticks_us()
while echo.value() == 1:
signalon = time.ticks_us()
timepassed = signalon - signaloff
distance = (timepassed * 0.0340) / 2
return str(distance), 200
@server.catchall()
def catchall(request):
return render_template("index.html")
server.run()
Jak widać, kod jest o wiele bardziej czytelny, ponieważ można ustawić punkty końcowe i połączyć je z funkcjami, które zwracają określone dane.
Zamiast grzebać w kodzie, aby uruchomić gniazda, wystarczy wywołać funkcję z biblioteki Phew.
Niektóre rzeczy, które podobają mi się w Phew to:
- Koniec z używaniem request.find() aby utworzyć punkt końcowy
- Nie więcej get_html() aby otworzyć funkcję index.html wystarczy użyć pliku Phew render_template()
- main.py jest o wiele łatwiejszy do odczytania, przy minimalnym dodatkowym wysiłku!
- Phew dodaje również funkcję rejestrowania, która pozwala na łatwiejsze debugowanie kodu.
Jedynym minusem jest to, że Phew to wciąż "bardzo nowy projekt i powinien być uważany, w najlepszym razie, za fazę alfa". Czasami można więc napotkać nieoczekiwane przeszkody.
W poprzednich samouczkach omówiono sposób interakcji Pico W z komputerem/telefonem komórkowym.
Pójdźmy o krok dalej i pozwólmy Pico W na interakcję z usługą w chmurze.
W tym celu stwórzmy rejestrator temperatury i wilgotności z czujnikiem DHT22, który wysyła dane do Arkuszy Google za pośrednictwem IFTTT.
8. Konfiguracja czujnika temperatury i wilgotności DHT22 do Pico W
Wszystkie te kroki działają dla DHT11 i DHT22. Główną różnicą między nimi jest dokładność odczytów. DHT11 ma niebieski kolor, podczas gdy DHT22 jest biały.
Jeśli posiadasz DHT11, zwróć uwagę, że odniesienia do DHT22 w kodzie powinny zostać zmienione na DHT11. Na przykład,
import dht
#dht22 = dht.DHT22(Pin(16))
#should be
dht11 = dht.DHT11(Pin(16))
Patrząc na poniższy schemat, od góry do dołu DHT22, należy podłączyć napięcie 3,3 V do pierwszego pinu.
Drugi pin to pin danych. Musisz go zasilić. Podłącz więc do niego rezystor 10K Ohm z szyny zasilania, a następnie podłącz kolejny przewód połączeniowy do GPIO 16 w Raspberry Pi Pico.
GND idzie do masy.
Aby przetestować czujnik, wykonaj następujące czynności:
from machine import Pin
import dht
# ultrasonic sensor pins and functions
dht22 = dht.DHT22(Pin(16))
print(dht22.measure())
print(dht22.temperature())
print(dht22.humidity())
Jeśli otrzymasz OSError: [Errno 110] ETIMEDOUT oznacza zbyt szybkie uruchomienie skryptu. DHT22 wymaga dwusekundowej przerwy przed zwróceniem kolejnej wartości. DHT11 wymaga jednej sekundy.
Łączenie IFTTT i Arkuszy Google
Najprostszym sposobem przesyłania danych z Pico W do Arkuszy Google jest IFTTT.
Po pierwsze, Zarejestruj konto IFTTT.
Następnie kliknij przycisk "Utwórz", aby utworzyć aplet.
Zostanie wyświetlony ten ekran:
Kliknij "Jeśli to" i wyszukaj Webhooks. Kliknij "Odbierz żądanie internetowe". Nie wybieraj opcji JSON. Nazwij nazwę zdarzenia "dht22". Nazwa zdarzenia jest krytyczna, ponieważ w ten sposób IFTTT wie, który aplet uruchomić.
To, co tutaj robisz, to tworzenie punktu końcowego, do którego możesz wysyłać ping z danymi czujnika DHT22.
Następnie kliknij "Następnie to". Wybierz "Arkusze Google". Następnie wybierz "Dodaj wiersz do arkusza kalkulacyjnego". Musisz połączyć swoje konto Google Sheets.
Zmień "Nazwę arkusza kalkulacyjnego" i "Ścieżkę folderu na dysku" na cokolwiek chcesz. Jedyną krytyczną rzeczą jest tutaj "Sformatowany wiersz", gdzie ma się znaleźć
{{OccurredAt}} ||| {{Value1}} ||| {{Value2}}
Teraz należy przejść do punktu końcowego, do którego Pico W może wysyłać dane z czujników.
Kieruj się do https://ifttt.com/maker_webhooks i kliknij "Dokumentacja".
Dokumentacja zawiera informacje na temat klucza, punktu końcowego, do którego należy wysłać dane, oraz sposobu struktury treści JSON.
Ponieważ użyłeś "dht22" jako nazwy zdarzenia, twój punkt końcowy to:
ttps://maker.ifttt.com/trigger/dht22/with/key/[your_key_here]
Będziesz także chciał ustrukturyzować swoje ciało JSON w następujący sposób:
{'value1': *** temperature data *** , value2': *** humidity data *** }
Kodowanie Pico W do pobierania danych DHT22 i wysyłanie ich do IFTTT
Oto jak.
from machine import Pin
from wifi import init_wifi
import urequests
import ujson
import dht
import time
init_wifi()
dht22 = dht.DHT22(Pin(16))
def send_data():
#tell dht22 to take a reading
dht22.measure()
#find temp & humidity data and then jsonify data.
dht_data = {'value1': str(dht22.temperature()),
'value2': str(dht22.humidity())}
post_data = ujson.dumps(dht_data)
request_url = 'https://maker.ifttt.com/trigger/dht22/with/key/[your_key_here]'
res = urequests.post(request_url, headers={
'content-type': 'application/json'}, data=post_data)
#log response from IFTTT.
print(res.text)
#sleep for a minute before running send_data again
time.sleep(1*60)
send_data()
send_data()
Jeśli zamierzasz skopiować ten kod, upewnij się, że zastąpiłeś [your_key_here] w request_url zmienna.
Co minutę powinien pojawiać się nowy odczyt, który zostanie zapisany w Arkuszu Google, jak poniżej.
Należy pamiętać, że rejestrowana temperatura jest podawana w stopniach Celsjusza. Jeśli chcesz uzyskać temperaturę w stopniach Fahrenheita, skorzystaj z poniższego wzoru:
fahrenheit = dht22.temperature() * 1.8000 + 32.00
Jeśli chcesz, aby dane były rejestrowane częściej (lub rzadziej), zmień wartość w polu time.sleep().
Użyj IFTTT, aby powiadomić Cię o wystąpieniu błędu
Oczywiście kod ten jest wciąż dość delikatny.
Powiedzmy, że coś poszło nie tak. Na przykład kot pociągnął za przewód połączeniowy 3,3 V, gdy położyłeś go na podłodze, aby zarejestrować temperaturę.
Program umrze, ale nie otrzymasz żadnego powiadomienia, dopóki nie zauważysz, że Twoje dane nie są rejestrowane.
Jak to rozwiązać?
IFTTT wyśle ci powiadomienie, gdy to się stanie!
Będziesz potrzebować aplikacji IFTTT na swoim telefonie. Należy ją pobrać.
Następnie należy utworzyć nowy aplet.
Dla "If This" część, Wybierz Webhooks -> Odbieranie żądań internetowych. Nazwij swoje wydarzenie "błąd".
Dla "Więc to" część, wybierz "Powiadomienia" oraz "Wyślij powiadomienie z aplikacji IFTTT".
Przekazałem prostą wiadomość
Error: {{Value1}}
Teraz zbudujmy bloki try-error.
from machine import Pin
from wifi import init_wifi
import urequests
import ujson
import dht
import time
init_wifi()
dht22 = dht.DHT22(Pin(16))
def send_data():
# tell dht22 to take a reading
dht22.measure()
# find temp & humidity data and then jsonify data.
dht_data = {'value1': str(dht22.temperature()),
'value2': str(dht22.humidity())}
post_data = ujson.dumps(dht_data)
request_url = 'https://maker.ifttt.com/trigger/dht22/with/key/[your-key-here]'
res = urequests.post(request_url, headers={
'content-type': 'application/json'}, data=post_data)
# log response from IFTTT.
print(res.text)
# sleep for a minute before running send_data again
time.sleep(1*60)
send_data()
try:
send_data()
except Exception as e:
print(e)
request_url = 'https://maker.ifttt.com/trigger/error/with/key/[your-key-here]'
post_data = ujson.dumps({"value1": str(e)})
urequests.post(request_url, headers={
'content-type': 'application/json'}, data=post_data)
Spróbuj. Odłącz przewód 3,3 V od DHT22, a otrzymasz takie powiadomienie:
9. Zbuduj fizycznego pilota Spotify z Raspberry Pi Pico W
Opierając się na poprzednim projekcie, użyjemy IFTTT do kontrolowania Spotify.
Stworzymy urządzenie z przyciskami odtwarzania, pauzy i pomijania utworów.
Główną zaletą korzystania z IFTTT do sterowania Spotify jest łatwość tego procesu.
Wadą jest to, że potrzebujesz płatnego konta Spotify, a odpowiedzi są powolne. Oznacza to, że jeśli naciśniesz przycisk pomijania, będziesz musiał chwilę poczekać, zanim zobaczysz wynik.
Piękno posiadania dedykowanego pilota Spotify polega na tym, że możesz zmieniać muzykę bez noszenia telefonu lub konieczności otwierania aplikacji Spotify.
Jeśli kiedykolwiek jeździłeś nowoczesnym samochodem, wiesz, jak przyjemne jest sterowanie z kierownicy.
Okablowanie zdalnego kontrolera Spotify
Będziesz potrzebował...
- 7 przewodów połączeniowych
- 3x przyciski
- Raspberry Pi Pico W
- Płatne konto Spotify
Na obrazku widać wiele krzyżujących się przewodów, więc oto wyjaśnienie tekstowe.
Przyciski są jak przełączniki. Musisz podłączyć pin 3V3 do każdego z nich, co oznacza użycie dodatniej kolumny na płytce drukowanej. Dlatego:
3V3 -> Kolumna dodatnia płytki -> Przycisk (po jednej stronie rynienki płytki) -> GPIO (po drugiej stronie)
Mój kod będzie używał GPIO 16 dla przycisku odtwarzania, GPIO 2 dla przycisku pauzy i GPIO 15 dla przycisku pomijania ścieżki.
Konfiguracja IFTTT do sterowania Spotify
Musimy stworzyć trzy aplety, po jednym dla funkcji odtwarzania, pauzy i pomijania.
Jeśli masz wersję premium IFTTT, prawdopodobnie możesz użyć filtrów JavaScript, aby zawrzeć to wszystko w jednej aplikacji. Ale ponieważ tego nie robimy, potrzebujemy każdego apletu.
Po zalogowaniu kliknij "Utwórz" w prawym górnym rogu menu głównego.
Na pasku "Jeśli to" kliknij go i wyszukaj Webhooks.
Następnie kliknij "Receive a web request" (nie drugą opcję, która ma "with a JSON payload").
Jako nazwę zdarzenia wpisz spotify_skip.
Będziesz musiał powtórzyć ten krok jeszcze dwa razy dla spotify_pause oraz spotify_play po zakończeniu tworzenia tego apletu.
Gdy to zrobisz, przejdź do "Więc to" i kliknij go. Wyszukaj "Spotify".
Będziesz musiał raz autoryzować IFTTT, aby połączyć się ze Spotify.
Jeśli wykonujesz spotify_skip będziesz chciał kliknąć "Pomiń ścieżkę". Jeśli jednak tworzysz aplet w celu wykonania innej akcji, powyższy obrazek pokaże ci, którego z nich użyć.
Po utworzeniu wszystkich trzech apletów nadszedł czas na kodowanie!
Kodowanie pilota Spotify dla Pico W
Po pierwsze, musisz znać punkt końcowy, który chcesz osiągnąć.
Przejdź do tej strony i kliknij przycisk Dokumentacja.
Zobaczysz tam swój klucz. Jeśli wykonałeś wszystkie powyższe kroki, różnica między twoim punktem końcowym a moim to twój klucz. Stąd,
Punkt końcowy odtwarzania: https://maker.ifttt.com/trigger/spotify_play/with/key/[your_key_here]
Pauza: https://maker.ifttt.com/trigger/spotify_pause/with/key/[your_key_here]
Pomiń: https://maker.ifttt.com/trigger/spotify_skip/with/key/[your_key_here]
Kod
from machine import Pin
from wifi import init_wifi
import urequests
import time
init_wifi()
play_btn = Pin(16, Pin.IN, Pin.PULL_DOWN)
pause_btn = Pin(2, Pin.IN, Pin.PULL_DOWN)
skip_btn = Pin(15, Pin.IN, Pin.PULL_DOWN)
def play():
request_url = 'https://maker.ifttt.com/trigger/spotify_play/with/key/[your_key_here]'
res = urequests.post(request_url)
# print response from IFTTT.
print(res.text)
def pause():
request_url = 'https://maker.ifttt.com/trigger/spotify_pause/with/key/[your_key_here]'
res = urequests.post(request_url)
# print response from IFTTT.
print(res.text)
def skip():
request_url = 'https://maker.ifttt.com/trigger/spotify_skip/with/key/[your_key_here]'
res = urequests.post(request_url)
# print response from IFTTT.
print(res.text)
try:
while True:
if play_btn():
print('play btn')
play()
time.sleep(0.25)
if pause_btn():
print('pause btn')
pause()
time.sleep(0.25)
if skip_btn():
skip()
print('skip')
time.sleep(0.25)
except Exception as e:
print(e)
request_url = 'https://maker.ifttt.com/trigger/error/with/key/[your_key_here]'
post_data = ujson.dumps({"value1": str(e)})
urequests.post(request_url, headers={
'content-type': 'application/json'}, data=post_data)
Przejdźmy przez kod.
Należy pamiętać, że konieczna będzie wymiana [your_key_here] za pomocą rzeczywistego klucza, uzyskanego za pośrednictwem Dokumentacja link.
Najpierw deklarujemy zmienne dla przycisków.
play_btn = Pin(16, Pin.IN, Pin.PULL_DOWN)
pause_btn = Pin(2, Pin.IN, Pin.PULL_DOWN)
skip_btn = Pin(15, Pin.IN, Pin.PULL_DOWN)
Obecnie, jeśli nie naciśniesz przycisku, zmienna będzie miała wartość 0. Jeśli go naciśniesz, stanie się 1. To jest to, czego użyjemy do uruchomienia funkcji play() , pause() oraz skip() funkcje.
Następnie tworzymy funkcje dla punktów końcowych odtwarzania, pauzy i pomijania. Ogólny szablon wygląda następująco:
def play():
request_url = 'https://maker.ifttt.com/trigger/spotify_play/with/key/[your_key_here]'
res = urequests.post(request_url)
# print response from IFTTT.
print(res.text)
To całkiem proste. Jeśli ta funkcja zostanie uruchomiona, wyśle żądanie POST do IFTTT. Wysłanie żądania GET nie zadziała.
Następnie mamy blok try/except.
try:
while True:
if play_btn():
print('play btn')
play()
time.sleep(0.25)
if pause_btn():
print('pause btn')
pause()
time.sleep(0.25)
if skip_btn():
skip()
print('skip')
time.sleep(0.25)
except Exception as e:
print(e)
request_url = 'https://maker.ifttt.com/trigger/error/with/key/[your_key_here]'
post_data = ujson.dumps({"value1": str(e)})
urequests.post(request_url, headers={
'content-type': 'application/json'}, data=post_data)
Jeśli przycisk zostanie naciśnięty, kod uruchomi odpowiednią funkcję. Na przykład naciśnięcie przycisku pomijania spowoduje uruchomienie funkcji skip().
A time.sleep(0.25) spowoduje wstrzymanie funkcji na 250 ms. Bez tego nawet krótkie naciśnięcie przycisku może spowodować przeciążenie i awarię Pico W.
Strona z wyjątkiem jest opcjonalny, ale zrobiłem to, ponieważ miałem już aplet "error" na IFTTT. Jeśli postępowałeś zgodnie z poprzednim samouczkiem, mogłeś go użyć.
Zasadniczo wysyła komunikat o błędzie, edo IFTTT, dzięki czemu otrzymasz komunikat o błędzie jako powiadomienie aplikacji telefonicznej.
Dlaczego to nie działa?
Korzystanie z IFTTT jako medium do kontrolowania Spotify jest łatwe, ale ma pewne wady.
Najpierw należy uruchomić muzykę w zwykły sposób
Jeśli próbowałeś nacisnąć przycisk odtwarzania na Pico W i oczekiwałeś, że muzyka zacznie grać... cóż, nic się nie dzieje.
Rozwiązaniem jest normalne uruchomienie muzyki na komputerze lub telefonie. Należy przejść do aplikacji i nacisnąć przycisk odtwarzania.
Myślę, że to deklaruje, które urządzenie jest aktywne. Gdy to zrobisz, będziesz mógł używać pilota Pico W Spotify.
Powolne odpowiedzi
Od naciśnięcia przycisku do reakcji mija kilka sekund. Niestety, tak to już jest.
Możesz zapłacić za aktualizację IFTTT, aby uzyskać szybszą reakcję. Przynajmniej to obiecują za twoje pieniądze.
Czy istnieje bezpośredni sposób na podłączenie Spotify?
Tak! Spotify posiada API, z którym można się połączyć.
Daje to znacznie większą kontrolę. Można dodać pokrętło do sterowania głośnością. Można dodać ekran LCD, aby pokazać, co jest odtwarzane. Sprawdź konsolę Spotify tutaj.
Niesamowite, ale też znacznie trudniejsze do zaprogramowania, zwłaszcza na Pico W.
IFTTT sprawia, że wszystko jest łatwe, ponieważ wykonuje wszystkie ciężkie zadania. Jeśli chcesz być tym ciężkim, sprawdź przepływ uwierzytelniania.
Oczywiście, jesteśmy entuzjastami Raspberry Pi. Ktoś tam to zrobi. Czy to powinieneś być ty? A może ja? Skomentuj poniżej.
Steruj swoim Pico W bezprzewodowo za pomocą PiCockpit!
Możesz kontrolować i uzyskiwać dane ze swojego Pico W bezprzewodowo za pomocą PiCockpit.
PiCockpit pozwala uzyskać wartości, kontrolować i używać PWM poprzez GUI za pośrednictwem swojego apletu GPIO.
Możesz również zobaczyć statystyki swojego Pico W poprzez aplet PiStats.
Integracja PiCockpit z Pico W jest super prosta.
Postępuj zgodnie z tym poradnikiem.
Napisz jeszcze mniej kodu dzięki PiCockpit i Pico W
PiCockpit ułatwia sterowanie pinami GPIO bez konieczności pisania jakiegokolwiek kodu.
Jeśli spojrzysz na samouczek nr 2Zauważ, jak dużo kodu jest potrzebne tylko do przełączenia diody LED.
Dzięki naszej nowej integracji z Pico W, PiCockpit czyni to o wiele łatwiejszym, ponieważ nie musisz niczego programować. Nawet konfiguracja WiFi - to jest zrobione za pomocą naszego kreatora konfiguracji.
10. Proste sterowanie diodami LED za pomocą PiCockpit i Pico W
Jeśli masz swoją diodę skonfigurowaną dokładnie tak, jak zrobiłem to w tutorialu nr 2, to pozostaje tylko skonfigurować ją na PiCockpit.
Jeśli kodujesz, zadeklarujesz, na którym pinie znajduje się Twoja dioda, używając led = machine.Pin(2, machine.Pin.OUT)
Na PiCockpicie wchodzisz w swój aplet GPIO, i przewijasz do "GPIO Output (On/Off)".
Wybierz BCM02 z rozwijanego menu, ponieważ twoja dioda jest na GPIO 2.
Następnie w kolumnie "Control" przełączamy przełącznik, aby włączyć diodę.
Możesz również łatwo użyć sekcji Software PWM poniżej, aby kontrolować jasność swojej diody LED.
Zauważ, że będziesz musiał usunąć poprzednie ustawienie, ponieważ nie możesz mieć dwóch wyjść na tym samym GPIO.
Gdy będziesz przesuwał suwak "Control", zauważysz, że jasność diody LED zmienia się.
11. Pico W, wentylator 5V i tranzystor, sterowany przez PiCockpit
Spróbujmy czegoś nieco bardziej kompleksowego, ale wykorzystującego ten sam przełącznik GPIO Output.
Aby zilustrować niektóre przypadki użycia w świecie rzeczywistym, będę zasilał wentylator 5V za pomocą PiCockpit.
Jest to wentylator o niskiej mocy 5V pobrany z mojego Raspberry Pi 4, więc mieści się w możliwościach wyjściowych Raspberry Pi Pico W.
To powiedziawszy, ponieważ jest to wentylator 5V, nie mogę użyć pinu GPIO. W mniej energochłonnych komponentach, takich jak diody LED, możesz mieć GPIO do podwójnego zadania dostarczania zasilania do komponentu i bycia "przełącznikiem", który włącza i wyłącza go.
Ale wentylator 5V wymagałby zbyt wysokiego napięcia. Więc kolejnym najlepszym sposobem jest umieszczenie tranzystora w środku.
Dzięki temu mogę dostarczyć 5V do wentylatora, jednocześnie zapewniając sobie możliwość jego włączenia i wyłączenia.
Po raz kolejny, ze względu na PiCockpit, zrobiłem zero programowania. Zrobiłem tylko hardware, który jest okablowany w następujący sposób:
Jest to wentylator 5V/0,12A, podłączony do 5V na dodatnim końcu (czerwony przewód), a ujemny przewód idzie do nogi emiterowej tranzystora.
Tranzystor jest tranzystorem PN2222 (NPN), co oznacza, że włącza się, gdy otrzyma sygnał wysoki.
Od lewej do prawej, z półokrągłą częścią skierowaną od ciebie, nogi to Emiter, Base i Collector.
Nóżka Base jest podłączona do rezystora 1K, a następnie podłączona do GPIO 15.
Noga Collector jest podłączona do masy.
Konfiguracja PiCockpit do pracy z tranzystorem
Po raz kolejny super proste.
Przejdź do rozwijanego menu w sekcji GPIO Output i dodaj BCM15.
Gdy już jest, możesz kliknąć strzałkę w dół i zmienić nazwy stanów na "fan off" i "fan on".
Przełącz przełącznik sterujący i powinieneś zobaczyć, że wentylator się włącza.
Możesz również użyć PiStats, aby zobaczyć spadek temperatur na swojej płycie.
Wyświetlanie fotorezystora za pomocą MQTT i Node-RED z Pico W.
Głównym celem tego samouczka jest wprowadzenie do MQTT.
W poprzednich samouczkach pokazałem, jak można używać Pico W do dostarczania danych, ale co zrobić, jeśli chcesz mieć centralne repozytorium danych w chmurze?
HiveMQ Cloud to darmowa usługa, którą możemy wykorzystać do osiągnięcia tego celu. Korzystając z cudzych komputerów, możemy również odciążyć Pico W.
Co więcej, MQTT ma duże zalety w porównaniu z poprzednimi metodami. Po pierwsze, jest o wiele bardziej wydajny w wysyłaniu małych danych. Nagłówki protokołu MQTT mają rozmiar 2 bajtów. HTTP jest około 4000 razy większy.
Zmniejszenie obciążenia lokalnego przetwarzania i obciążenia sieci oznacza dłuższą żywotność baterii dla Pico W, co jest idealne dla projektów zasilanych bateryjnie lub słonecznie.
Połączenie fotorezystora z Pico W
Fotorezystor (fotokomórka) jest bardzo łatwy do podłączenia.
Umieść fotorezystor w centralnej rynience płytki drukowanej.
Następnie podłącz pin 3V3 do jednej strony fotorezystora.
Będziesz chciał podłączyć pin ADC do drugiej strony fotorezystora, więc podłącz GPIO 26.
Na koniec podłącz rezystor 10K omów od masy do fotokomórki.
Chmura HiveMQ i kodowanie Pico W
Na początek, Zarejestruj się w usłudze HiveMQ Cloud tutaj.
Przejdź przez konfigurację i utwórz klaster. Zostaniesz poproszony o wybranie AWS lub Azure. Dla naszych celów nie ma różnicy.
Następnie kliknij "Zarządzaj klastrem".
Zanotuj adres URL klastra i kliknij Zarządzanie dostępem, aby utworzyć nowego użytkownika. Przejdź przez kolejne kroki i utwórz nowego użytkownika.
Dzięki tym szczegółom można teraz zaprogramować Pico W do wysyłania tam danych.
Kodowanie Pico W w celu odbierania danych fotokomórki i MQTTClient
from machine import Pin, ADC
from wifi import init_wifi
import time
from umqtt.simple import MQTTClient
init_wifi()
photoresistor = ADC(Pin(26))
def readLight():
light = photoresistor.read_u16()
return light
# Connect MQTT
def connectMQTT():
client = MQTTClient(client_id=b"[your_client_id]",
server=b"[your-host-name]",
port=0,
user=b"[your-user]",
password=b"[your-pw]",
keepalive=7200,
ssl=True,
ssl_params={
'server_hostname': '[your-host-name]'}
)
client.connect()
return client
client = connectMQTT()
def publish(topic, value):
print(topic)
print(value)
client.publish(topic, value)
print("data published")
while True:
brightness = str(readLight()) #to publish, must send string
print(brightness)
publish('picow/brightness', brightness)
time.sleep(0.1)
Najpierw uporządkujmy nasz import.
from machine import Pin, ADC
from wifi import init_wifi
import time
from umqtt.simple import MQTTClient
Strona wifi
import pochodzi z poprzednich samouczków.
Potrzebna będzie biblioteka umqtt.simple, która można pobrać tutaj.
Po pobraniu możesz przesłać go na swoją płytę (przewodnik tutaj).
Pliki te powinny znajdować się na urządzeniu Pico W.
Następnie utwórz funkcję pobierającą odczyt z fotorezystora:
photoresistor = ADC(Pin(26))
def readLight():
light = photoresistor.read_u16()
return light
Zwraca wartość do 65535. Im jaśniejszy, tym wyższa wartość.
Łączenie z HiveMQ
Aby połączyć się z HiveMQ, należy wysłać pewne parametry do klasy MQTTClient.
# Connect MQTT
def connectMQTT():
client = MQTTClient(client_id=b"[your_client_id]",
server=b"[your-host-name]",
port=0,
user=b"[your-user]",
password=b"[your-pw]",
keepalive=7200,
ssl=True,
ssl_params={
'server_hostname': '[your-host-name]'}
)
client.connect()
return client
client = connectMQTT()
Zastąp [your-host-name] adresem znalezionym na pulpicie nawigacyjnym. Będziesz musiał zrobić to dwa razy, raz dla server
a drugi dla server_hostname
. Zastąp również [your_client_id] nazwą urządzenia, taką jak "your_picow".
Następnie zastąp [your-user]
oraz [your-pw]
z użytkownikiem utworzonym na stronie Access Management (zrzut ekranu strony Access Management poniżej).
Dla porównania, funkcja ta wysyła dane do HiveMQ:
def publish(topic, value):
print(topic)
print(value)
client.publish(topic, value)
print("data published")
Nazwijmy to w naszym while
pętla:
while True:
brightness = str(readLight()) #to publish, must send string
print(brightness)
publish('picow/brightness', brightness)
time.sleep(0.1)
Podczas publikowania należy wysyłać ciągi znaków, dlatego też brightness = str(readLight())
jest tam.
Jeśli wyślesz liczby całkowite lub zmiennoprzecinkowe, program umrze.
W funkcji publikowania nadaj swojemu tematowi nazwę. Powiedz, picow/brightness
, a następnie dodaj wartość, którą chcesz wysłać. W tym przypadku chcemy wysłać ciąg znaków odczytu światła, brightness
.
Po zalogowaniu się na karcie Web Client powinieneś być w stanie zobaczyć publikowane dane.
Node-RED
To tylko liczby online, które mogą wydawać się bełkotem. A co jeśli chciałbyś uzyskać dostęp do danych w chmurze HiveMQ i zaprezentować je graficznie?
Zamiast tworzyć własne, można po prostu użyć Node-RED.
Node-RED ułatwia pobieranie danych z HiveMQ, a następnie prezentowanie ich za pomocą graficznych reprezentacji.
Stworzymy miernik przy użyciu Node-RED.
Aby rozpocząć, będziesz potrzebować nodejs. Sprawdź dokumentację HiveMQ aby sprawdzić, która wersja jest zalecana.
Po zainstalowaniu Node należy otworzyć wiersz poleceń/terminal i uruchomić poniższe polecenia (wyłącz sudo, jeśli korzystasz z systemu Windows):
sudo npm install -g --unsafe-perm node-red
Spowoduje to użycie menedżera pakietów node (npm) do globalnej instalacji Node-RED.
Następnie uruchom Node-RED wpisując node-red
w wierszu polecenia terminala.
Otwórz przeglądarkę i przejdź do http://127.0.0.1:1880 lub inny adres podany w terminalu.
Zbudujmy przepływ. Przeciągnij "mqtt in" na płótno. Można go znaleźć w zakładce "network" na lewym pasku bocznym.
Będziemy musieli skonfigurować kartę, więc kliknij dwukrotnie prostokąt i wykonaj następujące czynności:
W polu "temat" upewnij się, że dodałeś obraz/jasność, ponieważ to właśnie opublikowałeś z Pico W.
W sekcji "Serwer" dodaj nowy, klikając ikonę ołówka, a zostaniesz przeniesiony do następnego menu.
Wstaw nowy adres serwera i zmień port na 8883. Zaznacz "Użyj TLS", ale nie przejmuj się dodawaniem nowej konfiguracji tls.
Następnie przejdź do zakładki bezpieczeństwa i dodaj swoje dane logowania.
Wszystkie te szczegóły można znaleźć w kodzie podczas inicjalizacji MQTTClient.
Dodawanie wskaźnika
Aby dodać miernik, musisz mieć ustawioną opcję node-red-dashboard.
Na lewym pasku bocznym, jeśli ich nie widzisz:
Następnie przejdź do menu (prawy górny przycisk) -> Zarządzaj paletą. Następnie przejdź do zakładki Install i wyszukaj node-red-dashboard. Kliknij "Zainstaluj".
Przeciągnij i upuść "wskaźnik" na prawo od ikony mqtt in prostokąt i połącz je, przeciągając linię z pozycji mqtt in do miernika.
Kliknij dwukrotnie prostokąt miernika i zmień etykietę na "jasność", a "zakres" na maks. 65535.
Świetnie. Teraz naciśnijmy "Deploy".
Jeśli ustawienia były prawidłowe, pod prostokątem pojawi się zielone kółko i napis "connected". Jeśli nie, terminal poda więcej szczegółów na temat przyczyny błędu.
Gdy Pico W dostarcza dane do chmury HiveMQ, nadszedł czas, aby sprawdzić pulpit nawigacyjny. Odwiedź http://127.0.0.1:1880/ui i powinieneś zobaczyć, że wskaźnik jest często aktualizowany.
Twoje sugestie są mile widziane.
Zostaw komentarz w polu komentarzy poniżej!
Witam,
Dziękujemy za podzielenie się z nami swoją wiedzą.
Czy możesz doradzić, czy ćwiczenia WiFi są dostępne tylko w sieci? Nie byłem w stanie uzyskać dostępu do Pico W, jeśli jestem w innej sieci WiFi. Jeśli tak, czy masz jakieś przykłady dostępu poza siecią?
Dziękuję.
Tak, ze względu na naturę sieci, routerów i zapór sieciowych ćwiczenia te działają tylko w obrębie tej samej sieci WiFi.
PiCockpit sam w sobie jest rozwiązaniem wykraczającym poza sieć - dostęp do Pico W można uzyskać z dowolnego miejsca w Internecie.
Pracujemy nad wprowadzeniem większej liczby funkcji do platformy.
Jeśli chcesz odtworzyć coś takiego samodzielnie, musiałbyś mieć jakieś rozwiązanie tunelowania do swojej sieci, serwer przekaźnikowy lub coś w tym rodzaju.
Oferujemy usługi konsultingowe, jeśli chcesz zagłębić się w ten temat.
Dziękuję za ten świetny poradnik.
Niestety nie działa.
Utknąłem na końcu części "1. Wyświetl stronę internetową z napisem "Hello World" na Pico".
Moje przeglądarki Firefox i Chrome informują mnie tylko o "przerwaniu połączenia z błędem".
W Thonny widzę
Połączony
ip = 192.168.188.198
Nasłuchiwanie na ('0.0.0.0', 80)
Klient połączył się z ('192.168.188.100', 54025)
Połączenie zamknięte
Zamknięcie połączenia następuje kilka razy.
Co mogę zmodyfikować, aby mój Pico W działał?
Z góry dziękuję za pomoc.
Pozdrawiam Pete
Podczas uruchamiania main.py pojawia się komunikat o błędzie, jak mogę go rozwiązać.
Plik "", linia 1, w
ImportError: brak modułu o nazwie 'wifi'
z góry dziękuję.
Musisz utworzyć i dodać wifi.py - który jest pokazany nieco wyżej na stronie. Bez wifi.py kod nie będzie działał.
"Samouczek dotyczący komponentów Raspberry Pi Pico W dla początkujących" to fantastyczny przewodnik dla tych, którzy dopiero zaczynają przygodę z platformą Raspberry Pi Pico W. Samouczek jest dobrze skonstruowany i łatwy do naśladowania, dzięki czemu jest idealny dla początkujących. Obejmuje niezbędne komponenty i zawiera jasne instrukcje, dzięki czemu jest doskonałym punktem wyjścia dla każdego, kto chce poznać tę technologię. Włączenie szczegółowych wyjaśnień i obrazów zwiększa doświadczenie w nauce, zapewniając czytelnikom szybkie zrozumienie pojęć. Ogólnie rzecz biorąc, ten samouczek jest cennym źródłem informacji dla tych, którzy chcą rozpocząć pracę z Raspberry Pi Pico W i jego komponentami.