Σεμινάριο εξαρτημάτων Raspberry Pi Pico W για αρχάριους

raspberry pi pico w συστατικά φροντιστήριο

Αυτό το σεμινάριο για τα εξαρτήματα του Raspberry Pi Pico W για αρχάριους θα σας διδάξει πώς να αλληλεπιδράσετε με τον μικροελεγκτή για να αλληλεπιδράσετε με απλά εξαρτήματα όπως LED, αισθητήρες υπερήχων και πολλά άλλα στοιχεία που βρίσκονται σε ένα σετ για αρχάριους.

Αν είστε εντελώς αρχάριος, αυτό το σεμινάριο θα σας βοηθήσει να κατανοήσετε το MicroPython ώστε να μπορείτε να διαβάζετε, να γράφετε και να τροποποιείτε κώδικα. Με αυτές τις γνώσεις, μπορείτε να συνδυάσετε κώδικα και στοιχεία για να δημιουργήσετε κάτι που έχει μια πραγματική περίπτωση χρήσης.

Αν έρχεστε από ένα Pico, αυτό το σεμινάριο θα σας διδάξει πώς να ελέγχετε το Pico W ασύρματα. Προηγουμένως, μπορούσατε να αλληλεπιδράσετε με το Pico μόνο μέσω ενός διακόπτη, ενός κουμπιού ή κάποιας φυσικής συσκευής αλληλεπίδρασης. Όχι πια! Τώρα μπορείτε να ελέγχετε τα εξαρτήματα με το τηλέφωνό σας ή την επιφάνεια εργασίας σας.

Ροή σεμιναρίου

Εισαγωγή

  1. Συγκόλληση ακροδεκτών κεφαλής
  2. Χρησιμοποιώντας το Thonny
  3. Ενημέρωση του υλικολογισμικού σας

Το σεμινάριο Hello World για το Pico W

  1. Εκτελέστε μια ιστοσελίδα που λέει "Hello World" στο Pico
  2. Ασύρματος έλεγχος ενός LED

Ένα βήμα πιο πάνω

  1. Έλεγχος RGB LED ασύρματα
  2. Λειτουργία βομβητή στο Pico W

Βασικοί τρόποι μετάδοσης δεδομένων από αισθητήρα

  1. Αισθητήρας υπερήχων Pico W και HC-SR04
  2. Μετάδοση μιας ιστοσελίδας με δεδομένα αισθητήρα
  3. Μείωση του ωφέλιμου φορτίου με AJAX
  4. Το Pimoroni Phew για να βελτιώσει την κωδικοποίηση του τελικού σημείου

Σύνδεση σε βοηθητικές υπηρεσίες ιστού

  1. Καταγραφή δεδομένων κλίματος αισθητήρα DHT22 σε φύλλα Google με το IFTTT
  2. Κατασκευάστε ένα τηλεχειριστήριο Spotify με λειτουργίες αναπαραγωγής/παύσης/μετακίνησης

Έλεγχος GPIO χωρίς κώδικα με το PiCockpit

  1. Σούπερ απλή εγκατάσταση του PiCockpit στο Pico W
  2. Απλός έλεγχος LED με PiCockpit και Pico W
  3. Pico W, ανεμιστήρας 5V και ένα τρανζίστορ, ελεγχόμενο από το PiCockpit

MQTT

  1. Φωτοαντίσταση οθόνης με χρήση MQTT και Node-RED με Pico W

Πίνακας περιεχομένων

Περιεχόμενα απόκρυψη

Οι στόχοι του σεμιναρίου συνοπτικά

  • Μάθετε πώς να αλληλεπιδράτε με τα θεμελιώδη στοιχεία που συνθέτουν μεγαλύτερα έργα
  • Ελέγξτε όλα αυτά ασύρματα - χωρίς διακόπτες, κουμπιά ή άλλες συσκευές αλληλεπίδρασης.
  • Καλύτερη κατανόηση των πλεονεκτημάτων του Pico W

Σημαντικοί σύνδεσμοι

Github repo για τον κώδικα του σεμιναρίου (εκτός από το secrets.py)

Τεκμηρίωση MicroPython

Λάθη, προτάσεις, σχόλια; Αφήστε ένα σχόλιο στο παρακάτω πλαίσιο σχολίων, στείλτε μου email ή Tweet me.

OSError: [Errno 98] EADDRINUSE

Αν λάβετε αυτό το σφάλμα, απλά αποσυνδέστε και συνδέστε το Raspberry Pi Pico.

Μπορείτε επίσης να το κάνετε αυτό πληκτρολογώντας αυτές τις εντολές στο κέλυφος του Thonny:

import machine
machine.reset()

Αποτέλεσμα:

Συγκόλληση ακροδεκτών κεφαλής

Όταν αγοράζετε ένα Raspberry Pi Pico W, μπορεί να μην συνοδεύεται από ακροδέκτες που θα σας επιτρέψουν να συνδέσετε εξαρτήματα στο Pico.

Τη στιγμή που γράφονται αυτές οι γραμμές, το Pico WH (H για κεφαλίδες) δεν έχει κυκλοφορήσει. Το mega-άρθρο μας για το Pico W παρακολουθεί την κυκλοφορία του.

Αν, ωστόσο, μπορείτε να βρείτε ένα Pico W με προ-συγκολλημένες ακροδέκτες, θα σας συμβούλευα να αγοράσετε αυτό.

Παρ' όλα αυτά, για τους υπόλοιπους από εμάς, η συγκόλληση κεφαλίδων στο Pico W είναι κάτι απλό. Θα χρειαστείτε:

  • Breadboard
  • Σίδερο συγκόλλησης και κόλληση
  • Κεφαλίδες

Όταν αγοράζετε τις κεφαλίδες σας, βεβαιωθείτε ότι αγοράζετε μία που προορίζεται για το Pico W. Σε αντίθεση με τις κεφαλίδες για τη σειρά Raspberry Pi Zero, οι κεφαλίδες του Pico W δεν είναι δίπλα-δίπλα. Βρίσκονται στα αντίθετα άκρα της πλακέτας.

Ένα breadboard, το Pico W και ακροδέκτες 2×20 pin

Οι ακίδες έχουν μια μακριά και μια κοντή πλευρά. Θα θέλετε οι μακρύτερες ακίδες να είναι στην πλευρά όπου βλέπετε τις ετικέτες GPIO (GP0, GP1, GND, VBUS, VSYS, κλπ.)

Θα θέλετε οι μεγαλύτερες ακίδες να βρίσκονται στην πλευρά που βρίσκεται απέναντι από το βύσμα USB.

Επομένως, τοποθετήστε τους μακρύτερους ακροδέκτες στην πλακέτα ψωμιού. Θα χρειαστείτε τέσσερις οπές και ένα διάκενο μεταξύ τους. Αν δεν είστε σίγουροι, δοκιμάστε με το Pico W.

Η συγκόλληση είναι εύκολη. Βεβαιωθείτε ότι το κολλητήρι σας είναι καυτό και βεβαιωθείτε ότι χρησιμοποιείτε την άκρη του κολλητηριού.

Αυτό που βρήκα πιο αποτελεσματικό ήταν να φέρω την άκρη του κολλητήριου κοντά στον ακροδέκτη, να ακουμπήσω την άκρη με την κόλληση και να την δω να ρέει στον ακροδέκτη και να δημιουργεί μια σύνδεση.

Μετά τη συγκόλληση, βεβαιωθείτε ότι δεν υπάρχει ξένη κόλληση που θα μπορούσε να συνδέει δύο ακίδες GPIO μεταξύ τους ή κάποια περισσευούμενη κόλληση που έχει απομείνει στην πλακέτα σας.

Χρησιμοποιήστε το Thonny ως επεξεργαστή κώδικα

Thonny προγραμματισμός ενός Raspberry Pi Pico W

Το Thonny παραμένει ο ευκολότερος τρόπος για να προγραμματίσετε το Raspberry Pi Pico W.

Αν χρησιμοποιείτε το λειτουργικό σύστημα Raspberry Pi, θα το έχετε ήδη εγκαταστήσει.

Ωστόσο, αν χρησιμοποιείτε Windows ή Mac, θα πρέπει να το κατεβάσετε και να το ρυθμίσετε.

Ακολουθεί ένας οδηγός που θα σας καθοδηγήσει στα βήματα.

Φροντίστε επίσης να ανατρέξτε στον οδηγό για το πώς να ανεβάσετε αρχεία στο Pico W.

Ενημερώστε το υλικολογισμικό σας μεταφορτώνοντας το πιο πρόσφατο UF2

Όταν αγοράσατε το Pico W, μπορεί να έχετε ήδη το ξεπερασμένο υλικολογισμικό.

Πολλές αλλαγές έρχονται στο Pico W, οπότε είναι ιδανικό να ενημερώσετε το υλικολογισμικό σας τώρα.

Ορισμένες αλλαγές που έχω δει από την ημέρα της κυκλοφορίας είναι βελτιώσεις στη λειτουργία του σημείου πρόσβασης WLAN, ενώ μελλοντικές ενημερώσεις θα μπορούσαν να ξεκλειδώσουν τη λειτουργία Bluetooth στην πλακέτα.

Ενημέρωση τώρα! Εδώ είναι ένας οδηγός στο mega-άρθρο μας.


1. Εκτελέστε μια ιστοσελίδα που λέει "Hello World" στο Pico

Το έργο "Hello World" του Raspberry Pi Pico W

Ένα από τα πιο βασικά έργα σε όλα τα σεμινάρια προγραμματισμού είναι το έργο "Hello World".

Το "Hello World" ενός μικροελεγκτή περιλαμβάνει συνήθως το αναβοσβήσιμο μιας λυχνίας LED. Είναι πανεύκολο. Ακούστε πώς.

Ωστόσο, δεδομένου ότι το Pico W μπορεί να εξυπηρετήσει μια ιστοσελίδα, ας ξεκινήσουμε μαθαίνοντας πώς να εξυπηρετούμε μια ιστοσελίδα που περιέχει ένα μήνυμα "Hello World".

Η ρύθμιση που χρησιμοποιείται εδώ θα αποτελέσει το βασικότερο δομικό στοιχείο για τα υπόλοιπα σεμινάρια.

Υπάρχουν δύο τρόποι για να συνδεθείτε στο Pico W. Μπορείτε να το βάλετε να συνδεθεί σε ένα δίκτυο WiFi ή μπορείτε να μεταδίδει ένα hotspot SoftAP παρόμοιο με αυτό που κάνει το smartphone σας. Αν θέλετε να δοκιμάσετε το τελευταίο, ακολουθήστε αυτόν τον σύνδεσμο. Ωστόσο, για λόγους συνέπειας σε αυτό το σεμινάριο, θα συνδεόμαστε πάντα σε ένα δίκτυο WiFi και όχι σε ένα δίκτυο μετάδοσης από το Pico W.

