Networking and Communications

Assignment

-individual assignment:
-design, build, and connect wired or wireless node(s) with network or bus addresses
-group assignment:
-send a message between two projects

Resources

pico to pico

Throughout The Week

Networking two picos

Wired

To start everything off I followed the raspberry pi pico rp2040 to raspberry pi pico rp2040 tutorial linked above to learn how to network them together. I started off by wiring the whole thing. I linked the pin one on the first raspberry pi pico otherwise known as the TX pin to the pin two on the other pico known as the RX pin. The RX pin receives the data being sent through the UART by the TX pin. I also did the opposite connecting the Rx pin on the first pico to the second pin. Lastly I added a communal ground so that nothing shorted. Here is an image of the wiring.
image
After I was done with the wiring it was time to code. The tutorial gave me a basic library and code to get the two picos to talk and recieve eachothers messages. To do this I put in this library onto both picos so that I could send messages over the serial port.

#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


The next step was to upload a seperate code onto poth picos so that one would send a message and one would recieve it. Thats why I uploaded this code that sends the message ahoy on the first pico and recieves it on the second one printing message recieved on the serial monitor. Here is both codes.

Here is the sending code that sends the message ahoy and checks if it is being recieved.

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


Here is the code that recievs the message and logs it in the console.

# 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


Here is a video of the whole thing working.


After I got it working I made the Leds on the boards blink on and off through the master board telling the slave board what to do. Here are the codes that were running

This code was the code that was controlling the other pico and turned its own led on and off, telling the other board to do the same.

# 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(25, 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)


Here is the code that recieved the command and turned on and off its own LED.

# led_client

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

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

while True:
    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'] == 'on':
                    led.on()
                if command['args'] == 'off':
                    led.off()
            sleep(1)
        except Exception as e:
            print(f'error: {e}')


Here is a video of those codes working.


After getting it all to work I wanted to add my own thing to the whole board so I added a button that I connected to the master board and made it so when I click it It toggles its button and sends the command for the other board to do through the UART. Here is the wiring the new circuit.
image
For all the code all I had to change was add an if button clicked statment into the server code so it only ran when the button was clicked so Here is my edited code and a video of it working.

# 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(25, Pin.OUT)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)


while True:
    com1.send(str(json.dumps(command)))
    B = button.value()
    if B:
        command = {'command':'blink', 'args': 'on'}
        if command['args'] == 'on':
            com1.send("on")
            led.value(1)

    else:
        command = {'command':'blink', 'args': 'off'}
        if command['args'] == 'off':
            led.value(0)
            com1.send("off")
    sleep(1)



Making the board

After I had completly finished making and breadboarding out my board I then Had to design it in Ki-Cad. I started by getting in two raspberry pi pico rp 2040's into the schematic and connecting each of their TX pins to the others RX pin.
image
I then had too add in the buttons, resistors, and, Leds in to schematic with each button having a pull down resistor.
image
Lastly I had to put it all into the board editor and plan it all out. Here is the final board.
image

Milling and Soldering the board

After I had designed the whole board all that was left was to actually mill out the board with a 1/32 inch bit. It took 15 minutes and here is the final result.
image
I then had to start soldering all the pieces on. I started with the raspberry pi pico rp2040's because they are the pieces that are hardest the solde because of the many points of contact that you have to solder.
image
After soldering my micro controller down I soldered down the 330 olm resistor that helps the led not burn out from the power going out of the Pico.
image
After putting the resistor for the led on the board I soldered the LED onto the board.
image
Next I had to solder the button for an input on my board to help test with the networking.
image
After soldering the button on I had to solder a 100 ohm pull down resistor so that the button would work properly. And with that I had completly soldered one side of the PCB together.
image
The last step was doing everything over again to have a complete board with both sides soldered.
image

Testing the Board

Once I was completely done soldering all that was left was to upload the code written above to each of the picos and run it on each. Here is a video of my board working with networking.


Wireless

After figuring out wired I wanted to figure out how to do wireless networking to network my board to my friend Merrit Backerman's board for the group work this week.

I started off by following the wireless tutorial linked above to figure out how to connect to pico W's. It is done with the codes below.

