Overview

The Pi-Plates MICROpi is a low cost yet surprisingly powerful controller for your Pi-Plate stack. Similar to the Raspberry Pi PICO, it is designed around theRP2040 microcontroller which, with few exceptions, supports all the functions of our Pi-Plates. The MICROpi is shipped  preloaded with Micropython - a small footprint version of Python 3.

MICROpi Features

  • The Raspberry Pi RP2040 - a 32-bit dual ARM Cortex-M0+ microcontroller with 264K of SRAM
  • A Raspberry Pi 2X20 header with support of all the signals required by Pi-Plates
  • 16 Mbytes of QSPI for program and data storage
  • An I²C controlled temperature sensor
  • An I²C controlled real time clock
  • A microSD memory slot for increased data storage
  • A micro USB connector for programming and control
  • A USB C power connector
  • A power select jumper
  • A 3D Printed bezel with
    • An I²C controlled, forward facing, 0.91" 128X32 OLED display divided into 3 lines of text
    • Three forward facing LED indicators:
      • GREEN for power
      • YELLOW for microSD activity
      • RED for user control
  • Two forward facing user controlled buttons
  • A MICROpi python module that provides convenient access to all of the above peripherals
  • A boot select header for installing your own OS

Differences from Raspberry Pi

The MICROpi lacks a number of features found on a Raspberry Pi board including:

  • An Ethernet connection
  • WiFi
  • Bluetooth
  • Video outputs
  • Camera inputs
  • GBytes of RAM
  • USB Connections

Instead, the MICROpi has:

  • Low power consumption
  • Surprisingly fast floating point and integer math processing
  • Versatile I/O features
  • Much lower cost
  • An onboard front facing display
  • A real time clock
  • An onboard temperature sensor
  • Easy programming and control from your PC using Thonny or Visual Studio

Assembly

The MICROpi ships with four 17mm standoffs and four 10mm spacers. These should be fastened to the four holes located in the corners of the board. Insert the threaded end of the 17mm standoff into the top of the board and secure it in place with a 10mm spacer. Repeat for the remaining three holes. If you mount your MICROpi to a CASEplate or DINplate, you can discard the 25mm spacers that these products ship with and simply screw the bottom section directly to the 10mm spacer.

After the standoffs are in place, remove the included CR1220 battery from its packaging and pop it into the holder with the plus sign + facing up.

Connecting

There are two connectors on the MICROpi that facilitate programming and power. For programming, the microUSB connector is used. This connector can also provide power to the board but it is limited to what your PC can provide. As shipped, the MICROpi is configured to get power from this connector. But, if you have a a number of Pi-Plates attached (especially RELAYplates), you should consider using the USB-C input for power. To do this, move the power select jumper  down one position.

Note that it is still possible to program and interact with the MICROpi through the microUSB connector when power is being applied from the USB-C

Coding

Programming Environments

First, it is assumed that you are familiar with Python programming. Second, there are two popular programming environments that you can use with the MICROpi. One is Microsoft's Visual Studio Code and the other is Thonny. We use Thonny to develop our code and for the examples that follow because it's the same environment available for Python3 on the Raspberry Pi. However, if you would prefer Visual Studio Code, head to THIS link and get this extension to assist with your coding. Note that both of these development environments work for Windows and macOS. It is also possible to program and explore the MICROpi using Thonny on a Raspberry Pi.

Getting Started with Thonny

Downloading

Thonny can be downloaded from THIS link.

Connecting to MICROpi

Once Thonny is installed, connect the included USB cable between your PC, mac, or Raspberry Pi and the microUSB connector on the MICROpi. Open Thonny and you'll see a window similar to the one shown below.  To connect, select "MicroPython (RP2040) • COMX" from the popup window in the lower righthand corner. This will set the MICROpi as your target device. You should also see a reference to  "MICROpi with RP2040" in the Python Shell window.

There is a wealth of information about Thonny out there so, if this is your first exposure, we recommend that you review it and become familiar with it before proceeding.

On Board Peripherals

All of the peripherals on the MICROpi are initialized and accessed by loading the MICROpi module. In the Shell, type "import MICROpi as Mp" and press <ENTER>. After this you should see this:

MicroPython v1.20.0-396-g1dedb65e6-dirty on 2023-08-28; MICROpi with RP2040
Type "help()" for more information.
>>> import MICROpi as Mp
>>>

The display should look like this:

Your Free Ram and Free Mem values may vary from that shown above.