Έτσι, βασικά, τα βήματα για την εξυπηρέτηση μιας ιστοσελίδας περιλαμβάνουν:

  • Σύνδεση στο WiFi
  • Γράφοντας κώδικα για να σερβίρουμε το index.html σε οποιονδήποτε συνδέεται στη διεύθυνση IP του Pico W

Ας ρυθμίσουμε μερικά αρχεία. Αποθηκεύστε τα και μεταφορτώστε τα στο Raspberry Pi Pico W. Εδώ είναι ο τρόπος μεταφόρτωσης αρχείων, σε περίπτωση που το χάσατε.

wifi.py

Το wifi.py είναι ένα boilerplate που προορίζεται να σας βοηθήσει να συνδεθείτε στο δίκτυο WiFi σας. Δημιουργώντας ένα ξεχωριστό αρχείο και εισάγοντας το στο main.py αρχείο αργότερα θα βοηθήσει στη μείωση του ακατάστατου κώδικα.

Σημειώστε ότι θα πρέπει να αλλάξετε τον κωδικό της χώρας σας στη γραμμή rp2.country('DE') εάν η χώρα σας δεν είναι η Γερμανία.

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])

secrets.py

wifi.py εισαγωγές secrets.py, όπου αποθηκεύετε τις πληροφορίες του δικτύου WiFi σας.

secrets.py είναι ένα απλό αρχείο JSON που περιέχει το SSID και τον κωδικό πρόσβασης του WiFi σας.

secrets = {
    'ssid': 'SM-A520W9371',
    'pw': 'starting',
    }

serve_webpage.py

Όπως υποδηλώνει και το όνομα, αυτή η σελίδα εξυπηρετεί τους χρήστες που συνδέονται στο Pico W.

Μόλις λάβει μια σύνδεση, το Pico W βρίσκει ένα αρχείο με όνομα index.html και το στέλνει στον συνδεδεμένο πελάτη, όπως φαίνεται στη γραμμή 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')

Τέλος, πρέπει να δημιουργήσουμε το index.html αρχείο που θα αποσταλεί σε έναν συνδεδεμένο πελάτη.

<!DOCTYPE html>
<html>
    <head>
        <title>Pico W</title>
    </head>
    <body>
        <h1>Hello World</h1>
    </body>
</html>

Αυτό είναι ένα απλό πρότυπο HTML με δύο αλλαγές: μία στο πεδίο <title>που βγάζει ως τίτλο "Pico W" και την ετικέτα <h1> που λέει "Hello World".

main.py

Εφόσον έχουμε τοποθετήσει όλο τον κώδικα αλλού, το main.py πρέπει απλώς να εισαγάγει και να καλέσει αυτές τις συναρτήσεις για να εξυπηρετήσει την ιστοσελίδα Hello World.

Όπως μπορείτε να δείτε, αρχικοποιούμε πρώτα το WiFi προτού εξυπηρετήσουμε την ιστοσελίδα.

from wifi import init_wifi
from serve_webpage import serve_webpage

init_wifi()
serve_webpage()

Σχεδόν φτάσατε!

Ανατρέχοντας στο παρακάτω στιγμιότυπο οθόνης, βεβαιωθείτε ότι:

  • Έχετε μεταφορτώσει πέντε αρχεία στο Raspberry Pi Pico W (βλέπε κάτω αριστερά κόκκινο πλαίσιο)
  • Βεβαιωθείτε ότι ο διερμηνέας σας έχει οριστεί σε MicroPython (Raspberry Pi Pico) (βλ. κάτω δεξιά πλαίσιο)
  • Στη συνέχεια, επισημάνετε το main.py στον επεξεργαστή κώδικα και κάντε κλικ στο πράσινο κουμπί run (πάνω αριστερά στο κόκκινο πλαίσιο).
  • Μόλις το εκτελέσετε, θα δείτε τη διεύθυνση IP σας στο Shell. Πηγαίνετε στο πρόγραμμα περιήγησής σας και πληκτρολογήστε αυτή τη διεύθυνση και θα δείτε την ιστοσελίδα Hello World.
  • Αν το Shell δεν είναι ανοιχτό, μεταβείτε στην επιλογή Προβολή -> Shell.

Αν όλα είναι επιτυχή, θα δείτε την παρακάτω σελίδα.


2. Ασύρματος έλεγχος ενός LED

Τώρα που έχετε δημιουργήσει τα βασικά, ας προχωρήσουμε ένα βήμα μπροστά.

Ένα από τα πιο βασικά έργα του Raspberry Pi περιλαμβάνει το αναβόσβημα μιας λυχνίας LED.

Ας το ανεβάσουμε λίγο παραπάνω, ελέγχοντας το LED ασύρματα. Θέλουμε να μπορούμε να αναβοσβήνουμε, να ενεργοποιούμε και να απενεργοποιούμε το LED.

Για να το κάνετε αυτό, θα πρέπει να δημιουργήσετε ένα κύκλωμα και έναν διακομιστή ιστού με τρία κουμπιά - ON, OFF, BLINK.

Για αυτό το έργο, θα χρειαστείτε μια λυχνία LED, μια αντίσταση 330 ωμ, ένα καλώδιο βραχυκυκλώματος και μια πλακέτα ψωμιού.

Θα χρησιμοποιήσουμε ένα κόκκινο LED επειδή τα περισσότερα κιτ το διαθέτουν. Σημειώστε ότι αν χρησιμοποιήσετε LED άλλου χρώματος, θα πρέπει να προσαρμόσετε την αντίσταση.

Ακολουθεί ο τρόπος σύνδεσης των εξαρτημάτων

  • GPIO 2 -> μακρύ σκέλος LED (άνοδος/θετικό)
  • GND -> αντίσταση 330 Ω -> βραχύ πόδι LED (κάθοδος/αρνητικό)

Κώδικας για τον έλεγχο του LED στο Pico W

Ας βασιστούμε σε αυτό που κάναμε στο προηγούμενο σεμινάριο. Τα μόνα δύο αρχεία που θα χρειαστεί να τροποποιήσουμε είναι τα εξής index.html για να προσθέσετε κουμπιά και main.py να αλληλεπιδράσει με το LED με βάση την είσοδο από το index.html.

Τα τμήματα με έντονη γραφή υποδεικνύουν τις νέες γραμμές που προστέθηκαν στο index.html. Προσθέτουν τρία κουμπιά και μια παράγραφο που λέει "Control the 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>&nbsp;
        <a href=\"?led=off\"><button>OFF</button></a>
        <a href=\"?led=blink\"><button>BLINK</button></a>
    </body>
</html>

Παρατηρήστε ότι όταν πατάτε τα κουμπιά, θα δείτε μια παράμετρο που προστίθεται στη διεύθυνση IP του Pico W (π.χ. http://192.168.43.134/%22?led=blink\). Αυτές οι παράμετροι συλλαμβάνονται από το backend του Pico W και ελέγχουν το LED.

Θα κινηθούμε serve_webpage.pyστον κώδικα του main.py αρχείο.

Εδώ είναι 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')

Το πρώτο, και βασικό, τμήμα είναι παρακάτω:

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()

Η μεταβλητή "request", όταν εκτυπωθεί, παράγει το πρώτο τμήμα του κειμένου που ακολουθεί. Οι τρεις τελευταίες γραμμές είναι οι εντολές εκτύπωσης που ελέγχουν αν το LED είναι ενεργοποιημένο, απενεργοποιημένο ή αναβοσβήνει:

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

Ο παραπάνω κώδικας θα προσπαθήσει να αναζητήσει συγκεκριμένες συμβολοσειρές όπως "led=on". Εάν υπάρχει, η τιμή θα είναι μεγαλύτερη από -1, επομένως θα ενεργοποιηθεί η σχετική εάν δήλωση.

Για παράδειγμα, εάν υπάρχει led=on στις παραμέτρους, τότε η μεταβλητή led_on θα είναι μεγαλύτερη από -1, επομένως η if led_on > -1 η δήλωση ενεργοποιεί και εκτελεί led.on();

Το μόνο περίπλοκο κομμάτι εδώ είναι το led_blink η οποία θα ενεργοποιήσει τη λειτουργία:

    def blink_led():
        led.on()
        time.sleep(0.2)
        led.off()
        time.sleep(0.2)

Τέλος, δείτε πώς αρχικοποιείτε το GPIO 2 για να λειτουργήσει η λυχνία LED:

import machine
import time
    
#LED controls
led = machine.Pin(2, machine.Pin.OUT)

Εισάγουμε μηχανή για να αλληλεπιδράσουμε με τον ακροδέκτη GPIO. Όπως μπορείτε να δείτε στη μεταβλητή led, θέλουμε το Pico W να τροφοδοτεί το GPIO 2.

Εισάγουμε χρόνος έτσι ώστε να μπορούμε να έχουμε μια παύση 0,2 δευτερολέπτων στο blink_led().


3. RGB LED στο Pico W

Για να ανάψετε το RGB LED σας, χρειάζεστε:

  • Τρεις αντιστάσεις 330 Ωm
  • Ένα LED RGB
  • Ένα καλώδιο βραχυκύκλωσης

Στο RGB LED, θα βρείτε τέσσερα πόδια. Το ένα πόδι θα είναι το μακρύτερο. Αυτό είναι είτε κάθοδος (αρνητικό) είτε άνοδος (θετικό). Το RGB LED μου είχε κοινή κάθοδο, οπότε εδώ είναι η σύνδεση:

Η εικόνα δείχνει τα σκέλη R, G, B σε ένα LED RGB κοινής καθόδου. (Εικόνα από Raspberry Pi Foundation CC-BY-SA)
  • GPIO 15 -> αντίσταση 330 ωμ -> κόκκινη λυχνία LED
  • GPIO 17 -> αντίσταση -> πράσινο LED
  • GPIO 16 -> αντίσταση -> μπλε LED

Εδώ είναι κάποιος κώδικας για να δείτε αν το έχετε συνδέσει σωστά:

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)

Σε αυτό το παράδειγμα, χρησιμοποιούμε το PWM, το οποίο σας επιτρέπει να μεταβάλλετε τη φωτεινότητα των LED R, G, B.

Μπορείτε να αλλάξετε τις τιμές που μεταβιβάζονται στο [color].duty_u16 σε μια τιμή μεταξύ 0 και 65534. Θεωρητικά, θα έπρεπε να μπορείτε να περάσετε την τιμή 65535, αλλά για κάποιο λόγο αυτό δεν φαίνεται να λειτουργεί για μένα.

