Raspberry Pi Pico Tips and Tricks

Saturday, 19 November 2022

Attaching an OLED Screen to a Raspberry Pi Pico

 

Using an OLED Display attached to a Pico

This project will use an attached OLED display unit to present information from our Raspberry Pi Pico.

I've written this short explanation as part of the much larger book 'Raspberry Pi Pico Tips and Tricks'. You can download it for free from here.

The OLED Display

The display that we’ll use in this example is based on the SSD1306 driver chip, which acts as a bridge between the display matrix and the Pico. The matrix can come in a variety of resolutions (128x64, 128x32, 72x40, 64x48) and colours (white, yellow, blue). The display itself uses an organic light-emitting diode (OLED) technology that allows it to be bright, fairly detailed and to have a wide viewing angle. It also doesn’t hurt that the device is also very reasonably priced.

The specifications of the unit used here is 0.96 inches on the diagonal, has a resolution of 128x64 and is white on a black background.

The SSD1306 Display

The green tab on the side is simply there to make removal of the protective film on the screen easy.

The SSD1306 micro-chip driver uses an I2C communications protocol and there is a PyPI library available that can be used for basic controls. There are some models that will also include SPI connectivity and these can be identified by having more than the four connecting pins that are shown on the model above. For more information on the unit we can consult the datasheet.

Connecting the Display to the Pico

The connection is fairly simple with only four connecting wires being required. Power, ground, Serial CLock line (SCL) and Serial DAta line (SDA). The following connections are used for this example;

  • Display GND to Ground (pin 38) on the Pico (Black)
  • Display VIN to the 3V3(OUT) (pin 36) on the Pico (Red)
  • Display SCL to I2C1 SCL (pin 32, or GPIO27) on the Pico (Orange)
  • Display SDA to I2C1 SDA (pin 31, or GPIO26) on the Pico (Brown)
OLED Connection

An important point to note when we are connecting our Pico is that because the RP2040 microcontroller has two I2C controllers, we need to ensure that we define which controller we are using in the code. I2C0 = id 0 and I2C1 = id 1. This is set in the following lines in the MicroPython code;

i2c = I2C(1, sda=sda, scl=scl)

In our case, since we are using GPIO26 and GPIO27 for the SDA and SCK connections we are using I2C Controller 1.

Loading the ssd1306 PyPI module

The display is accessed via I2C, but we can abstract the complexities of this via a pre-built MicroPython library. To make use of the library we will use Thonny to find and download it.

  1. With our Pico connected to our desktop computer, open Thonny.
  2. Click on Tools > Manage Packages to access Thonny’s package manager.
  3. Type ‘ssd1306’ in the search bar and click on ‘Search on PyPI’. This will return a few results.
  4. Click on ‘micropython-ssd1306’ (ssd1306 module for MicroPython) and then click on ‘Install’. This will copy the library to our Pico.
ssd1306 module library download

Click on ‘Close’ to return to the main screen.

And that’s it, we’re all set up to use the ‘ssd1306’ library.

Code

The code below is incredibly basic and aimed at providing an example of how easy it it is to get started using the display. There is a great deal more that can be done with the display to add shapes, pictures and movement, but our aim is to get up and running and then from there we can push on to greater things :-).

The code below will print ‘Pico’ five times staggered across the screen.

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

# Create I2C object
sda = Pin(26)
scl = Pin(27)
i2c = I2C(1, scl=scl, sda=sda, freq=400000)

oled = SSD1306_I2C(128, 64, i2c)

oled.text("Pico", 0, 0)
oled.text("Pico", 20, 10)
oled.text("Pico", 40, 20)
oled.text("Pico", 60, 30)
oled.text("Pico", 80, 40)

oled.show()
Pico Pico Pico Pico Pico

While the example above is limited, we can also use some of the code’s functions available for the display to add greater complexity. Feel free to have a play with some of the options below;

oled.poweroff()     # power off the display, pixels persist in memory
oled.poweron()      # power on the display, pixels redrawn
oled.contrast(0)    # dim
oled.contrast(255)  # bright
oled.invert(1)      # display inverted
oled.invert(0)      # display normal
oled.rotate(True)   # rotate 180 degrees
oled.rotate(False)  # rotate 0 degrees
oled.show()         # write the contents of the FrameBuffer to display memory

For greater illustration of what can presented on the display, check out the MicroPython docs page for the ESP8266 which presents further options.

And as a final tribute to the MicroPython instructions, run the following code;

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

# Create I2C object
sda = Pin(26)
scl = Pin(27)
i2c = I2C(1, scl=scl, sda=sda, freq=400000)

oled = SSD1306_I2C(128, 64, i2c)

oled.fill(0)
oled.fill_rect(0, 0, 32, 32, 1)
oled.fill_rect(2, 2, 28, 28, 0)
oled.vline(9, 8, 22, 1)
oled.vline(16, 2, 22, 1)
oled.vline(23, 8, 22, 1)
oled.fill_rect(26, 24, 2, 4, 1)
oled.text('MicroPython', 40, 0, 1)
oled.text('SSD1306', 40, 12, 1)
oled.text('OLED 128x64', 40, 24, 1)

oled.show()

Enjoy!

Don't forget, if you're looking for the book 'Raspberry Pi Pico Tips and Tricks'. You can download it for free (or donate if you wish) from here.

Sunday, 30 October 2022

Connecting an SD Card to a Raspberry Pi Pico

 

Connecting an SD Card to the Raspberry Pi Pico

