Overview
In this blog we are going to look at how to wirelessly control the Kitronik Autonomous Robotics Platform for Pico with the Kitronik Mini Controller for Pico. We will use two Raspberry Pi Pico W's, one in the ARP buggy and the other in the Mini Controller.
The library and example code which we look through, can be found on our GitHub repo.
How It Works
As we are using two Pico Ws we can communicate wirelessly between the two. One of the Pico Ws will set itself up as the server which can be connected to. The other Pico W will be the client and connect to the server. Once connected, the two Pico Ws will be able to send and receive messages between them.
This allows us to setup one Pico W with the Mini Controller as the client, which sends commands to the other when we press the buttons. The other Pico W we'll setup with the ARP buggy as the server, which will receive commands from the other and move the buggy.
Mini Controller for Pico Code
Import Libraries
Before we start using the Mini Controller we first need to import some libraries that we are going to need. We'll use the KitronikPicoWClient class from the PicoWNetworking library to handle our wireless connection with the ARP buggy. We'll use the secrets dictionary from the secrets library to store the SSID and password for our wireless connection. We'll use the KitronikMiniControllerPico class from the KitronikMiniControllerPico library to help us access the components on our Mini Controller.
from PicoWNetworking import KitronikPicoWClient
from secrets import secrets
from KitronikMiniControllerPico import *
Setup the Mini Controller for Pico
With the libraries imported, we can setup our Mini Controller. We'll initialise our Mini Controller using the KitronikMiniControllerPico class and store this object in the controller variable.
# Setup Mini Controller for Pico
controller = KitronikMiniControllerPico()
Let's also create some flag variables that will help us keep track of when our buttons are being held down. We will call these flags upClicked, for example, to store when the Up button is being pressed. We can set them all to be False to start off with as our buttons aren't being pressed yet.
# Create flags for button presses
# Want to send the command once, when the button is initially pressed
upClicked = False
Setup the Wireless Connection
We'll setup our wireless connection using the PicoWNetworking library to help us. We are going to set the Mini Controller as the client meaning it will connect to the ARP buggy. To do this we want to initialise an object called client using the KitronikPicoWClient class. We'll pass the server's SSID and password from the secrets dictionary as the two inputs for the client constructor. This will tell the client class which device we want to connect to.# Setup network connection with Pico ARP
# Client - Connect to soft AP setup by the server
client = KitronikPicoWClient(secrets["ssid"], secrets["password"])
Next we need to wait until we have connected to the server. We can wait for the connection to be made using a while loop which checks the status of our wireless connection. The loop will continue to repeat while the client has not established a connection with the server.
# While not connected, waiting for connection
while not client.isWifiConnected():
pass
Now we have the client wirelessly connected to the server we need to setup a way to communicate with the server. We want to surround the next section of code in a try catch block. Inside the try block the Pico W will try and run the code. If any errors occur when running this code, then we will catch those errors and handle them in a suitable way. For our code, we could have an error while communicating with the server. If this happens, we want to close the connection with the server.
Inside of the try block, let's start by opening a communication channel with the server using the connectToServer function on the client. After our client has connected let's turn the onboard LED on to show we have full wireless communication available. At the end of the try block, we'll want to disconnect from the server to close the wireless communication.
try:
# Connect to the server to open a communication channel
client.connectToServer()
# Turn LED on to show its connected
led.on()
# The rest of our code will go here
# Close connection
client.disconnect()
except Exception as e:
# Error occurred, close connection
client.disconnect()
Communicate with the ARP Buggy
For our communication with the ARP buggy we are going to put this inside of an infinite loop. This means our loop will continue repeating forever. We can use a while loop with the condition set to True to make an infinite loop. At the start of our loop we want to create the message variable and set it to be an empty string.
# Loop forever
while True:
# Clear message
message = ""
Next we are going to detect button presses on our Mini Controller. We'll add these inside of the infinite loop to continuously check when a button is being pressed. An example of this is our Up button. We'll check when the Up button is being pressed using an if statement and using the Up.pressed() function as the condition. Then when the Up button on our Mini Controller is being pressed down, the code inside of the if statement will execute.
Inisde our if statement we are going to check that the upClicked flag has not been set, or is False. When the upClicked flag is True we know that we have already detected the current button press. This allows us to only send the command to the ARP buggy a single time each button is pressed, and stops us from overloading the wireless connection with commands.
When we know this button press has not been detected yet, we want to set the up flag to True and set the message variable to have the Forward command to move the ARP buggy forward.
if controller.Up.pressed():
# When Up pressed and up flag isn't set
if not upClicked:
# Set the up flag and send Forward command
upClicked = True
message = "Forward"
At the end of the button detection if statements, we want to have an else statement. This will allow us to reset our button flags and send the Stop command to stop the ARP buggy moving around. Inside of the else statement we need to check when the upClicked flag is True. When it is, we are going to set the upClicked flag to False and set the message variable to have the Stop command.
else:
# Clear any button flags and send Stop command
if upClicked:
upClicked = False
message = "Stop"
So far we haven't sent any commands to our ARP buggy. We'll add this to the end of our infinite loop and start by checking whether the message variable is empty. This if statement checks when the message variable is not empty, and means that we have a command stored inside of message.
When we have a command to send, we can use the client function called sendToServer which takes a single input for the message we want to send to the server. As we want to send our command, we'll use the message variable as the input for the function to tell the ARP buggy what to do.
# When we have a command in message
if message != "":
# Send command to server
client.sendToServer(message)
Pico Autonomous Robotics Platform Code
Import Libraries
Before we start using the ARP buggy we first need to import some libraries that we are going to need. We'll use the KitronikPicoRobotBuggy class from the PicoAutonomousRobotics library to help us access the components on our ARP buggy. We'll use the KitronikPicoWServer class from the PicoWNetworking library to handle our wireless connection with the Mini Controller. We'll use the secrets dictionary from the secrets library to store the SSID and password for our wireless connection.
from PicoAutonomousRobotics import KitronikPicoRobotBuggy
from PicoWNetworking import KitronikPicoWServer
from secrets import secrets
Setup the Autonomous Robotics Platform Buggy
With the libraries imported, we can setup our ARP buggy. We'll initialise our ARP buggy using the KitronikPicoRobotBuggy class and store this object in the buggy variable.
# Setup Pico Autonomous Robotics Platform Buggy
buggy = KitronikPicoRobotBuggy()
Let's also create a speed variable to store current speed of our buggy. We'll set this to 50% to start off with.
# Set the buggy speed to 50%
speed = 50
Setup the Wireless Connection
We'll setup our wireless connection using the PicoWNetworking library to help us. We are going to set the ARP buggy as the server meaning it will receive the connection from the Mini Controller. To do this we want to initialise an object called server using the KitronikPicoWServer class. We'll pass the SSID and password from the secrets dictionary as the two inputs for the server constructor. This will start the server using the SSID and password provided, allows devices to connect to it using those values.# Setup network connection with Mini Controller for Pico
# Server - Start soft AP for client to connect to
server = KitronikPicoWServer(secrets["ssid"], secrets["password"])
Next we need to wait until the server has set itself up, and is available for devices to connect to. We can wait for it to turn on using a while loop which checks the status of our wireless connection. The loop will continue to repeat while the server is not fully setup.
# While not turned on, waiting for access point
while server.isAPConnected() == False:
pass
Now the server is available for wireless connections we want to listen for the client to open a communication channel. This will allow the client and server to send messages to each other. We want to surround the next section of code in a try catch block. Inside the try block the Pico W will try and run the code. If any errors occur when running this code, then we will catch those errors and handle them in a suitable way. For our code, we could have an error while communicating with the client. If this happens we want to close the connection with the client.
Inside of the try block, let's start by listening for the client to open a communication channel using the listenForClient function on the server. After our server has opened a communication channel let's turn the onboard LED on to show we have full wireless communication available. At the end of the try block, we'll want to disconnect from the client to close the wireless communication.
try:
# Listen for the client to open a communication channel
server.listenForClient()
# Turn LED on to show its connected
led.on()
# The rest of our code will go here
# Close connection
server.disconnect()
except Exception as e:
# Error occurred, close connection
server.disconnect()
Communicate with the Mini Controller
For our communication with the Mini Controller we are going to put this inside of an infinite loop. This means our loop will continue repeating forever. We can use a while loop with the condition set to True to make an infinite loop. At the start of our loop we want to create the message variable and set it to be an empty string.
After this we want to receive the command from our Mini Controller. We will receive a message from the client by using the server function called receiveFromClient. This function returns the string message that has been received by the server and we'll store this in the message variable. The message variable will store the command we have been sent by the Mini Controller.
# Loop forever
while True:
# Clear message
message = ""
# Receive command from client
message = server.receiveFromClient()
Next we are going to check which command we have received in the message variable. To do this we'll use if statements to test the contents of message against our known commands. The first one will be the Forward command and checking when message is equal to it.
When we have received the Forward command in message we simply want to turn both motors on going forward at our current speed.
if message == "Forward":
# When Forward command received, move buggy forward
buggy.motorOn("l","f",speed)
buggy.motorOn("r","f",speed)
At the end of checking for known commands we want to use an else statement which essentially acts as our Stop command. Inside the else statement we are going to turn off both motors on the buggy, to stop any movement.
else:
# When we don't receive an above command
# Assume Stop command and turn off motors
buggy.motorOff("l")
buggy.motorOff("r")
Conclusion
In this blog we have learnt how to use the wireless networking on the Pico W's to control the ARP buggy using the Mini Controller. Now that we have seen how we can add the basic functionality, you can now customise this code to make your own fun projects using the ARP buggy and Mini Controller.
You can also check out the GitHub repo to see the full example code project.
©Kitronik Ltd – You may print this page & link to it, but must not copy the page or part thereof without Kitronik's prior written consent.