LEDs

Referring to the image above, the lower red led on the front bezel can be user controlled using the following functions:
setLED() - turns on the user LED
clrLED() - turns off the user LED
toggleLED() - toggles the state of the user LED. If the LED is initially off, this function will turn it on. If the LED is initially on, this function will turn it off.

Here's a simple example that flashes the LED once per second:

Hitting the red STOP button on the Thonny toolbar will end the above script.

Buttons

The MICROpi provides two general purpose buttons to the right of the bezel:

Both buttons have hardware debounce and, when pressed, interrupt the RP2040 and set a flag. This approach ensures that you will never miss seeing a button press even if your code is busy when it occurs. There is only a single function for the buttons:

getBUTTON(button) - returns the boolean status of the selected button. Valid button numbers are 1 and 2. The returned status is False for button up and True for button down.

In the following example, Button 1 will turn on the red LED and Button 2 will turn it off:

Again, hitting the red STOP button on the Thonny toolbar will end the script.

Display

The MICROpi includes a front facing 128X32 OLD display based on the SSD1306 driver chip. The display communicates with RP2040 on the I2C bus at address 0X3C. As configured, the display shows three lines of text that are 15 characters long.  The functions available include:
dispWriteline(text,line) - writes a single line of text to the specified line. The text argument should be a string of 15 or fewer characters. Strings greater than 15 characters will be truncated. The line argument should have a value of 1, 2, or 3. All text is left justified.
dispWriteall(textList) - writes three lines of text to the display at once. textlist is a 3 element list of strings with a maximum length of 15 characters.

The following script displays a welcome message by updating all three lines of text at once:

This script updates the status of the user controlled LED on line 3 of the screen whenever the buttons are pressed:

Temperature Sensor

The temperature sensor is a Texas Instruments TMP102 accessed via the I2C bus at address 0x48. This device is accurate to ±2°C and can be accessed with the following functions:
getTEMPC() - returns the temperature in degrees Celsius as numeric value
getTEMPF() - returns the temperature in degrees Fahrenheit as numeric value
getTEMPK() - returns the temperature in degrees Kelvin as numeric value

The following example uses the buttons to cycle through the different temperature functions and display them on line 3 of the display:

Real Time Clock

Description

Micropython provides a real time function that is initialized by the clock on the host computer. However, this does not work if the MICROpi was operating remotely. To make up for that we added a DS1307 RTC chip so that your applications will always have an accurate clock for data logging. Like the other onboard peripherals, the DS1307 is connected to the I2C bus at address 0X68.

Functions

getTIME() - returns a string with the time with format 'HH:MM:SS'
getDATE() - returns a string with the date with format 'MM/DD/YYYY'
setTIME() - sets the time on the real time clock to the computer's time. This function only needs to be executed once.
getDATETIME() - returns a tuple of numeric values with format: (YYYY, MM, DD, DAY OF WEEK, HH, MM, SS, SUB)
Where:

YYYY is the year
MM is the month (1-12)
DD is the day (1-31)
DAY OF THE WEEK is a single digit with Monday=1, Tuesday = 2, through to Sunday = 7
HH is hours
MM is minutes
SS is seconds
SUB is subseconds and is always 0.

getDAY() - returns a string with the day of the week. Returned values are 'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'

When powering up the MICROpi for the first time, you should initialize the RTC. This can be done by typing two lines in the python shell. Remember, this only has to be done once:

>> import MICROpi as Mp
>> Mp.setTIME()

To be sure, we can read the time, date, and day back:
>>> Mp.getTIME()
'8:16:23'
>>> Mp.getDATE()
'9/19/2023'
>>> Mp.getDAY()
'Tuesday'

For numeric values, use the getDATETIME function and parse the values of interest from the returned tuple:

>>> Mp.getDATETIME()
(2023, 9, 19, 1, 8, 19, 5, 0)

microSD Memory

The best way to explain the microSD card functions is by example:

To use the microSD card, two modules have to be imported:
from MICROpi import sd
import os

Then we create a virtual file system around the sd card: vfs = os.VfsFat(sd)

And finally, we mount our sd card: os.mount(vfs, "/sd")

Now, we can open a file on the sd card for writing: file=open("/sd/sdtest.csv", "w")

First we write a header: file.write("Time, Date, Temperature\r\n")

Next, we write a line of text to the file every second: file.write(Mp.getTIME()+', '+Mp.getDATE()+', '+str(Mp.getTEMPF())+"\r\n")