Σκεφτείτε ότι περνώντας το "0" λέτε ότι θέλετε μηδέν τοις εκατό φωτεινότητα. Αν το περάσετε 65534, θέλετε 100 τοις εκατό φωτεινότητα.

Αν κάνετε 65534 για ένα χρώμα και μηδέν για τα υπόλοιπα, θα μπορείτε να καταλάβετε αν έχετε συνδέσει τους σωστούς ακροδέκτες GPIO με το σωστό χρώμα LED.

Γιατί λοιπόν χρησιμοποιούμε PWM; Επειδή θα σας βοηθήσει να αποκτήσετε περισσότερα χρώματα. Εάν χρησιμοποιείτε απλώς μια μέθοδο "on-and-off", μπορείτε να έχετε κόκκινο, πράσινο, μπλε, λευκό-χρωματικό και καθόλου φως. Με το PWM, μπορείτε να μεταβάλλετε την ένταση των LED R, G, B και να δημιουργήσετε όσα χρώματα μπορείτε να φανταστείτε.

Τώρα, ας δημιουργήσουμε κάτι που μπορείτε να ελέγχετε ασύρματα!

index.html

Η κύρια αλλαγή εδώ είναι να έχουμε ένα <form> το οποίο διαθέτει τρία ρυθμιστικά. Αυτά τα ρυθμιστικά έχουν μια τιμή μεταξύ μηδέν και 100.

Η χρήση τιμών από μηδέν έως 100 σας βοηθά να απεικονίσετε τη φωτεινότητα ως ποσοστό. Μειώνει επίσης την ποσότητα του κώδικα που απαιτείται για την ανάλυση της τιμής από τις παραμέτρους (βλ. αργότερα στην ενότητα main.py)

Όταν ρυθμίσετε τις τιμές για τις λυχνίες LED R, G, B, πατάτε submit και τα δεδομένα αυτά καταγράφονται από το 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')

Καθώς πατάτε το κουμπί υποβολής στο index.html ιστοσελίδα, το Pico W θα λάβει τις παραμέτρους και θα τις επεξεργαστεί.

Ας δούμε μερικά βασικά σημεία του κώδικα, που είναι γραμμένα με έντονη γραφή στο παραπάνω μπλοκ κώδικα.

συνάρτηση find_intensity

Αυτή η συνάρτηση λαμβάνει δύο παραμέτρους: χρώμα και request_str. χρώμα παίρνει το "red", "green" ή "blue" και βρίσκει την τιμή μετά το σύμβολο της ισότητας (=).

Για παράδειγμα, η διεύθυνση URL σας μετά την υποβολή της φόρμας είναι "http://192.168.1.142/?red=89&green=50&blue=50".

Αν δώσετε "red" στην find_intensity, θα επιστρέψει 89.

αναλυτής έντασης

Το δεύτερο έντονο μπλοκ κώδικα αντιπροσωπεύει τον κώδικα που λέει στο GPIO του Pico W πόση φωτεινότητα θέλετε από κάθε LED.

Πρώτα απ' όλα, πρέπει να βεβαιωθούμε ότι τα params υπάρχουν στη διεύθυνση URL. Αυτό γίνεται από την εντολή εάν δήλωση request_str.find('red') > -1. Απλά χρησιμοποίησα 'κόκκινο' επειδή τα params θα 100% περιέχουν το αλφαριθμητικό 'red' αν χρησιμοποιήσετε τη φόρμα.