The Raspberry Pi Pico is a very capable device, but it lacks the ability to store sizeable amounts of data on the board. This is a useful function when using the Pico for tasks such as data logging. To make this function practical we can use an SD card for expanding storage via an adapter.

SD cards are great for storing logging and data from microcontroller projects that can then be read on a computer.

We can use SD cards in Serial Peripheral (SPI) mode which allows us to rely on easy to use SPI peripherals and libraries for communication. SPI mode is perfect if we’re writing short amounts of data to a file (e.g. event logging).

I've written this short explanation as part of the much larger book 'Raspberry Pi Pico Tips and Tricks'. You can download it for free from here.

SD card adapter or adaptor.

First the elephant in the room. Whether you spell it adapter or adaptor, it means the same thing. Let’s not get hung up on the semantics of language usage. As a gesture of improving international relations (or perhaps it’s just a personal weakness) I will spell it both ways, although I tend to lean towards adapter.

My personal SD Card adapter journey

I’ll be the first to admit that I haven’t exactly got a large amount of experience in using SD card adapters, but while going the through the process of testing different adapters and cards, I came across a few inconsistencies. This varied between adapters and card types. With that in mind, stay flexible and be patient. Have a range of cards on hand, and don’t be afraid to try something new like rolling your own adapter made out of a standard adapter and some header pins. Also try to start from a consistent baseline with a freshly formatted SD card, ensuring that it’s formatted using the FAT32 file system. And while we’re here, we can’t do anything fancy like having multiple partitions on our SD card. There can be only one! (Gratuitous Highlander reference)

Choose your weapon

While writing this section I used a few different adapters. From the range below I had consistently good results from the smaller adapter and the ghetto version that I created from a traditional adapter and some header pins. I never god results that I was happy with using the larger circuit board version. This might have been some combination of software, hardware and my own personal incompetence, but there it is.

Various SD Card Adapters

Install the SDCard Library.

The modules for supporting SD card use are not yet (as at 2022-10-31) built into the MicroPython distribution for the Pico, so we can add them simply enough manually (once they are included, if an observant reader notices before I do, could you let me know and I will update this section of the book :-))

To make use of the module we will need to download it from GitHub and then copy it over to our Pico. I found this most easily accomplished by first downloading the file to the main computer and then going File >> Open on Thonny and selecting the appropriate file. From there go File >> Save as… and select the Pico as the location to save the file (making sure to save it with the appropriate name (sdcard.py))

Connect the SD Card Adapter

The Serial Peripheral Interface (SPI) utilises four physical connections. Typically on an adapter they will be labelled as such;

  • SCK: Serial Clock
  • MOSI: Master Out Slave In
  • MISO: Master In Slave Out
  • CS: Chip Select

In turn they will be connected to one of the sets of SPI connections on the Raspberry Pi Pico. In our case we will use controller 0 (the pico has two controllers and four sets of possible connections to the GPIO pins) and GPIO pins 16 - 19

  • SPI0 RX (GPIO16) <-> MISO: Master In Slave Out
  • SPI0 CSN (GPIO17) <-> CS: Chip Select
  • SPI0 SCK (GPIO18) <-> SCK: Serial Clock
  • SPI0 TX (GPIO19) <-> MOSI: Master Out Slave In
SD Card Connection

Of course we also connect up or 3.3V and ground connections.

In a practical sense, connecting up with Dupont connectors is a simple method to test functionality.

SD Card Connection

Code

In a new new document, enter the following code:

import machine
import sdcard
import os

# Set the Chip Select (CS) pin high
cs = machine.Pin(17, machine.Pin.OUT)

# Intialize the SD Card
spi = machine.SPI(0,
                  baudrate=1000000,
                  polarity=0,
                  phase=0,
                  bits=8,
                  firstbit=machine.SPI.MSB,
                  sck=machine.Pin(18),
                  mosi=machine.Pin(19),
                  miso=machine.Pin(16))
sd = sdcard.SDCard(spi, cs)

# Mount filesystem
vfs = os.VfsFat(sd)
os.mount(vfs, "/sd")

# Create a file in write mode and write something
with open("/sd/sdtest.txt", "w") as file:
    file.write("Hello World!\r\n")
    file.write("This is a test\r\n")

# Open the file in read mode and read from it
with open("/sd/sdtest.txt", "r") as file:
    data = file.read()
    print(data)

Make sure you have the SD card inserted into the breakout board and click the Run button. You should see the contents of the file that is created (sdtest.txt) printed out in the shell. We can go one step further and eject the SD card from the adapter and plug it into our desktop machine where we can browse to the file and read it from the computer.

Our code above has the feature of creating the file sdtest.txt when it writes to it. This also means that it will overwrite the file every time it is run. If we want to append information to an already existing file we can use an a instead of a w. Something similar to the below would do the trick placed between the write and read blocks;

# Append information to a file
with open("/sd/sdtest.txt", "a") as file:
    file.write("With even more information!\r\n")

If we were utilising the SD card as a store for a data logging application, we would be appending information.

Bonus Connection!

If you’re keen to DIY you can solder header pins to a more traditional SD to Micro SD card adapter and connect that up to our Pico. I was a little sceptical before trying it out, but it worked like a charm.

With that in mind, here is a connection diagram for when you have mastered your soldering skills.

SD Card Ghetto Connection

Don't forget, if you're looking for the book 'Raspberry Pi Pico Tips and Tricks'. You can download it for free (or donate if you wish) from here.