We write the time (a string), append a comma and space, the date (another string), append another comma and space, the temperature after converting it to a string, and finally the carriage return/line feed characters. After that we close the file, then reopen it, read all of it, and print it to the Python shell:

with open("/sd/sdtest.csv", "r") as file: 
    data = file.read() 
    print(data)
file.close()

The above produces the following output:

Time, Date, Temperature
21:32:19, 9/20/2023, 80.71249
21:32:20, 9/20/2023, 80.71249
21:32:21, 9/20/2023, 80.71249
21:32:22, 9/20/2023, 80.71249
21:32:23, 9/20/2023, 80.71249
21:32:24, 9/20/2023, 80.71249
21:32:25, 9/20/2023, 80.71249
21:32:26, 9/20/2023, 80.71249
21:32:27, 9/20/2023, 80.71249
21:32:28, 9/20/2023, 80.71249

Note that the microSD card can only accept string data which is fine when you save it in a CSV (Comma Separated Values) format like we did for this demonstration. The advantage of the CSV format is that you can view and edit it with a simple text editor and it is recognized by all spreadsheet programs including Microsoft Excel, Google Sheets, and LibreOffice Calc to name a few.

GPIO

The MICROpi provides a number of GPIO signals via the 2X20 header. These signals are mapped and numbered like those on a Raspberry Pi. The supported ports
are: 5, 6, 8, 12, 13, 14, 15, 16, 17, 19, 20, 21, and 26. The locations of these pins can be seen below:

The GPIO functions include:
configGPIO(port, direction, pullup) - sets up a GPIO port on the 2X20 header. The arguments are:

port is the GPIO port being configured from the list above.
direction is self explanatory and can be either 'in' or 'out'
pullup is an optional argument only valid when direction='in' - this is a Python boolean value of True or False

getGPIO(port) - returns a numeric value of 0 if the port input is low or 1 if the port input is high. This function works on both inputs and outputs.
setGPIO(port) - if the selected port is configured as an output, this function sets the output to 3.3 volts or a logical 1
clrGPIO(port) - if the selected port is configured as an output, this function sets the output to 0 volts or a logical 0
toggleGPIO(port) - if the GPIO output is set to 1, this function will switch it to 0. If the output is set to 0, this function will switch it to 1

The simple code below produces a ten cycle burst of a 1Khz square wave on GPIO port 21 when button 1 is pushed:

First of all notice how Micropython provides a time.sleep_us function. This allows for more precise timing. Next note how the half period argument is 440µsec and not the 500µsec you would expect for the half cycle of 1Khz. This is because the while loop and the functions under it require about 60µsec of overhead. Connecting an oscilloscope to pin 40 of the 2X20 header allows us to observe GPIO21 when button 1 is pressed:

The above shows 10 pulses of a square wave with a 1msec period and a peak amplitude of 3.3V which is what we would expect.

Be aware of the following:

  1. Using 3.3V to drive 5V CMOS inputs usually doesn't work. You will likely need a level translation circuit such as a 74VHCT50.
  2. The GPIO pins that are brought out to the header have no ESD protection so take precautions when touching these pins
  3. While not visible above, a software generated square wave will exhibit some jitter on the MICROpi

System Functions

The MICROpi has a couple useful system functions

getSRQ() - a convenience function that returns the state of the SRQ pin on the 2X20 header (pin 15 GPIO22). Returns False if there is no service request or True if a Pi-Plate has generated an event.
getFREEMEM() - returns a list with the amount of free program memory in KB and RAM in bytes

Controlling Pi-Plates

The primary reason we developed the MICROpi was to provide a low cost and readily available platform for controlling Pi-Plates. Where possible, we tried to make the programming experience identical to using a Raspberry Pi. However, the limited RAM on the RP2040 and the use of Micropython does introduce a few small differences:

Pi-Plate Module Differences

Common

The example below use the DAQC2plate but they apply to all Pi-Plates

Import

When using the Raspberry Pi, the most common Pi-Plate module import statement looks like: import piplates.DAQC2plate as DAQC2.
With Micropython, this has been shortened to: import DAQC2plate as DAQC2.

getID

To reduce required code space, we removed this function from each Pi-Plate Module.

Specific Pi-Plate Differences

With few exceptions, all Pi-Plates behave exactly the same way with the MICROpi as they would when using a Raspberry Pi or our RPIplate controller. The differences are listed in the sections below.