Αν επισκέπτεστε τη διεύθυνση IP του Pico W (π.χ. http://192.168.1.142/) για πρώτη φορά, δεν θα έχετε τις παραμέτρους, οπότε το πρόγραμμα θα καταρρεύσει αν εκτελέσετε την εντολή find_intensity.

Εάν υπάρχουν params, βρίσκουμε την ένταση για κάθε LED σύμφωνα με τις τιμές που έχουν υποβληθεί. Ας ρίξουμε μια ματιά στο red_intensity.

red_intensity = int(find_intensity('red=', request_str) /100 * 65534)
...
red_led.duty_u16(red_intensity)

find_intensity επιστρέφει έναν ακέραιο αριθμό από μηδέν έως 100. Το διαιρούμε με το 100 ώστε να λάβετε ένα ποσοστό. Αυτό το ποσοστό διαιρεί τη μέγιστη τιμή που duty_u16 μέθοδος μπορεί να λάβει.

Ωστόσο, χρειαζόμαστε ένα int συνάρτηση για να το τυλίξετε αυτό επειδή μπορείτε να πάρετε μια float μερικές φορές και duty_u16 χρειάζεται ένα int. Για παράδειγμα, ας πούμε ότι θέλατε 41% φωτεινότητα - 41% των 65534 είναι 26.868,94. Δεν μπορείτε να περάσετε αυτό το float καθώς το πρόγραμμα θα καταρρεύσει.


4. Λειτουργία βομβητή στο Pico W

Ένας βομβητής είναι ένα αρκετά σημαντικό στοιχείο για βασικές ειδοποιήσεις, όπως ακριβώς ένα LED μπορεί να σας ενημερώσει για την κατάσταση κάποιου πράγματος, έτσι και ένας βομβητής σας δίνει μια ακουστική ειδοποίηση.

Συνδέστε τον θετικό ακροδέκτη του βομβητή στο GPIO 16 και γειώστε τον σε έναν ακροδέκτη GND του Pico W.

Αντί να εφαρμόσω τον δικό μου κώδικα, επέλεξα να χρησιμοποιήσω το Εφαρμογή του Giuseppe Cassibba. Αν εκτελέσατε τον κωδικό του στο Pico W, θα ακούσετε ηχητικά σήματα στο βομβητή σας.

Αλλά δεδομένου ότι αυτός ο κώδικας προορίζεται για το Pico, δεν θα έχει χαρακτηριστικά ασύρματης διαδραστικότητας.

Ας βγάλουμε λοιπόν το πιρούνι!

Πρώτα, ας τροποποιήσουμε το index.html για την υλοποίηση των κουμπιών. Ας έχουμε ένα κουμπί για "ON", "OFF", "SCALE", "MUSIC".

Τα δύο πρώτα κουμπιά είναι αυτονόητα. Το τρίτο κουμπί παίζει μια κλίμακα C και το τελευταίο παίζει ένα μουσικό κομμάτι.

<!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>&nbsp;
        <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>

Όπως και πριν, δημιουργούμε μερικά <button> ετικέτες με <a> ετικέτες που τα περιβάλλουν. Όταν κάνετε κλικ στα κουμπιά, η διεύθυνση URL θα έχει μια παράμετρο όπως /buzzer=on. Το Pico W διαβάζει αυτό το μήνυμα και ενεργοποιεί τον βομβητή.

Τώρα, ας δούμε τον κώδικα του Giuseppe για το 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()

Ο κώδικάς του παίζει μια κλίμακα C όταν εκτελείται χρησιμοποιώντας τη συνάρτηση buzzer(), η οποία λαμβάνει τέσσερις παραμέτρους: Διάρκεια ήχου και διάρκεια παύσης πριν από την αναπαραγωγή του επόμενου ήχου.

Ας τροποποιήσουμε τον κώδικα έτσι ώστε να μπορούμε να ενεργοποιήσουμε το ON, OFF, ΚΛΙΜΑΚΑ και ΜΟΥΣΙΚΗ.

Να πώς ενσωματώνουμε τον κώδικα του Giuseppe στο δικό μας 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')

Στην παραπάνω υλοποίηση, δεν έχουμε γράψει τον κώδικα για το ΜΟΥΣΙΚΗ.

Ο κώδικας είναι πολύ παρόμοιος με το παραπάνω σεμινάριο για τις κόκκινες λυχνίες LED, όπου το Pico W καταγράφει τις παραμέτρους μετά τη διεύθυνση IP του Pico W. Εάν η παράμετρος buzzer=ON, θα παίξει έναν ήχο 440Hz. Εάν buzzer=scale, θα παίξει την κλίμακα που προέρχεται από τον κώδικα του Giuseppe.

Τι γίνεται με την εφαρμογή της μουσικής; Η υλοποίηση της μουσικής είναι λίγο πιο περίπλοκη, οπότε θα πρέπει να δημιουργήσουμε ένα νέο αρχείο με όνομα constants.py και να προσθέσουμε μερικές γραμμές στο main.py.

Αυτός ο κώδικας είναι μια διακλάδωση από το Ο κώδικας Arduino του Rowan Packard.

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 (προσθήκες με έντονη γραφή)

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')

Όπως μπορείτε να δείτε, υπάρχουν δύο πίνακες, music_notes και ρυθμός. Στη συνέχεια, θα εκτελέσετε έναν βρόχο for για να βάλετε αυτές τις τιμές στο buzzer() λειτουργία. Επίσης, στην αρχή του κώδικα, εισάγουμε όλες τις μεταβλητές από το constants.py.

Το buzzer() Η συνάρτηση χρησιμοποιεί επίσης δύο νέες μεταβλητές - t και παύση. Αυτές οι δύο μεταβλητές σας βοηθούν να συντονίσετε το ρυθμό της μουσικής. t ορίζει πόσο καιρό θα πρέπει να παίζεται κάθε νότα και παύση ορίζει πόσο μεγάλη θα πρέπει να είναι η σιωπή ανάμεσα στις νότες.


5. Αισθητήρας υπερήχων Pico W και HC-SR04

αισθητήρας υπερήχων pico-w
`

Στα προηγούμενα μαθήματα, χρησιμοποιήσαμε το Pico W για να στέλνουμε εντολές στα LED και τους βομβητές.

Τι γίνεται όμως αν χρησιμοποιούμε το Pico W για να λαμβάνουμε πληροφορίες;

Σε αυτή την περίπτωση, μιλάμε για τον αισθητήρα υπερήχων HC-SR04.

Όταν συνδέετε τον αισθητήρα υπερήχων σας, βεβαιωθείτε ότι γνωρίζετε αν πρόκειται για εξάρτημα 5V ή 3,3V. Έβαλα την έκδοση 5V μου στην ακίδα 3,3V και δεν πήρα καμία απάντηση από το πρόγραμμα, την οποία θα μοιραστώ παρακάτω. Μόλις μετέφερα την πηγή τροφοδοσίας στον ακροδέκτη 5V, πήρα αμέσως απάντηση.

Προφανώς, ορισμένες νεότερες εκδόσεις του HC-SR04 μπορούν να δέχονται και τα 3,3V και τα 5V. Ίσως είναι καλύτερο να δοκιμάσετε πρώτα τον ακροδέκτη 3,3V και να δείτε αν θα έχετε αποτέλεσμα. Εάν όχι, δοκιμάστε τα 5V.

Εδώ είναι τα σχέδια και το πρόγραμμα που μπορείτε να εκτελέσετε στο Thonny. Εάν λάβετε απάντηση, αυτό σημαίνει ότι έχετε συνδέσει τα πάντα με τον σωστό τρόπο, συμπεριλαμβανομένης της τάσης.

Καλωδίωση

Η συνδεσμολογία από τους επισημασμένους ακροδέκτες των αισθητήρων HC-SR04 έχει ως εξής:

  • VCC σε καρφίτσα 3.3V ή 5V (αν έχετε αμφιβολίες, δοκιμάστε πρώτα τα 3,3V)
  • TRIG σε GPIO 16
  • ECHO σε GPIO 15
  • GND προς GND

Πρόγραμμα δοκιμής για το HC-SR04

Για να ελέγξετε αν η καλωδίωσή σας είναι σωστή, δοκιμάστε αυτόν τον κώδικα που θα εκτυπώσει την απόσταση στο 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)

Η έξοδός σας θα πρέπει να είναι:

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

Αν το πρόγραμμα εκτελείται και τερματίζεται χωρίς καμία έξοδο, πιθανόν να έχετε συνδέσει κάτι λάθος. Όταν συνέδεσα τον αισθητήρα σε ακίδα 3,3V αντί για 5V, το πρόγραμμα τερμάτισε χωρίς απόκριση.

Λήψη δεδομένων που αποστέλλονται στο πρόγραμμα περιήγησής σας

Ας ανακτήσουμε τα αρχεία που χρησιμοποιήσαμε για την εξυπηρέτηση μιας ιστοσελίδας και ας τα τροποποιήσουμε ώστε να μπορούμε να δούμε τις τιμές της απόστασης.

Εδώ είναι ο τελικός κώδικας:

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>

Ας δούμε μερικά αποσπάσματα του κώδικα για να καταλάβουμε τι συμβαίνει.

Κώδικας για να λάβετε την απόσταση υπερήχων

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

Το παραπάνω μπλοκ κώδικα ενεργοποιεί την εκπομπή ενός υπερηχητικού κύματος. Το time.sleep μεταξύ των χαμηλών και των υψηλών τιμών είναι απαραίτητες για τη λειτουργία του αισθητήρα υπερήχων.

Για να μετρήσουμε πόσος χρόνος μεσολαβεί μεταξύ της εκπομπής του υπερηχητικού κύματος και του χρόνου επιστροφής του ηχητικού κύματος, χρησιμοποιούμε time.ticks_us για τη μέτρηση του χρόνου εκπομπής και του χρόνου ανίχνευσης της ηχούς.

time.ticks_us είναι ένας αυθαίρετος αριθμός, οπότε θα πρέπει να αφαιρέσουμε signalon από το signaloff για να περάσει ο χρόνος.

Για να υπολογίσουμε την απόσταση, χρησιμοποιούμε τον τύπο απόσταση = (χρόνος που πέρασε * ταχύτητα του ήχου) / 2. Η ταχύτητα του ήχου είναι 340m/s, η οποία επομένως είναι 0,0340.

Ο λόγος για τον οποίο πρέπει να το διαιρέσουμε με το δύο είναι επειδή το ηχητικό κύμα ταξιδεύει προς το αντικείμενο και επιστρέφει πίσω.

Κώδικας για να σερβίρουμε ιστοσελίδα με τιμή απόστασης

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())

Αυτή η συνάρτηση έχει τροποποιηθεί λίγο σε σχέση με τα προηγούμενα σεμινάρια, λαμβάνοντας μια επιπλέον παράμετρο απόσταση, το οποίο τρέχει ultrasonic().

Η συνάρτηση ανοίγει το index.html αρχείο κανονικά, αλλά χρησιμοποιεί το αντικαταστήστε το μέθοδο για να βρείτε το <h2> και εισάγει το απόσταση μεταβλητή.

index.html pings διακομιστή κάθε 500ms για να πάρει νέα τιμή

index.html

Η κύρια ιστοσελίδα λαμβάνει μια συνάρτηση που επαναφορτώνει την ιστοσελίδα κάθε 500ms. Σε κάθε επαναφόρτωση γίνεται pings στο Pico W για να ληφθεί η νέα τιμή της απόστασης υπερήχων.

    <script>
            setInterval(() => location.reload(), 500)
        </script>

6. Δεδομένα υπερήχων, αλλά ας χρησιμοποιήσουμε AJAX για να μειώσουμε το ωφέλιμο φορτίο

Το προηγούμενο σεμινάριο λειτουργεί με το Raspberry Pi Pico W να στέλνει ένα εντελώς νέο index.html αρχείο κάθε φορά που υπάρχει σύνδεση.

Αυτό λειτουργεί, αλλά είναι απίστευτα αναποτελεσματικό, επειδή το σύνολο των index.html αποστέλλεται εκ νέου, όταν χρειάζεται να ενημερώσετε μόνο τα δεδομένα απόστασης υπερήχων.

Θέλουμε τα ίδια αποτελέσματα με το προηγούμενο σεμινάριο, αλλά χωρίς το βαρύ φορτίο της προηγούμενης μεθόδου.

Έτσι, πρέπει να κάνουμε τον πελάτη (το τηλέφωνο ή τον υπολογιστή σας) να κάνει ping σε ένα τελικό σημείο που θα απαντά μόνο με τα δεδομένα υπερήχων.

Η νέα μεθοδολογία είναι η εξής: αν οι χρήστες επισκεφθούν τη ριζική διεύθυνση URL, ας πούμε 192.168.1.119, θα τους σερβιριστεί το index.html.

index.html θα έχει JavaScript που θα κάνει pings στο /data τελικό σημείο, το οποίο ενεργοποιεί το Pico W για να λάβει δεδομένα απόστασης υπερήχων και να ανταποκριθεί με αυτά.

Τότε, index.html θα λάβει αυτά τα δεδομένα και θα ενημερώσει την ιστοσελίδα.

Συναρμολόγηση της αίτησης από τον πελάτη

Θυμηθείτε ότι στο main.py, υπάρχει πάντα μια ατάκα που λέει requests = cl.recv(1024). Το αντικείμενο αίτησης μοιάζει κάπως έτσι:

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

Πρώτα απ' όλα, πρέπει να φιλτράρουμε αυτόν τον τοίχο κειμένου.

Χρησιμοποιούμε το find() μέθοδο για να βρείτε αν η αίτημα μεταβλητή έχει "/data". Εάν ναι, απαντήστε με τα δεδομένα της απόστασης υπερήχων. Εάν δεν υπάρχει "/data", τότε απαντήστε με index.html.

Πριν από το

request = cl.recv(1024)
        print(ultrasonic())
        response = get_html('index.html', ultrasonic())

Μετά το

 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())

Αν επισκεφτείτε το /data στο πρόγραμμα περιήγησής σας, θα δείτε την τιμή της απόστασης να εκτυπώνεται, όπως παρακάτω.

Προηγουμένως, το backend χειριζόταν σχεδόν τα πάντα. Η υπερηχητική απόσταση τροποποιήθηκε πριν σερβιριστεί ως index.html.

Τώρα, index.html αντλεί τα δεδομένα του αισθητήρα από το Pico W, οπότε θα πρέπει να κάνουμε κάποιες αλλαγές στην JavaScript που βρίσκεται μέσα στο αρχείο HTML. Οι αλλαγές επισημαίνονται με έντονη γραφή.

<!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>

Κεντρικό ρόλο στον κώδικα εδώ παίζει η Φέρτε API και το τελευταίο async/await σύνταξη εδώ.

Η λειτουργία getData() κάνει pings στο τελικό σημείο /data του Pico W και το Pico W ανταποκρίνεται. Διασφαλίζουμε ότι το πρόγραμμα δεν θα προχωρήσει μπροστά πριν λάβουμε μια πλήρη απάντηση που θα του ζητάει να περιμένουμε.

Το Fetch γίνεται ένα αντικείμενο Response, το οποίο θα πρέπει να χρησιμοποιήσετε τη μέθοδο Response.text() για να φτάσετε στο σώμα της απόκρισης. Ως εκ τούτου, οι γραμμές const distance = await data.text(),

Μόλις έχουμε τα δεδομένα υπερήχων, αλλάζουμε το <h2 id="”ultrasonic”"> εσωτερική HTML του στοιχείου, η οποία ξεκινάει κενή, με τα δεδομένα της απόστασης. Μπορείτε να στοχεύσετε ένα στοιχείο με ένα id απευθείας χωρίς να χρησιμοποιήσετε το getElementById() ή querySelector() μέθοδοι.

Μόλις ολοκληρωθεί όλος ο κώδικας, θέλουμε να εκτελέσουμε ξανά την getData(). Γιατί χρησιμοποίησα ένα setInterval για να ορίσετε ένα διάστημα 100ms;

Αυτό που διαπίστωσα είναι ότι αν καλέσετε την getData() χωρίς διάστημα, θα έχετε περισσότερες παύσεις μεταξύ των εξόδων. Θα έχετε μια ακολουθία γρήγορων ενημερώσεων και στη συνέχεια μια παύση. Με τα 100ms περιθώριο αναπνοής, το Pico W τρέχει λίγο καλύτερα και οι ενημερώσεις φαίνονται λίγο πολύ σε πραγματικό χρόνο ακόμα.

Αν θέλετε να καταλάβετε τι συμβαίνει κάτω από το καπό, ανατρέξτε στο Τεκμηρίωση του Fetch API και το async/await τεκμηρίωση.


7. Pimoroni Phew για καθαρότερο κώδικα

Το Pimoroni Phew χρησιμοποιείται για την παροχή δεδομένων υπερήχων

Στην προηγούμενη ενότητα καλύψαμε τη μέθοδο AJAX για την ενημέρωση των δεδομένων του αισθητήρα υπερήχων.

Υπάρχει όμως ένας ακόμη καλύτερος τρόπος για να το κάνετε αυτό;

Το Pimoroni's Phew είναι μια βιβλιοθήκη που σας βοηθάει να κάνετε πολλά δίκτυα εύκολα, επειδή μπορείτε να αποφύγετε πολλά ναρκωτικά.

Οι στόχοι είναι οι ίδιοι:

  • Λήψη δεδομένων υπερήχων και εμφάνισή τους στο index.html
  • Διατηρήστε το ωφέλιμο φορτίο όσο το δυνατόν χαμηλότερα.

Να πώς main.py μοιάζει.

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()

Όπως μπορείτε να δείτε, ο κώδικας είναι πολύ πιο ευανάγνωστος, καθώς μπορείτε να ορίσετε τελικά σημεία και να τα συνδέσετε με συναρτήσεις που επιστρέφουν συγκεκριμένα δεδομένα.

Αντί να ψάχνετε τον κώδικα για να τρέξετε τις υποδοχές, θα καλούσατε απλώς μια συνάρτηση από τη βιβλιοθήκη του Phew.

Μερικά πράγματα που αρέσουν στο Phew είναι:

  • Δεν υπάρχει πλέον χρήση των request.find() για να δημιουργήσετε ένα τελικό σημείο
  • Όχι άλλο get_html() συνάρτηση για να ανοίξετε το index.html αρχείο, απλά χρησιμοποιήστε το Phew's render_template()
  • main.py είναι πολύ πιο εύκολο να διαβαστεί, με ελάχιστη πρόσθετη προσπάθεια!
  • Το Phew προσθέτει επίσης λειτουργίες καταγραφής που θα σας επιτρέψουν να αποσφαλματώσετε τον κώδικά σας πιο εύκολα.

Το μόνο μειονέκτημα είναι ότι το Phew είναι ακόμα "ένα πολύ νέο έργο και θα πρέπει να θεωρείται, στην καλύτερη περίπτωση, σε στάδιο άλφα". Έτσι, μπορεί να συναντήσετε απροσδόκητα εμπόδια μερικές φορές.

Ελέγξτε το.

Τα προηγούμενα σεμινάρια μίλησαν για τον τρόπο αλληλεπίδρασης με το Pico W από τον υπολογιστή/το κινητό σας τηλέφωνο.

Ας κάνουμε ένα βήμα παραπέρα και ας βάλουμε το Pico W να αλληλεπιδράσει με μια υπηρεσία cloud.

Για το σκοπό αυτό, ας φτιάξουμε έναν καταγραφέα θερμοκρασίας και υγρασίας με έναν αισθητήρα DHT22 που στέλνει δεδομένα στο Google Sheets μέσω του IFTTT.


8. Ρύθμιση του αισθητήρα θερμοκρασίας και υγρασίας DHT22 στο Pico W

Raspberry Pi Pico W σε συνδυασμό με έναν καταγραφέα θερμοκρασίας και υγρασίας DHT22.

Όλα αυτά τα βήματα λειτουργούν για τα DHT11 και DHT22. Η κύρια διαφορά μεταξύ των δύο είναι η ακρίβεια των μετρήσεων. Το DHT11 έχει μπλε χρώμα, ενώ το DHT22 είναι λευκό.

Αν έχετε ένα DHT11, σημειώστε ότι οι αναφορές στο DHT22 στον κώδικα θα πρέπει να αλλάξουν σε DHT11. Για παράδειγμα,

import dht
#dht22 = dht.DHT22(Pin(16))
#should be
dht11 = dht.DHT11(Pin(16))
Ακίδες DHT22

Κοιτάζοντας το παρακάτω διάγραμμα, από πάνω προς τα κάτω του DHT22, θα συνδέσετε 3,3V στην πρώτη ακίδα.

Ο δεύτερος ακροδέκτης είναι ο ακροδέκτης δεδομένων. Θα πρέπει να τον τροφοδοτήσετε με ρεύμα. Έτσι, συνδέστε μια αντίσταση 10K ohm από τη ράγα τροφοδοσίας σε αυτήν και, στη συνέχεια, συνδέστε ένα άλλο καλώδιο βραχυκυκλώματος στο GPIO 16 του Raspberry Pi Pico.

Το GND πηγαίνει στο GND.

Για να ελέγξετε τον αισθητήρα, εκτελέστε το εξής:

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())

Αν πάρετε OSError: [Errno 110] ETIMEDOUT σημαίνει ότι εκτελείτε το σενάριο πολύ σύντομα. Το DHT22 απαιτεί ένα διάλειμμα δύο δευτερολέπτων πριν επιστρέψει άλλη τιμή. Το DHT11 απαιτεί ένα δευτερόλεπτο.

Σύνδεση IFTTT και Google Sheets

Το Pico W καταγράφει δεδομένα χρόνου, θερμοκρασίας και υγρασίας στο Google Sheets

Ο ευκολότερος τρόπος για να μεταφέρετε δεδομένα από το Pico W στο Google Sheets είναι μέσω του IFTTT.

Πρώτον, εγγραφείτε για λογαριασμό IFTTT.

Στη συνέχεια, κάντε κλικ στο κουμπί "Δημιουργία" για να δημιουργήσετε το applet.

Θα εμφανιστεί αυτή η οθόνη:

Κάντε κλικ στο "Εάν αυτό" και αναζητήστε το Webhooks. Κάντε κλικ στην επιλογή "Λήψη αιτήματος web". Μην επιλέξετε το JSON. Ονομάστε το συμβάν με το όνομα "dht22". Το όνομα του συμβάντος είναι κρίσιμο, επειδή με αυτόν τον τρόπο το IFTTT γνωρίζει ποιο applet πρέπει να ενεργοποιήσει.

Επιλέξτε αυτή, όχι την επιλογή JSON payload.

Αυτό που κάνετε εδώ είναι να δημιουργήσετε ένα τελικό σημείο στο οποίο μπορείτε να κάνετε ping με τα δεδομένα του αισθητήρα του DHT22.

Στη συνέχεια, κάντε κλικ στο "Then That". Επιλέξτε "Google Sheets". Στη συνέχεια, επιλέξτε "Add row to spreadsheet". Θα πρέπει να συνδέσετε το λογαριασμό σας στο Google Sheets.

Αλλάξτε το "Όνομα φύλλου" και τη "Διαδρομή φακέλου δίσκου" σε ό,τι θέλετε. Το μόνο κρίσιμο πράγμα εδώ είναι η "Μορφοποιημένη γραμμή", όπου θα θέλετε να είναι

{{OccurredAt}} ||| {{Value1}} ||| {{Value2}}

Τώρα, θα πρέπει να βρείτε το τελικό σημείο στο οποίο το Pico W μπορεί να στείλει δεδομένα αισθητήρα.

Επικεφαλής στο https://ifttt.com/maker_webhooks και κάντε κλικ στην επιλογή "Documentation" (Τεκμηρίωση).

Η τεκμηρίωση θα σας ενημερώσει για το κλειδί σας, το τελικό σημείο στο οποίο πρέπει να στείλετε δεδομένα και τον τρόπο δόμησης του σώματος JSON.

Εφόσον χρησιμοποιήσατε το "dht22" ως όνομα συμβάντος, το τελικό σας σημείο είναι:

ttps://maker.ifttt.com/trigger/dht22/with/key/[your_key_here]

Θα πρέπει επίσης να δομήσετε το σώμα JSON ως εξής:

{'value1': *** temperature data *** , value2': *** humidity data *** }

Κωδικοποίηση του Pico W για τη λήψη δεδομένων DHT22 και την αποστολή τους στο IFTTT

Ακούστε πώς.

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()

Αν πρόκειται να αντιγράψετε αυτόν τον κώδικα, φροντίστε να αντικαταστήσετε το [your_key_here] στο πανδοχείο request_url μεταβλητή.

Θα πρέπει να λαμβάνετε μια νέα μέτρηση κάθε λεπτό, η οποία καταγράφεται στο Google Sheet, όπως παρακάτω.

Το Pico W καταγράφει δεδομένα χρόνου, θερμοκρασίας και υγρασίας στο Google Sheets

Σημειώστε ότι η καταγεγραμμένη θερμοκρασία είναι σε Κελσίου. Αν τη θέλετε σε Φαρενάιτ, ορίστε ο τύπος:

fahrenheit = dht22.temperature() * 1.8000 + 32.00

Αν θέλετε τα δεδομένα να καταγράφονται πιο συχνά (ή λιγότερο συχνά), αλλάξτε την τιμή στο πεδίο time.sleep().

Χρησιμοποιήστε το IFTTT για να σας ειδοποιήσει αν προκύψει σφάλμα

Φυσικά, αυτός ο κώδικας εξακολουθεί να είναι αρκετά εύθραυστος.

Ας πούμε ότι κάτι δεν πάει καλά. Για παράδειγμα, η γάτα σας τράβηξε το καλώδιο βραχυκυκλώματος 3,3V, ενώ εσείς το τοποθετήσατε στο πάτωμα για να καταγράψετε τη θερμοκρασία.

Το πρόγραμμα θα πεθάνει, αλλά δεν θα λάβετε καμία ειδοποίηση μέχρι να παρατηρήσετε ότι τα δεδομένα σας δεν καταγράφονται.

Πώς το επιλύετε αυτό;

Λοιπόν, βάλτε το IFTTT να σας στέλνει μια ειδοποίηση όταν συμβαίνει αυτό!

Θα χρειαστείτε την εφαρμογή IFTTT στο τηλέφωνό σας. Οπότε κατεβάστε το.

Στη συνέχεια, θα δημιουργήσετε ένα νέο applet.

Για το "Αν αυτό" μέρος, Επιλέξτε Webhooks -> Λήψη αιτήματος web. Ονομάστε την εκδήλωσή σας "σφάλμα".

Για το "Τότε αυτό" μέρος, επιλέξτε "Ειδοποιήσεις" και "Αποστολή ειδοποίησης από την εφαρμογή IFTTT".

Έκανα το μήνυμα απλό

Error: {{Value1}}

Τώρα, ας φτιάξουμε τα μπλοκ 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)

Δοκιμάστε το. Αποσυνδέστε το καλώδιο 3,3V από το DHT22 και θα λάβετε μια τέτοια ειδοποίηση:


9. Κατασκευάστε ένα φυσικό τηλεχειριστήριο Spotify με Raspberry Pi Pico W

Με βάση το προηγούμενο έργο, θα χρησιμοποιήσουμε το IFTTT για να ελέγξουμε το Spotify.

Θα δημιουργήσουμε μια συσκευή που έχει ένα κουμπί αναπαραγωγής, παύσης και παράλειψης κομματιού.

Το κύριο πλεονέκτημα της χρήσης του IFTTT για τον έλεγχο του Spotify είναι το πόσο εύκολο είναι.

Το μειονέκτημα είναι ότι χρειάζεστε έναν επί πληρωμή λογαριασμό Spotify και οι απαντήσεις είναι αργές. Αυτό σημαίνει ότι αν πατήσετε το κουμπί skip, θα πρέπει να περιμένετε λίγο μέχρι να δείτε το αποτέλεσμα.

Η ομορφιά του να έχεις ένα ειδικό τηλεχειριστήριο Spotify είναι ότι μπορείς να αλλάζεις τη μουσική σου χωρίς να κουβαλάς μαζί σου το τηλέφωνό σου ή να ανοίγεις την εφαρμογή Spotify.

Αν έχετε οδηγήσει ποτέ ένα σύγχρονο αυτοκίνητο, θα ξέρετε πόσο καλό είναι να έχετε χειριστήρια στο τιμόνι.

Συνδέοντας έναν απομακρυσμένο ελεγκτή Spotify

Ελεγκτής Spotify Raspberry Pi Pico W
Ελεγκτής Spotify Raspberry Pi Pico W. Από πάνω προς τα κάτω, τα κουμπιά είναι pause, play, skip track.

Θα χρειαστείτε...

  • 7x καλώδια βραχυκυκλώματος
  • 3x κουμπιά
  • Raspberry Pi Pico W
  • Spotify λογαριασμός επί πληρωμή

Υπάρχουν πολλά καλώδια που διασταυρώνονται εκεί πάνω στην εικόνα, γι' αυτό εδώ είναι μια εξήγηση με κείμενο.

Τα μπουτόν είναι σαν διακόπτες. Πρέπει να συνδέσετε τον ακροδέκτη 3V3 σε καθένα από αυτά, πράγμα που σημαίνει ότι πρέπει να χρησιμοποιήσετε τη θετική στήλη στην πλακέτα. Επομένως, θα πρέπει να χρησιμοποιήσετε το καλώδιο της πλακέτας:

3V3 -> θετική στήλη breadboard -> μπουτόν (στη μία πλευρά της υδρορροής breadboard) -> GPIO (στην άλλη πλευρά)

Ο κώδικάς μου θα χρησιμοποιήσει το GPIO 16 για το κουμπί αναπαραγωγής, το GPIO 2 για το κουμπί παύσης και το GPIO 15 για το κουμπί παράλειψης κομματιού.

Ρύθμιση του IFTTT για τον έλεγχο του Spotify

Θα δημιουργήσουμε τρία applets IFTTT για τον έλεγχο του Spotify.

Πρέπει να δημιουργήσουμε τρία applets, ένα για την αναπαραγωγή, την παύση και την παράλειψη.

Αν έχετε την premium έκδοση του IFTTT, θα μπορούσατε πιθανώς να χρησιμοποιήσετε τα φίλτρα JavaScript για να τα συμπεριλάβετε όλα σε μία εφαρμογή. Επειδή όμως δεν έχουμε, χρειαζόμαστε ένα applet το καθένα.

Αφού συνδεθείτε, κάντε κλικ στο "Create" (Δημιουργία) στην επάνω δεξιά γωνία του κεντρικού μενού.

Στη γραμμή "Εάν αυτό", κάντε κλικ σε αυτήν και αναζητήστε Webhooks.

Κάντε κλικ στο "If This" ή στο "Then That" και επιλέξτε Webhooks και Spotify αντίστοιχα.

Στη συνέχεια, κάντε κλικ στην επιλογή "Receive a web request" (όχι στην άλλη επιλογή που έχει "with a JSON payload").

Για το όνομα του συμβάντος, πληκτρολογήστε spotify_skip.

Θα πρέπει να επαναλάβετε αυτό το βήμα άλλες δύο φορές για spotify_pause και spotify_play μόλις τελειώσετε με τη δημιουργία αυτής της εφαρμογής.

Μόλις γίνει αυτό, μεταβείτε στο "Τότε αυτό" και κάντε κλικ σε αυτό. Αναζητήστε "Spotify".

Θα πρέπει να εξουσιοδοτήσετε το IFTTT να συνδεθεί με το Spotify μία φορά.

Εάν κάνετε το spotify_skip ενέργεια, θα πρέπει να κάνετε κλικ στο "Skip track". Αλλά αν κάνετε ένα applet για να κάνετε κάποια άλλη ενέργεια, η παραπάνω εικόνα θα σας δείξει ποια από τις δύο πρέπει να χρησιμοποιήσετε.

Αφού δημιουργήσετε και τα τρία applets, είναι ώρα να κωδικοποιήσετε!

Κωδικοποίηση του τηλεχειριστηρίου του Spotify για το Pico W

Πρώτα απ' όλα, θα πρέπει να γνωρίζετε το τελικό σημείο που πρέπει να πετύχετε.

Πηγαίνετε σε αυτή τη σελίδα και κάντε κλικ στο Τεκμηρίωση.

Εκεί θα δείτε το κλειδί σας. Αν έχετε ακολουθήσει όλα τα παραπάνω βήματα, η διαφορά μεταξύ του δικού σας τελικού σημείου και του δικού μου είναι το κλειδί σας. Ως εκ τούτου,

Τελικό σημείο αναπαραγωγής: https://maker.ifttt.com/trigger/spotify_play/with/key/[your_key_here]

Παύση: https://maker.ifttt.com/trigger/spotify_pause/with/key/[your_key_here]

Παράλειψη: https://maker.ifttt.com/trigger/spotify_skip/with/key/[your_key_here]

Κωδικός

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)

Ας δούμε τον κώδικα.

Σημειώστε ότι θα πρέπει να αντικαταστήσετε [your_key_here] με το πραγματικό σας κλειδί, όπως προκύπτει από το Τεκμηρίωση σύνδεσμος.

Πρώτα, δηλώνουμε μεταβλητές για τα κουμπιά.

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)

Επί του παρόντος, αν δεν πατήσετε το κουμπί, η μεταβλητή σας θα έχει τιμή 0. Αν το πατήσετε, γίνεται 1. Αυτό είναι που θα χρησιμοποιήσουμε για να ενεργοποιήσουμε το play() , pause() και skip() λειτουργίες.

Στη συνέχεια, δημιουργούμε συναρτήσεις για τα τελικά σημεία αναπαραγωγής, παύσης και παράλειψης. Το γενικό πρότυπο έχει ως εξής:

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)

Είναι πολύ απλό. Εάν εκτελεστεί αυτή η λειτουργία, θα στείλει ένα αίτημα POST στο IFTTT. Η αποστολή ενός αιτήματος GET δεν θα λειτουργήσει.

Στη συνέχεια, έχουμε το μπλοκ 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)

Εάν πατηθεί ένα κουμπί, ο κώδικας θα εκτελέσει τη σχετική λειτουργία. Για παράδειγμα, το πάτημα του κουμπιού skip θα εκτελέσει τη λειτουργία skip().

A time.sleep(0.25) θα διακόψει τη λειτουργία για 250ms. Χωρίς αυτό, ακόμη και ένα σύντομο πάτημα μπορεί να υπερφορτώσει και να καταρρεύσει το Pico W.

Το εκτός από το block είναι προαιρετικό, αλλά το έκανα επειδή είχα ήδη ένα applet "error" στο IFTTT. Αν έχετε ακολουθήσει το προηγούμενο σεμινάριο, ίσως το έχετε χρησιμοποιήσει.

Βασικά, στέλνει το μήνυμα σφάλματος, e, στο IFTTT, ώστε να λαμβάνετε το μήνυμα σφάλματος ως ειδοποίηση της εφαρμογής του τηλεφώνου.

Γιατί δεν λειτουργεί;

Η χρήση του IFTTT ως μέσο ελέγχου του Spotify είναι εύκολη, αλλά έχει και κάποια μειονεκτήματα.

Πρέπει πρώτα να ξεκινήσετε τη μουσική με τον κανονικό τρόπο

Αν προσπαθήσατε να πατήσετε το κουμπί αναπαραγωγής στο Pico W και περιμένατε να ξεκινήσει η αναπαραγωγή της μουσικής... λοιπόν, δεν συμβαίνει τίποτα.

Η λύση είναι να ξεκινήσετε κανονικά τη μουσική στον υπολογιστή ή το τηλέφωνό σας. Πρέπει να μεταβείτε στην εφαρμογή σας και να πατήσετε το κουμπί αναπαραγωγής.

Νομίζω ότι αυτό δηλώνει ποια συσκευή είναι η ενεργή συσκευή. Μόλις το κάνετε αυτό, θα μπορείτε να χρησιμοποιήσετε το τηλεχειριστήριο του Pico W Spotify.

Αργές απαντήσεις

Χρειάζονται μερικά δευτερόλεπτα μεταξύ του πατήματος του κουμπιού και της απόκρισης. Δυστυχώς, έτσι είναι τα πράγματα.

Θα μπορούσατε να πληρώσετε για μια αναβάθμιση του IFTTT για να έχετε ταχύτερες ταχύτητες απόκρισης. Τουλάχιστον, αυτό υπόσχονται για τα χρήματά σας.

Υπάρχει άμεσος τρόπος σύνδεσης του Spotify;

Ναι! Το Spotify διαθέτει ένα API στο οποίο μπορείτε να συνδεθείτε.

Σας δίνει σημαντικά μεγαλύτερο έλεγχο. Θα μπορούσατε να προσθέσετε έναν περιστροφικό κωδικοποιητή για τον έλεγχο της έντασης. Θα μπορούσατε να προσθέσετε μια οθόνη LCD για να βλέπετε τι παίζει. Δείτε την κονσόλα του Spotify εδώ.

Καταπληκτικό, αλλά και πολύ πιο δύσκολο να προγραμματιστεί, ειδικά σε ένα Pico W.

Το IFTTT τα κάνει όλα εύκολα, επειδή κάνει όλη τη βαριά δουλειά. Αν θέλετε να είστε εσείς ο βαρύς αναβάτης, ελέγξτε τη ροή ελέγχου ταυτότητας.

Διάγραμμα ροής κώδικα εξουσιοδότησης από το Spotify

Φυσικά, είμαστε λάτρεις του Raspberry Pi. Κάποιος εκεί έξω θα το κάνει. Μήπως πρέπει να το κάνετε εσείς; Ή εγώ; Σχολιάστε παρακάτω.

Ελέγξτε το Pico W ασύρματα με το PiCockpit!

Μπορείτε να ελέγχετε και να λαμβάνετε δεδομένα από το Pico W ασύρματα χρησιμοποιώντας το PiCockpit.

Το PiCockpit σας επιτρέπει να λαμβάνετε τιμές, να ελέγχετε και να χρησιμοποιείτε το PWM μέσω ενός γραφικού περιβάλλοντος εργασίας μέσω του applet GPIO.

Μπορείτε επίσης να δείτε τα στατιστικά στοιχεία του Pico W μέσω της εφαρμογής PiStats.

Η ενσωμάτωση του PiCockpit στο Pico W είναι πανεύκολη.

Ακολουθήστε αυτό το σεμινάριο.

Γράψτε ακόμα λιγότερο κώδικα με το PiCockpit και το Pico W

Το PiCockpit σας διευκολύνει να ελέγχετε τις ακίδες GPIO χωρίς να χρειάζεται να γράψετε κώδικα.

Αν κοιτάξετε σεμινάριο νούμερο 2, παρατηρήστε πόσος κώδικας είναι απαραίτητος μόνο για την εναλλαγή ενός LED.

Με τη νέα μας ενσωμάτωση του Pico W, το PiCockpit το κάνει πολύ πιο εύκολο, καθώς δεν χρειάζεται να προγραμματίσετε τίποτα απολύτως. Ούτε καν τη διαμόρφωση του WiFi - αυτό γίνεται με τον οδηγό ρυθμίσεων.

10. Απλός έλεγχος LED με PiCockpit και Pico W

Αν έχετε ρυθμίσει το LED σας ακριβώς όπως το έχω κάνει στο σεμινάριο 2, τότε το μόνο που απομένει είναι να το ρυθμίσετε στο PiCockpit.

Αν το κωδικοποιήσετε, θα δηλώσετε σε ποια ακίδα βρίσκεται το LED σας χρησιμοποιώντας led = machine.Pin(2, machine.Pin.OUT)

Στο PiCockpit, θα μεταβείτε στο applet GPIO και θα μετακινηθείτε στο "GPIO Output (On/Off)".

Επιλέξτε BCM02 από το αναπτυσσόμενο μενού, επειδή η λυχνία LED βρίσκεται στο GPIO 2.

Στη συνέχεια, στη στήλη "Έλεγχος", ενεργοποιήστε το διακόπτη για να ανάψει η λυχνία LED.

Μπορείτε επίσης να χρησιμοποιήσετε εύκολα την ενότητα PWM λογισμικού παρακάτω για να ελέγξετε τη φωτεινότητα της LED σας.

Σημειώστε ότι θα πρέπει να αφαιρέσετε την προηγούμενη ρύθμιση επειδή δεν μπορείτε να έχετε δύο εξόδους στο ίδιο GPIO.

Καθώς μετακινείτε το ρυθμιστικό "Control", θα παρατηρήσετε ότι η φωτεινότητα της λυχνίας LED αλλάζει.

τηλεχειριστήριο picockpit gpio pwm

11. Pico W, ανεμιστήρας 5V και ένα τρανζίστορ, ελεγχόμενο από το PiCockpit

Ας δοκιμάσουμε κάτι λίγο πιο ολοκληρωμένο, αλλά χρησιμοποιώντας την ίδια εναλλαγή εξόδου GPIO.

Για να δείξω μερικές πραγματικές περιπτώσεις χρήσης, θα τροφοδοτήσω έναν ανεμιστήρα 5V χρησιμοποιώντας το PiCockpit.

Αυτός είναι ένας ανεμιστήρας χαμηλής ισχύος 5V που λαμβάνεται από το Raspberry Pi 4, οπότε είναι μέσα στις δυνατότητες εξόδου του Raspberry Pi Pico W.

Επειδή πρόκειται για ανεμιστήρα 5V, δεν μπορώ να χρησιμοποιήσω ακίδα GPIO. Σε λιγότερο ενεργοβόρα εξαρτήματα, όπως μια λυχνία LED, μπορείτε να έχετε το GPIO να κάνει διπλό καθήκον: να παρέχει ρεύμα στο εξάρτημα και να είναι ο "διακόπτης" που το ενεργοποιεί και το απενεργοποιεί.

Αλλά ο ανεμιστήρας 5V θα απαιτούσε πολύ υψηλή τάση. Έτσι, ο επόμενος καλύτερος τρόπος είναι να τοποθετήσετε ένα τρανζίστορ στη μέση.

Αυτό μου επιτρέπει να τροφοδοτώ 5V στον ανεμιστήρα, ενώ παράλληλα εξασφαλίζω ότι μπορώ να τον ενεργοποιώ και να τον απενεργοποιώ.

Για άλλη μια φορά, λόγω του PiCockpit, έκανα μηδενικό προγραμματισμό. Έκανα μόνο το υλικό, το οποίο είναι καλωδιωμένο ως εξής:

Ο ανεμιστήρας είναι ένας ανεμιστήρας 5V/0.12A, συνδεδεμένος στα 5V στο θετικό άκρο (κόκκινο καλώδιο) και το αρνητικό καλώδιο πηγαίνει στο πόδι εκπομπού του τρανζίστορ.

Το τρανζίστορ είναι ένα τρανζίστορ PN2222 (NPN), που σημαίνει ότι ενεργοποιείται όταν λαμβάνει ένα υψηλό σήμα.

Από αριστερά προς τα δεξιά, με το ημικυκλικό τμήμα να κοιτάζει μακριά από εσάς, τα πόδια είναι ο Πομπός, η Βάση και ο Συλλέκτης.

Το σκέλος της βάσης συνδέεται σε μια αντίσταση 1Κ και στη συνέχεια συνδέεται στο GPIO 15.

Το σκέλος του συλλέκτη συνδέεται με τη γείωση.

Διαμόρφωση του PiCockpit για να λειτουργεί με τρανζίστορ

Για άλλη μια φορά, εξαιρετικά εύκολο.

Μεταβείτε στο αναπτυσσόμενο μενού στην ενότητα GPIO Output και προσθέστε το BCM15.

Αφού το τοποθετήσετε, μπορείτε να κάνετε κλικ στο βέλος προς τα κάτω και να αλλάξετε τα State Names σε "fan off" και "fan on".

Εναλλαγή του διακόπτη ελέγχου και θα πρέπει να δείτε τον ανεμιστήρα να ενεργοποιείται.

Μπορείτε επίσης να χρησιμοποιήσετε το PiStats για να δείτε την πτώση των θερμοκρασιών στην πλακέτα σας.

Φωτοαντίσταση οθόνης με χρήση MQTT και Node-RED με Pico W.

Ο κύριος στόχος αυτού του σεμιναρίου είναι η εισαγωγή του MQTT.

Στα προηγούμενα σεμινάρια, σας έδειξα πώς μπορείτε να χρησιμοποιήσετε το Pico W για να παραδώσετε δεδομένα, αλλά τι γίνεται αν θέλετε ένα κεντρικό αποθετήριο δεδομένων στο σύννεφο;

Το HiveMQ Cloud είναι μια δωρεάν υπηρεσία που μπορούμε να χρησιμοποιήσουμε για την επίτευξη αυτού του στόχου. Χρησιμοποιώντας τους υπολογιστές κάποιου άλλου, μπορούμε επίσης να ελαφρύνουμε το φορτίο του Pico W.

Επιπλέον, το MQTT έχει σημαντικά πλεονεκτήματα σε σύγκριση με τις προηγούμενες μεθόδους που χρησιμοποιούνταν. Πρώτον, είναι πολύ πιο αποτελεσματικό στην αποστολή μικρών δεδομένων. Οι επικεφαλίδες του πρωτοκόλλου MQTT έχουν μέγεθος 2 bytes. Το HTTP είναι περίπου 4000 φορές μεγαλύτερο.

Η μείωση του τοπικού φορτίου επεξεργασίας και του φορτίου δικτύου σημαίνει μεγαλύτερη διάρκεια ζωής της μπαταρίας του Pico W, η οποία είναι ιδανική για έργα που λειτουργούν με μπαταρία ή ηλιακή ενέργεια.

Σύνδεση φωτοαντιστάσεων με το Pico W

Ένα φωτοαντίσταση (φωτοκύτταρο) είναι εξαιρετικά εύκολο να συνδεθεί.

Τοποθετήστε το φωτοαντίσταση κατά μήκος της κεντρικής υδρορροής της πλακέτας ψωμιού.

Στη συνέχεια, συνδέστε τον ακροδέκτη 3V3 στη μία πλευρά του φωτοαντιστάτη.

Θα θέλετε να συνδέσετε ένα pin ADC στην άλλη πλευρά του φωτοαντιστάτη, οπότε συνδέστε το GPIO 26.

Τέλος, συνδέστε μια αντίσταση 10K ohm από τη γείωση στο φωτοκύτταρο.

HiveMQ Cloud και κωδικοποίηση του Pico W

Πρώτα απ' όλα, εγγραφείτε για το HiveMQ Cloud εδώ.

Προχωρήστε στη ρύθμιση και δημιουργήστε μια συστάδα. Θα σας ζητηθεί να επιλέξετε AWS ή Azure. Για τους σκοπούς μας, δεν υπάρχει καμία διαφορά.

Στη συνέχεια, κάντε κλικ στο "Manage Cluster".

Κύριο μενού Cluster. Προσέξτε τα δύο πορτοκαλί ορθογώνια.

Σημειώστε τη διεύθυνση URL του Cluster και κάντε κλικ στο Access Management για να δημιουργήσετε έναν νέο χρήστη. Προχωρήστε στα βήματα και δημιουργήστε έναν νέο χρήστη.

Με αυτά τα στοιχεία, μπορείτε τώρα να προγραμματίσετε το Pico W να στέλνει δεδομένα εκεί.

Κωδικοποίηση του Pico W για τη λήψη δεδομένων φωτοκύτταρου και 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)

Πρώτον, ας βάλουμε σε τάξη τις εισαγωγές μας.

from machine import Pin, ADC
from wifi import init_wifi
import time
from umqtt.simple import MQTTClient

Το wifi εισαγωγή προέρχεται από τα προηγούμενα σεμινάρια.

Θα χρειαστείτε τη βιβλιοθήκη umqtt.simple, η οποία μπορείτε να το κατεβάσετε εδώ.

Μόλις το κατεβάσετε, μπορείτε να το ανεβάσετε στον πίνακα σας (οδηγός εδώ).

Θα πρέπει να έχετε αυτά τα αρχεία στο Pico W.

Στη συνέχεια, δημιουργήστε μια συνάρτηση για να λαμβάνετε μια ένδειξη από το φωτοαντίσταση:

photoresistor = ADC(Pin(26))

def readLight():
    light = photoresistor.read_u16()
    return light

Αυτό επιστρέφει μια τιμή έως 65535. Όσο πιο φωτεινή είναι, τόσο υψηλότερη είναι η τιμή.

Σύνδεση στο HiveMQ

Για να συνδεθείτε στο HiveMQ, θα πρέπει να στείλετε ορισμένες παραμέτρους στην κλάση 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()

Αντικαταστήστε το [your-host-name] με τη διεύθυνση που βρίσκεται στο ταμπλό σας. Θα πρέπει να το κάνετε αυτό δύο φορές, μία φορά για το server και ένα άλλο για server_hostname. Αντικαταστήστε επίσης το [your_client_id] με ένα όνομα για τη συσκευή σας, όπως "your_picow".

Στη συνέχεια, αντικαταστήστε [your-user] και [your-pw] με τον χρήστη που δημιουργήσατε στη σελίδα Διαχείριση πρόσβασης (στιγμιότυπο οθόνης της σελίδας Διαχείριση πρόσβασης παρακάτω).

Για λόγους αναφοράς, αυτή η λειτουργία στέλνει δεδομένα στο HiveMQ:

def publish(topic, value):
    print(topic)
    print(value)
    client.publish(topic, value)
    print("data published")

Ας το ονομάσουμε στο δικό μας while βρόχο:

while True:
    brightness = str(readLight()) #to publish, must send string

    print(brightness)

    publish('picow/brightness', brightness)

    time.sleep(0.1)

Κατά τη δημοσίευση, πρέπει να στέλνετε συμβολοσειρές, γι' αυτό το λόγο brightness = str(readLight()) είναι εκεί.

Αν στείλετε ακέραιους ή κινητές μονάδες, το πρόγραμμα θα πεθάνει.

Στη λειτουργία δημοσίευσης, δώστε ένα όνομα στο θέμα σας. Πείτε, picow/brightness, και στη συνέχεια προσθέστε την τιμή που θέλετε να στείλετε. Σε αυτή την περίπτωση, θέλουμε να στείλουμε την ανάγνωση του φωτός με συμβολοσειρά, brightness.

Θα πρέπει να μπορείτε να βλέπετε τα δεδομένα που δημοσιεύονται όταν συνδέεστε στην καρτέλα Web Client.

Ο πελάτης ιστού του HiveMQ, στα αριστερά, σας δείχνει τα δεδομένα που έχουν δημοσιευτεί.

Node-RED

Αυτοί είναι απλώς αριθμοί στο διαδίκτυο που μπορεί να φαίνονται σαν ασυναρτησίες. Τι θα συνέβαινε αν θέλατε να αποκτήσετε πρόσβαση στα δεδομένα στο HiveMQ Cloud και να τα παρουσιάσετε γραφικά;

Αντί να δημιουργήσετε το δικό σας, μπορείτε να χρησιμοποιήσετε το Node-RED.

Το Node-RED σας διευκολύνει πραγματικά να λαμβάνετε δεδομένα από το HiveMQ και στη συνέχεια να τα παρουσιάζετε χρησιμοποιώντας γραφικές αναπαραστάσεις.

Θα φτιάξουμε ένα μετρητή χρησιμοποιώντας το Node-RED.

Για να ξεκινήσετε, θα πρέπει να έχετε nodejs. Ελέγξτε την τεκμηρίωση του HiveMQ για να δείτε ποια έκδοση συνιστάται.

Μόλις εγκαταστήσετε το Node, θα πρέπει να ανοίξετε μια γραμμή εντολών/τερματικό και να εκτελέσετε αυτές τις εντολές (αποκλείοντας το sudo αν είστε σε Windows):

sudo npm install -g --unsafe-perm node-red

Αυτό θα χρησιμοποιήσει τον διαχειριστή πακέτων node (npm) για να εγκαταστήσει το Node-RED σε παγκόσμιο επίπεδο.

Στη συνέχεια, εκτελέστε το Node-RED πληκτρολογώντας node-red στο Terminal/στην προτροπή εντολών.

Ανοίξτε το πρόγραμμα περιήγησής σας και μεταβείτε στη διεύθυνση http://127.0.0.1:1880 ή οποιαδήποτε διεύθυνση είναι καταχωρημένη στο τερματικό σας.

Ας δημιουργήσουμε τη ροή. Σύρετε ένα "mqtt in" στον καμβά. Μπορείτε να το βρείτε στην καρτέλα "network" στην αριστερή πλευρική μπάρα.

Θα πρέπει να διαμορφώσουμε την καρτέλα, οπότε κάντε διπλό κλικ στο ορθογώνιο και κάντε τα εξής:

Στο πεδίο "θέμα", βεβαιωθείτε ότι έχετε προσθέσει picow/φωτεινότητα, αφού αυτό είναι που δημοσιεύσατε από το Pico W.

Στον "διακομιστή", προσθέστε έναν νέο κάνοντας κλικ στο εικονίδιο με το μολύβι και θα μεταφερθείτε στο επόμενο μενού.

Βάλτε μια νέα διεύθυνση διακομιστή και αλλάξτε τη θύρα σε 8883. Μαρκάρετε το "Use TLS" αλλά μην μπείτε στον κόπο να προσθέσετε νέο tls-config.

Στη συνέχεια, μεταβείτε στην καρτέλα ασφαλείας και προσθέστε τα διαπιστευτήρια σύνδεσής σας.

Όλες αυτές οι λεπτομέρειες μπορούν να βρεθούν στον κώδικά σας όταν αρχικοποιείτε το MQTTClient.

Προσθήκη μετρητή

Για να προσθέσετε ένα μετρητή, πρέπει να έχετε το node-red-dashboard.

Στην αριστερή πλαϊνή μπάρα, αν δεν τα βλέπετε:

Στη συνέχεια, μεταβείτε στο μενού (πάνω δεξιά) -> Διαχείριση παλέτας. Στη συνέχεια, μεταβείτε στην καρτέλα Εγκατάσταση και αναζητήστε το node-red-dashboard. Κάντε κλικ στο κουμπί "Εγκατάσταση".

Σύρετε και αφήστε ένα "μετρητή" στα δεξιά του πεδίου mqtt σε ορθογώνιο, και συνδέστε τα σύροντας μια γραμμή από το mqtt σε στο μετρητή.

Κάντε διπλό κλικ στο ορθογώνιο του μετρητή και αλλάξτε την ετικέτα σε "φωτεινότητα" και το μέγιστο "εύρος" σε 65535.

Ωραία. Τώρα ας πατήσουμε "Deploy".

Αν οι ρυθμίσεις σας ήταν σωστές, θα δείτε έναν πράσινο κύκλο και το "connected" κάτω από το ορθογώνιο. Εάν όχι, το τερματικό σας θα σας δώσει περισσότερες λεπτομέρειες σχετικά με το γιατί υπάρχει σφάλμα.

Με το Pico W να παρέχει δεδομένα στο HiveMQ Cloud, ήρθε η ώρα να ελέγξετε το ταμπλό. Επισκεφθείτε το http://127.0.0.1:1880/ui και θα πρέπει να βλέπετε ότι ο μετρητής ενημερώνεται συχνά.


Οι προτάσεις σας είναι ευπρόσδεκτες.

Αφήστε ένα σχόλιο στο πλαίσιο σχολίων παρακάτω!

6 Σχόλια

  1. Quang στις Ιανουάριος 10, 2023 στις 2:21 μμ

    Γεια σας,
    Σας ευχαριστούμε που μοιράζεστε τις γνώσεις σας μαζί μας.
    Θα μπορούσατε να μας ενημερώσετε αν οι ασκήσεις WiFi είναι μόνο εντός δικτύου; Δεν μπόρεσα να έχω πρόσβαση στο Pico W αν βρίσκομαι σε διαφορετικό δίκτυο WiFi. Αν ναι, έχετε παραδείγματα για πρόσβαση εκτός δικτύου;
    Σας ευχαριστώ.

    • raspi berry στις Φεβρουάριος 4, 2023 στις 11:52 πμ

      Ναι, λόγω της φύσης των δικτύων, των δρομολογητών και των τειχών προστασίας, αυτές οι ασκήσεις λειτουργούν μόνο εντός του ίδιου δικτύου WiFi.
      Το ίδιο το PiCockpit είναι μια λύση που εκτείνεται σε διάφορα δίκτυα - μπορείτε να έχετε πρόσβαση στο Pico W από παντού στο Διαδίκτυο.
      Εργαζόμαστε για να φέρουμε περισσότερες δυνατότητες στην πλατφόρμα.

      Αν θέλετε να αναδημιουργήσετε κάτι τέτοιο μόνοι σας, θα πρέπει να έχετε κάποιο είδος λύσης σήραγγας στο δίκτυό σας ή έναν διακομιστή αναμετάδοσης ή κάτι τέτοιο.
      Προσφέρουμε συμβουλευτικές υπηρεσίες αν θέλετε να εμβαθύνετε σε αυτό το θέμα.

  2. Peter Mayr στις Μάρτιος 29, 2023 στις 10:44 πμ

    Σας ευχαριστώ για αυτό το σπουδαίο σεμινάριο.
    Δυστυχώς δεν λειτουργεί.
    Έχω κολλήσει στο τέλος του μέρους "1. Εξυπηρετήστε μια ιστοσελίδα που λέει "Hello World" στο Pico"

    Τα προγράμματα περιήγησης ιστού Firefox και Chrome μου λένε μόνο "Error connection interrupted" .
    Στο Thonny βλέπω

    Συνδεδεμένο
    ip = 192.168.188.198
    Ακρόαση στο ('0.0.0.0', 80)
    Ο πελάτης συνδέθηκε από ('192.168.188.100', 54025)
    Σύνδεση κλειστή

    Σύνδεση κλειστή έρχεται μια-δυο φορές.
    Τι μπορώ να τροποποιήσω για να κάνω το Pico W να λειτουργεί;
    Σας ευχαριστώ εκ των προτέρων για τη βοήθειά σας.
    Χαιρετισμούς Pete

  3. mokcp στις Μάιος 3, 2023 στις 10:58 πμ

    Κατά την εκτέλεση του main.py, υπάρχει ένα μήνυμα σφάλματος, πώς μπορώ να το επιλύσω.

    Αρχείο "", γραμμή 1, σε
    ImportError: δεν υπάρχει ενότητα με όνομα 'wifi'

    σας ευχαριστώ εκ των προτέρων.

    • PiCaptain στις Μάιος 10, 2023 στις 12:31 μμ

      Πρέπει να δημιουργήσετε και να προσθέσετε το wifi.py - το οποίο εμφανίζεται λίγο πιο πάνω στη σελίδα. Χωρίς το wifi.py, ο κώδικας δεν θα λειτουργήσει.

  4. màn hình led στις Αύγουστος 26, 2023 στις 2:18 μμ

    Το "Raspberry Pi Pico W begers' components tutorial" είναι ένας φανταστικός οδηγός για όσους είναι νέοι στην πλατφόρμα Raspberry Pi Pico W. Το σεμινάριο είναι καλά δομημένο και εύκολο στην παρακολούθηση, καθιστώντας το ιδανικό για αρχάριους. Καλύπτει τα βασικά εξαρτήματα και παρέχει σαφείς οδηγίες, καθιστώντας το ένα εξαιρετικό σημείο εκκίνησης για όποιον θέλει να εξερευνήσει αυτή την τεχνολογία. Η συμπερίληψη λεπτομερών εξηγήσεων και εικόνων ενισχύει την εμπειρία εκμάθησης, διασφαλίζοντας ότι οι αναγνώστες μπορούν να κατανοήσουν γρήγορα τις έννοιες. Συνολικά, αυτό το σεμινάριο είναι μια πολύτιμη πηγή για όσους επιθυμούν να ξεκινήσουν με το Raspberry Pi Pico W και τα εξαρτήματά του.

Αφήστε ένα σχόλιο