I, like most of the maker world, was caught totally by surprise last week when the Raspberry Pi team announced their first microcontroller, the Pico. A custom, dual core, M0+ for 4 bucks? Sign me up!
I got my Pico this week and it's an impressive little device with lots of GPIOs, peripherals, and support for both C and MicroPython. And since the Notecard Python library supports MicroPython, CircuitPython and Python out of the box, I figured I'd wire up the Notecard and show off how you can use the two to add cellular connectivity to your Pico projects.
In this article I'll show you how to:
- Flash MicroPython to a Raspberry Pi Pico.
- Wire-up and connect to the Notecard over I2C.
- Communicate with the Notecard from MicroPython.
- Add a BME680 Temperature and Humidity sensor and send readings to the Notecard and Notehub.io cloud service.
The complete source for this project, including libraries for the notecard and BME680 sensor are in the notecard-pico GitHub repo.
Flashing MicroPythonFirst things first, I needed to get MicroPython on my Pico. I initially used the UF2 image from the official Pico documentation, but discovered quickly that, as of my initial experiments, that distribution didn't include the MicroPython ujson
library and since the Notecard speaks JSON, and the note-python library depends on JSON support, I had to find an alternative.
Thankfully, the Pimoroni team has a Pico-compatible fork of MicroPython that includes ujson, so I downloaded a recent UF2 from their repo. Then, following the official getting started guide, I held down the BOOTSEL button on the Pico as I plugged the board into USB and dragged the UF2 file onto the RPI-RP2 mass storage device on my machine. And just like that, I was running the Pico with MicroPython.
Note: Support for ujson
and other extended MicroPython modules is expected in the official distribution soon!
For creating Pico firmware, the official documentation and guides recommend you use the Thonny IDE, which seems like a nice tool, but since I use VS Code for Python and CircuitPython development, I figured I'd use it for this project as well. I installed a MicroPython extension from the VS Code extensions tab, created a project, and connected to the REPL on the Pico via the /dev/tty.usbmodem0000000000001
Serial-Over-USB port, which feels like the z-index:9999;
of device enumeration.
I've done some MicroPython work on the ESP32 in the past and one of my favorite things about the experience is the on-device REPL. It just feels so magical to inspect GPIOs and toggle pins while physically connected to a Microcontroller. So as soon as I connected, I imported the machine
library and toggled the Pico's onboard LED, which is at Pin 25.
import machine
led = machine.Pin(25, machine.Pin.OUT)
# Turn the LED on
led.value(1)
#Turn the LED off
led.value(0)
With the Pico connected, it was time to add in the Notecard.
What is the Notecard?Since the Pico doesn't come with Wi-Fi, cellular or Bluetooth, I decided to connect it to the Blues Wireless Notecard to add some cellular IoT goodness. The Notecard is a cellular and GPS-enabled device-to-cloud data-pump that comes with 500 MB of data and 10 years of cellular service for $49. No activation charges, and no monthly fees.
The Notecard is a small 30 by 34 mm SoM that’s ready to embed in a custom project via its m.2 connector. But Blues also provides a series of expansion boards, called Notecarriers, that include an m.2 socket for the Notecard and a number of other features for prototyping. For this project, I used the Notecarrier-AL which has onboard cellular and GPS antennas, a LiPo battery port, and a pin header strip, making it perfect for this project.
On the cloud side, the Notecard is preconfigured to talk to Notehub.io, the Blues Wireless service that enables secure device-to-cloud data flow. Notecards are assigned to a project in Notehub, which then sync data into those projects for routing to your cloud application.
Wiring the Notecard to the PicoThe Notecard can connect to any MCU or SBC over Serial or I2C. I chose I2C for this project and used the Pico pinout diagram to connect jumper wires from the Notecard's power, GND, SDA and SCL pins to the Pico. That diagram is especially helpful as the GPIO pin labels are silkscreened on the bottom of the Pico.
My next step was to put down the hardware for a minute, open a browser tab, and create a new project at Notehub.io. It's a pretty straightforward process and the blues wireless developer portal contains step-by-step instructions for creating an account, projects, and more. The key thing a new project gets me is an identifier called a ProductUID, which is used to associate a Notecard to Notehub.io so all my data ends up in the right place.
Talking to the Notecard with MicroPythonWith the devices connected and a ProductUID in hand, I was ready to connect to the Notecard in firmware. First, I downloaded the latest release of the note-python library and copied the notecard
directory into the lib
directory on my Pico.
Next, I added a few lines of code to main.py
on the Pico to import the library, configure an I2C connection to the Notecard, and send a hub.set request, which is used to set the ProductUID and set-up some syncing rules for the Notecard.
from machine import Pin, I2C
import notecard
productUID = "com.your_company.your_name:pi_pico"
i2c = I2C(0)
card = notecard.OpenI2C(i2c, 0, 0, debug=True)
print("Connected to Notecard...")
req = {"req": "hub.set"}
req["product"] = productUID
req["mode"] = "periodic"
req["inbound"] = 120
req["outbound"] = 60
rsp = card.Transaction(req)
Then, I uploaded main.py
and the lib
directory to run my code. Since I initialized the Notecard library with debug=True
, all of my requests and responses will show up in the terminal as my firmware executes.
I had the Pico and Notecard talking, which was great, but to make this a real project, I needed to add a sensor. I chose my go-to, the Adafruit BME680 and wired it up to I2C on the Pico as well.
As with the Notecard, I added a library to make it easier to work with the BME680. Since I'm using MicroPython, the CircuitPython version of the library can't be used as-is, but worked just fine after some light modifications. If you're following along, you can use the adafruit_bme680.py
library in my GitHub repo.
Once added, I adapted my main.py
source to import the library, initialize the sensor and take temperature and humidity readings every 60 seconds.
import utime
from machine import Pin, I2C
import notecard
import adafruit_bme680
productUID = "com.your_company.your_name:pi_pico"
i2c = I2C(0)
card = notecard.OpenI2C(i2c, 0, 0, debug=True)
print("Connected to Notecard...")
bmeSensor = adafruit_bme680.BME680_I2C(i2c)
print("Connected to BME680...")
req = {"req": "hub.set"}
req["product"] = productUID
req["mode"] = "periodic"
req["inbound"] = 120
req["outbound"] = 60
rsp = card.Transaction(req)
while True:
temp = bmeSensor.temperature
humidity = bmeSensor.humidity
print("\nTemperature: %0.1f C" % temp)
print("Humidity: %0.1f %%" % humidity)
utime.sleep(60)
Then I loaded everything up on my Pico and watched environmental readings stream across my terminal.
Once I had my BME680 connected and reading the temp and humidity in my office, it was time to send that data to the Notecard (and to the cloud)! I adapted my main.py
program one final time to send a note.add request each time I take a reading.
req = {"req": "note.add"}
req["file"] = "sensors.qo"
req["body"] = { "temp": temp, "humidity": humidity}
req = card.Transaction(req)
I also added a few lines to turn on the Pico LED when a new reading is taken from the BME680, and turn it off after the data is sent to the Notecard. The complete source for my program is below.
import utime
from machine import Pin, I2C
import notecard
import adafruit_bme680
ledPin = 25
productUID = "com.your_company.your_name:pi_pico"
led = Pin(ledPin, Pin.OUT)
i2c = I2C(0)
card = notecard.OpenI2C(i2c, 0, 0, debug=True)
print("Connected to Notecard...")
bmeSensor = adafruit_bme680.BME680_I2C(i2c)
print("Connected to BME680...")
req = {"req": "hub.set"}
req["product"] = productUID
req["mode"] = "periodic"
req["inbound"] = 120
req["outbound"] = 60
rsp = card.Transaction(req)
while True:
# Turn on the LED to take a reading
led.value(1)
temp = bmeSensor.temperature
humidity = bmeSensor.humidity
print("\nTemperature: %0.1f C" % temp)
print("Humidity: %0.1f %%" % humidity)
req = {"req": "note.add"}
req["file"] = "sensors.qo"
req["body"] = { "temp": temp, "humidity": humidity}
req = card.Transaction(req)
# Turn off the LED
led.value(0)
utime.sleep(60)
And for a final time, I uploaded main.py
and ran it on the Pico.
As the Notecard receives new data (called Notes), it securely connects to the Notehub.io cloud service and sends that data to my project, which I confirmed by visiting the event dashboard for the project.
The Notecard is a powerful little device, and with MicroPython support, it's easy to add low-cost, no-fees cellular IoT to your Pico-powered projects! To learn more about the Notecard, visit blues.io. I can't wait to see what you build.
Comments