Skip to content

Week 13: Networking and Communication

This week I made a raspberry pi pico and a seeed xiao rp2040 communicate via UART serial. I also made tworaspberry pi pico W boards to communicate via WIFI and send random rgb colors to be displayed on a neopixel LED connected to one of the Picos.

UART Serial

I used this video to show me how to do the networking. I substituted one of the Picos for a seeed Xiao rp2040 and changed the pinout accordingly, everything else was the same. I started by opening Thonny. Then I copied and pasted the code into thonny on three separate files, easy_comms, pico_comms a, and pico comms b.

easy_comms

#Easy comms is a simple class that allows you to send and receive messages over a serial port.

from machine import UART, Pin
from time import time_ns

class Easy_comms:

    uart_id = 0
    baud_rate = 9600
    timeout = 1000 # milliseconds

    def __init__(self, uart_id:int, baud_rate:int=None):
        self.uart_id = uart_id
        if baud_rate: self.baud_rate = baud_rate

        # set the baud rate
        self.uart = UART(self.uart_id,self.baud_rate)

        # Initialise the UART serial port
        self.uart.init()

    def send(self, message:str):
        print(f'sending message: {message}')
        message = message + '\n'
        self.uart.write(bytes(message,'utf-8'))

    def start(self):
        message = "ahoy\n"
        print(message)
        self.send(message)

    def read(self)->str:
        start_time = time_ns()
        current_time = start_time
        new_line = False
        message = ""
        while (not new_line) or (current_time <= (start_time + self.timeout)):
            if (self.uart.any() > 0):
                message = message + self.uart.read().decode('utf-8')
                if '\n' in message:
                    new_line = True
                    message = message.strip('\n')
                    # print(f'received message: {message}')
                    return message
        else:
            return None

pico_comms_a

# Pico_comms_a
# Sends commands and listens to responses from pico_comms_b

from easy_comms import Easy_comms
from time import sleep

com1 = Easy_comms(uart_id=0, baud_rate=9600)
com1.start()

while True:
    message = ""
    message = com1.read()

    if message is not None:
        print(f"message received: {message.strip('\n')}")
    sleep(1)

pico_comms_b

# Pico_comms_b
# Sends commands and listens to responses from pico_comms_a

from easy_comms import Easy_comms
from time import sleep

com1 = Easy_comms(uart_id=0, baud_rate=9600)
com1.start()

count = 0
while True:
    # send a message
    com1.send(f'hello, {count}')

    #check for messages
    message = com1.read()

    if message is not None:
        print(f"message received: {message.strip('\n')}")
    sleep(1)
    count +=1

After this, I plugged both pico w’s into my computer and saved the easy comms file to the pico individually. Then I uploaded pico comms a to one of the Picos and b to the other. Then I ran them both and transmitted messages between the two.

Then I did the same thing but replaced the pico comms code with the led code. here is the code.

Led_server.py

# led_server

from easy_comms import Easy_comms
from time import sleep
from machine import Pin
import json

command = {'command':'blink', 'args': 'on'}

com1 = Easy_comms(0,9600)
led = Pin(8, Pin.OUT)

while True:
    com1.send(str(json.dumps(command)))
    if command['args'] == 'on':
       command = {'command':'blink', 'args': 'off'}
    else:
       command = {'command':'blink', 'args': 'on'}
    led.toggle()
    sleep(1)

led_client.py

# led_client

from easy_comms import Easy_comms
from time import sleep
from machine import Pin
import json
import machine, neopixel
com1 = Easy_comms(0,9600)
led = Pin("LED", Pin.OUT, value=0)
np = neopixel.NeoPixel(machine.Pin(28), 1)
while True:
    p2 = Pin(27, Pin.IN, Pin.PULL_UP)
    message = com1.read()
    if message is not None:
        print(f'message: {message}')
        try:
            command = json.loads(message)
            print(f'json: {command}')
            if command['command'] == 'blink':
                if command['args'] == 1:
                    np[0] = (50, 0, 50)
                    np.write()
                if command['args'] == 0:
                    np[0] = (0, 0, 0)
                    np.write()
            sleep(0.1)
        except Exception as e:
            print(f'error: {e}')

Wifi Wireless communications

I used this pico tutorial.

Here is a diagram of how it works:

img

secret.py

ssid = 'Network ID'
password = 'password'

client.py

# Program to read RGB values from a local Pico Web Server
# Tony Goodhew 5th July 2022
# Connect to network
import network
import time
from secret import ssid, password
import socket
import machine, neopixel
np = neopixel.NeoPixel(machine.Pin(28), 1)

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
while not wlan.isconnected() and wlan.status() >= 0:
    print("Waiting to connect:")
    time.sleep(1)

# Should be connected and have an IP address
wlan.status() # 3 == success
wlan.ifconfig()
print(wlan.ifconfig())

while True:
    ai = socket.getaddrinfo("###.##.##.#", 80) # Address of Web Server, input your ip here
    addr = ai[0][-1]

    # Create a socket and make a HTTP request
    s = socket.socket() # Open socket
    s.connect(addr)
    s.send(b"GET Data") # Send request
    ss=str(s.recv(512)) # Store reply
    # Print what we received
    print(ss)
    # Split into RGB components
    l = len(ss)
    ss = ss[2:l-1]     # Strip to essentials  
    p = ss.find(",")   # Find first comma
    r = int(ss[0:p])   # Extract RED value
    ss = ss[p+1:]      # Remove red part
    p = ss.find(",")   # Find comma separator
    g = int(ss[0:p])   # Extract GREEN value
    b = int(ss[p+1:])  # Extract BLUE value
    print(r,g,b)       # Print RGB values
    print()
    np[0] = (r, g, b)
    np.write()
    s.close()          # Close socket
    time.sleep(0.2)    # wait

server.py

# Webserver to send RGB data
# Tony Goodhew 5 July 2022
import network
import socket
import time
from machine import Pin, ADC
from secret import ssid,password
import random
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)

# Wait for connect or fail
max_wait = 10
while max_wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        break
    max_wait -= 1
    print('waiting for connection...')
    time.sleep(1)

# Handle connection error
if wlan.status() != 3:
    raise RuntimeError('network connection failed')
else:
    print('connected')
    status = wlan.ifconfig()
    print( 'ip = ' + status[0] )

# Open 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)
        # Do not unpack request
        # We reply to any request the same way
        # Generate 3 values to send back
        r = random.randint(0,255)
        g = random.randint(0,255)
        b = random.randint(0,255)
        # Join to make a simple string with commas as separators
        rgb = str(r) + "," + str(g) + ","+str(b)

        response = rgb # This is what we send in reply

        cl.send(response)
        print("Sent:" + rgb)
        cl.close()

    except OSError as e:
        cl.close()
        print('connection closed')

I saved the secret.py file to both of the pico w’s and uploaded the server to one of them. after running serve it outputs the IP address of the network into the shell and I copied and pasted that value into the client.py file.

img

Next, I uploaded the client file to the other pico, connected a neopixel to it, and ran both codes. The code generated random rgb numbers on the server file, and read them from the client file to be displayed on a neopixel. Here are the rgb numbers being generated.

img

This Weeks Group Work


Last update: August 25, 2024
Back to top