ssid = 'sside'
password = 'password'


This is a library for the code to call nameing your wifi name and its password. This goes on both Rasberry pi pico W's

// 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 = 100
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')


This is the code that sets on of the picos as a server to send messages.

import network
import time
from secret import ssid, password
import socket


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)

    wlan.status() # 3 == success
    wlan.ifconfig()
    print(wlan.ifconfig())
    while True:
    ai = socket.getaddrinfo("192.168.0.15", 80) # Address of Web Server
    addr = ai[0][-1]
    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()
    # Set RGB LED here
    s.close()          # Close socket
    time.sleep(0.2)    # wait

This is the code that sets one of the picos to a client to recive messages from the other pico.

ai = socket.getaddrinfo("192.168.1.27", 80) # Address of Web Server This is the code that you need to change based on your wifi. you set it to your IP adress and then port 80 becuase that is the default port.
*** This is a random hotspot IP that changes every time I use it so it does not mean anything.
Once I got all the code downloded I then hit run on both the picos and here is a image of connection being made beteween them.
image
image

Once I got this working I needed to get it to turn on the onboard LED of the other pico so I changed the client server codes responce from the r,g,b values to this. I also did declare the variable hi as 1 at the start of the code so that it would work.

 if hi == 1:
            hi = 0
             # This is what we send in reply
        else:
            hi = 1
        response = str(hi)
        cl.send(response)
        print("Sent:" + response)
        cl.close()

This way it sent out a 1 and 0 for an easy way to turn the LED on and off. Once that was done I changed the Client code to this

 if r == 1:
        led.on()  # Turn on the LED
        print("on")
 elif r == 0:
        led.off()  # Turn off the LED
        print("off")


This way it turns off the Led and back on when it recieves a 1/0. With this I also had to declare the onboard LEd pin to be a pin.out so that I could use it. Once I had changed it It worked as seen here.



Group Work

Once I was done with wireless connections me and Merrit Backerman decided to go further into wireless and connect the two boards we made this week. To do this we took my original code for the two boards and edited it so that instead of controlling the onboard LED it would control the LED that we soldered onto the board to see the connection. To do this I had to edit parts of the code to specify that the LED was pin 15, so that my boards Pico W was the client and Merrit's was the server so that my Pico W could recieve his boards information and turn off and on my LED according to it. Taking all that into account here is the code we ended up with.

# 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)
hi = 1

# Wait for connect or fail
max_wait = 100
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)

        if hi == 1:
            hi = 0
             # This is what we send in reply
        else:
            hi = 1
        response = str(hi)
        cl.send(response)
        print("Sent:" + response)
        cl.close()

    except OSError as e:
        cl.close()
        print('connection closed')
# 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

from machine import Pin
led = Pin(15, Pin.OUT)


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("172.20.10.4", 80) # Address of Web Server
    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

    # Split into RGB components
    l = len(ss)
    ss = ss[2:l-1]     # Strip to essentials  
    p = ss.find(",")   # Find first comma
    r = int(ss[p])   # Extract RED value
    ss = ss[p+1:]      # Remove red part
    print(r)

    print()
    # Set RGB LED here
    s.close()          # Close socket
    time.sleep(0.2)    # wait

    if r == 1:
        led.on()  # Turn on the LED
        print("on")
    elif r == 0:
        led.off()  # Turn off the LED
        print("off")
ssid = 'sside'
password = 'password'

With this we were able to send 1 and 0 values from the server code which is the first code that was listed and recieve them and turn the LED on and off through the second code listed. The last code is the secret code which just list the network SSID and PASSWORD so that it knows what network to connect too. Here is a video of the whole process working.


For more information on this go to our group work page listed here.(if its not then it is not merged yet)

Summary

This week I learned how to network pico w's through UART and through the Network or over wifi. This will help alot on the final project because IM going to be using UART to communicate with my Time of Flight sensor and im going to be connecting my Raspberry pico w to the internet so I can control my final project from my phone. With thi sweek I now have the bare bones on how to control my project and how im going to be able to communicate data from the Time of Flight Sensor and my pico w.

Files

Week 13 Downloads