ADCplate

The ADCplate module requires a large amount of memory. And, without modification, it would not load on the MICROpi. To address this, we had to reduce the maximum block size from 8192 values down to 1024. This change will be reflected in the advanced functions of startBLOCK and startSTREAM. For startBLOCK the block size argument has a max value of 1024. For startSTREAM the block size argument has a max value of 512.

POWERplate and POWERplate24

Unfortunately, the MICROpi does not support these two Pi-Plates due to the conflicting I2C addresses of the Real Time Clock chips.

Pi-Plate Examples

DAQC2plate

For this demo, we used a DAQC2plate and connected the DAC1 output to ADC input 0 and DAC2 to ADC input 1. The program looks like:

Before you run the above script inside of Thonny, be sure to enable the Plotter Window - it can be turned on under the View drop down menu. Then after you run the script you'll see the sine and cosine data plotted out like an oscilloscope:

When the above program runs, you should see the yellow microSD Activity LED blink while the file data is written and read.

RELAYplate2

For this demo, we simply plugged a RELAYplate2 onto the MICROpi and ran the program. Button 1 cycles through the relays while button 2 toggles their state. The display is updated to show the currently selected relay and its and its state.

Low Level Functions

Many of the IO commands available for the MICROpi are calling low level Micropython functions that directly interface to the RP2040 microcontroller. If you want to access some of these functions yourself then check out THIS link. The link references the Raspberry Pi PICO but it also applies to the MICROpi. You can do some pretty cool stuff that isn't implemented on the MICROpi such as outputting PWM signals, driving Neopixels, and interfacing with one-wire devices like a DS18B20 temperature sensor.

The table below maps the available pins on the 2X20 header to the pins on the RP2040:

For example, if we want to control a single Neopixel using pin 11 on the header, we could use the following code:

Remember:

  1. the above code references the RP2040 GPIO pins and not the MICROpi
  2. the signals on the header operate from 0 to 3.3V and devices like Neopixels may require a 5V signal. To address this, you may need a level shifter like the 74VHCT50.

Here's another example where we use pin 29 on the header to output a Pulse Width Modulator (PWM) output:

Looking at pin 29 on the header with our oscilloscope, we can confirm the settings we chose above:

Having simple to use PWMs gives you the ability to do things like set the brightness of an LED, control the speed of a DC motor, create a simple digital to analog controller, or control the position of a servo motor.

Random Programming Notes

There is no specific category for these topics so we placed them here:

  1. For convenience, we've included a lightweight statistics module. Simply include import statistics as STAT at the top of your script to access to these functions. Go HERE to read about the functions available and how to use them.
  2. Manipulating files in Thonny is not obvious or easy. THIS YouTube Video shows you how to do it.
  3. If you want to launch a script automatically when your MICROpi powers up, simply rename it main.py.
  4. It's a good idea to back up your code to the connected PC as you develop you programs on the MICROpi.

Restoring the OS and Python Modules

You may need to restore the files on your MICROpi if they are somehow corrupted or if you just want to clean everything off and start over. To do this requires the following steps:

  1. Connect the cable included with the MICROpython between the microUSB connector and your PC.
  2. Download the ZIP file containing the custom Micropython image along with all of the Python modules by clicking HERE or by typing https://pi-plates.com/downloads/MICROpi_IMAGE.zip into your browser window and pressing <ENTER>
  3. Go to your downloads folder and locate the MICROpi_IMAGE.zip file.
  4. Unzip it to a location that will be easy to find later (we used a folder called TEMP)
  5. Disconnect the USB cable from the MICROpi
  6. Place the jumper across the two pins of the Boot Select Header
  7. Reconnect the USB cable to the MICROpi
  8. Your computer should now see a new disk drive. Open this drive so that files are visible. You should see something like:
  9. Now, open a another file explorer window and locate the files you unzipped in step 4
  10. Locate and drag the file labeled firmware.uf2 to the disk drive that we opened in step 8.
  11. Once the above is complete, the MICROpi folder will close.
  12. Unplug the USB cable
  13. Move the jumper off of the Boot Select Header
  14. Plug the USB cable in again.
  15. Open Thonny and connect to your MICROpi
  16. In the window where your PC files are located, navigate to the folder where the downloaded files are
  17. Locate the folder labeled lib
  18. Right click it and select "Upload to /"
  19. Thonny will then move all of the Python modules onto your MICROpi.
  20. When completed, the expanded file directory should look something like: