.st0{fill:#FFFFFF;}

News

Book sample: Node-RED & Raspberry Pi Pico 

 September 21, 2023

By  Peter

Join Our Mailing List

We publish fresh content each week. Read how-to's on Arduino, ESP32, KiCad, Node-RED, drones and more. Listen to interviews. Learn about new tech with our comprehensive reviews. Get discount offers for our courses and books. Interact with our community.

One email per week, no spam, unsubscribe at any time.

I am finishing a new book on Node-RED and the Raspberry Pi Pico W. This book is filled to the brim with projects combining Node-RED with Raspberry Pi Pico W (the Pico version with built-in WiFi). These projects span simple environment monitoring web Dashboards to more advanced ones using cloud APIs.

I’m sharing a couple of projects from this book in this post. The first explains how to use the “catch” node, equivalent to the “try” command you’ll find in many programming languages. The second is an example from the MicroPython primer (a mini-book within a book) that shows how to use the serial port on a microcontroller.

By the way, if you want to become an early adopter, please submit this form. There is nothing to pay, and you will not commit to purchasing this book when it is published. Adding your email address to the early adopters’ list lets me email you information about my progress with the book, including how to purchase the draft at a steep discount when the first draft is ready.

Sample content

The “catch” node

The catch node in Node-RED is used for error handling. It captures runtime errors or exceptions in a flow, allowing you to manage them effectively. When an error occurs in any node that the catch node is configured to watch, the catch node triggers and sends a message object containing details about the error.
The catch node in Node-RED is equivalent to similar commands in languages like Python and Ruby. For example, you can use the try, except, finally blocks for exception handling in Python. Here’s a simple example:

try:
    result = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero.")
finally:
    print("Execution completed.")

In this example, an attempt is made to divide ten by zero within the try block. This produces a ZeroDivisionError, caught in the except block, and the message “Cannot divide by zero.” is printed. The “finally” block is executed regardless of whether an exception was raised, printing “Execution completed.”
In Ruby, exception handling can be done using begin, rescue, and ensure blocks. Here’s a straightforward example:

begin
    result = 10 / 0
rescue ZeroDivisionError
    puts "Cannot divide by zero."
ensure
    puts "Execution completed."
end

Like the Python example, this Ruby code attempts to divide ten by 0 in the beginning block. This raises a ZeroDivisionError, caught in the rescue block. The message “Cannot divide by zero.” is printed. The ensure block is always executed, regardless of an exception, and prints “Execution completed.”
Let’s look at how exception handling works in Node-RED with “catch”.

How the “Catch” Node Works

When you add a catch node to your flow, you can configure it to listen for errors from all nodes in the same tab or from specific nodes. Once an error is caught, the catch node generates a new message object that contains information about the error. This message object usually has properties like msg.payload for the error message, msg.topic for categorising the error, and msg.error containing the complete error object with extra details such as the error code and stack trace.
In the screenshot below, you can see the properties window for the ”catch” node. The configuration is simple and requires you to set the scope to “all nodes” or “selected nodes“.

The “catch“ node properties allow you to set the scope.

If you choose “selected nodes”, all nodes in the current flow will be shown in a list from where you can select the ones you want to monitor for errors.

You can select specific nodes to monitor for errors.

An Example Showing the Catch Node Operating Within a Flow

Let’s create a simple flow to demonstrate how the catch node works. The flow will consist of an inject node, a function node that deliberately produces an error, and a catch node to capture that error.
Here are the nodes that make up this example:

  1. Inject Node: Use this node to start the flow. You can set it to inject a timestamp or any other simple payload.
  2. Function Node: Insert a function node right after the inject node. Inside the function node, write some code that will produce an error. For instance, you could use the following JavaScript code to throw an error:
throw new Error("This is a deliberate error");
  1. Catch Node: Add and configure a catch node to catch errors from the function node.
  2. Debug Node: Connect the catch node to a debug node. This will display the error message in the debug sidebar when the flow runs and an error is caught.

Connect these nodes sequentially: Inject Node -> Function Node -> Catch Node -> Debug Node. You can see the flow below, as well as the debug node output (I have expanded the JSON object):

The “catch” node waits for errors in the “function” node.

After deploying this flow, click the inject node’s button to initiate the sequence. The function node will throw an error, and the catch node will capture this error. The debug node will then display the error message, showing exactly what went wrong. Your flows can have multiple “catch” nodes. It can have one “catch” node listening for errors across all nodes in the flow or multiple “catch” nodes, each listening for errors in specific nodes.
This example demonstrates the core functionality of the catch node simply and understandably. Mastering the catch node can make your flows more robust and easier to debug.

Serial communications with the Raspberry Pi Pico

As virtually all microcontrollers, the Pico and Pico W also provide UART (Universal Asynchronous Receiver-Transmitter) channels that can be used to provide connectivity with nearby devices. The Pico and Pico W have two UART channels.
A UART channel allows bi-directional asynchronous serial communication and is one of the most common (and oldest) communications technologies.
UART (Universal Asynchronous Receiver/Transmitter) is a hardware protocol for asynchronous serial communication between devices. UART can interact with other microcontrollers, sensors, or a Raspberry Pi Pico computer terminal. This segment aims to provide a fundamental understanding of using UART communications on a Raspberry Pi Pico with MicroPython.
I decided to include this chapter in this book because UART, despite its age, is a beneficial communications technology. While Wi-Fi and Bluetooth are available in almost all modern microcontrollers, good-old UART is often a better option for your project. This may be because Bluetooth is unavailable on the other device, a WiFi hotspot might be unreliable or inoperative, or it is overkill considering the resources they require compared to UART. Therefore, knowing how to use UART in your project is helpful in your toolbox.
If you want to implement the instructions and code below, you will need two Raspberry Pi Picos. One will be the transmitter, and the other will be the receiver.

Setting Up UART with machine.UART

The UART class from the machine module is used to set up UART communication. You’ll need to specify the UART channel, baud rate, and, optionally, the pins for transmitting (TX) and receiving (RX).
Here is an example:

from machine import UART, Pin

# Initialize UART1
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))

This code first imports the UART and Pin classes from the machine module. We initialise a UART object named uart1 on UART channel 1 with a baud rate of 9600 bits per second. The transmitting (TX) is set to GPIO pin four, and the receiving (RX) is set to GPIO pin 5.

Sending data with write()

The write() method is used to send data over UART. Here is an example:

# Sending a string "Hello"
uart1.write("Hello")

The uart1.write(“Hello”) command sends the string “Hello” through UART1.

Receiving data with read()

The read() method reads a specified number of bytes from the UART buffer. Here is an example:

# Reading 5 bytes from the UART buffer
received_data = uart1.read(5)

The command uart1.read(5) reads 5 bytes of data from UART1 and stores it in the variable received_data.

Full UART communication example

Let’s consolidate the example code into a single program that establishes serial communications between two Picos. Here is the complete program:

from machine import UART, Pin
import time

# Initialize UART1
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))

# Wait for a second
time.sleep(1)

# Send data
uart1.write("Hello")

# Wait to receive data
time.sleep(1)

# Read received data
received_data = uart1.read(5)
print("Received:", received_data)

You can upload this code to both Picos. You should customise the message that each one sends to the other. For example, Pico 1 should send the message “Hello from Pico 1” and Pico 2 the message “Hello from Pico 2”. Using jumper wires to connect the TX pin of Pico 1 to the RX pin of Pico 2 and the RX pin of Pico 1 to the TX pin of Pico 2.
This code, UART1, is initialised with a baud rate of 9600, TX pin as GPIO 4, and RX pin as GPIO 5. A 1-second delay is introduced to ensure everything is set up. Then, the string “Hello” is sent over UART1. Another 1-second delay is added to wait for the incoming data. And finally, 5 bytes are read from UART1, and the received data is printed.
Understanding UART communication on the Raspberry Pi Pico opens doors to many exciting projects, especially those that require communications between a microcontroller and devices that only support UART, such as GPS receivers.


Tags

MicroPython, Node-RED, Raspberry Pi Pico


You may also like

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Understanding the power requirements is crucial for any enthusiast using the Arduino Uno in their projects. How you manage voltage, amperage, and power sources impacts the success or failure of your endeavours. In this guide,

Read More
The Ultimate Guide to Powering Your Arduino Uno Board

If you are curious about how electronic devices work, understanding the fundamentals of the operation of their basic components is essential. Every electronic device—from the smartphones in our pockets to the satellites orbiting our planet—contains

Read More
A Guide to Essential Electronic Components in Circuits