FaceBot 2.0 — Using 2.42" OLEDs over I2C with MicroPython
Our new generation of STEM teaching robots with big displays are easier to connect and more powerful.
In January 2019, our local CoderDojo club published our first low-cost ($40) robots that drew faces on bright OLED displays. However, those robots were hard to set up and program. This blog will show you how our next generation of Python-powered FaceBot works using just a single Grove connector with one extra reset wire.
Background of the FaceBot 1.0
Our students love robots! They are fantastic at getting students to have fun while they accidentally learn computational thinking. Although hundreds of types of robots are on the market, few are powerful enough and low-cost enough to drive a full 128X64 OLED display. Their older Arduino processors are limited by 2K of RAM, and they can’t keep up with the demands of graphics programming.
Although we did get FaceBot 1.0 working, it had several challenges:
- Limited RAM — The Arduino Nano had only a measly 2K of RAM, which means the graphics frame buffer took up most of the RAM.
- Limited CPU power — Our old Arduinos had just a single-core CPU running at a plodding 16 Mhz.
- Old C Programming — Students were required to learn the historically important but now unpopular C language.
- Slow Compile/Link/Test Cycles — C program had to be compiled and downloaded each time the students wanted to test their code. This works OK for small programs, but as our programs get larger the development cycles slow down.
- Small OLEDs Were Too Hard to Read — The small .96" low-cost ($4) OLEDs were too small to read without getting close up. Display readability is a problem when your robots are on the floor, and you are standing up.
- Bigger OLEDs Were Too Hard To Connect — The lovely 2.42" OLEDs that cost around $18 needed seven wires to hook up using SPI connections. These took up a lot of I/O pins on our microcontrollers.
We learned that our students loved these robots and liked drawing faces on the robots despite these drawbacks. We often intentionally gave them very dull faces and challenged them to draw the faces in new creative ways.
Here is a sample of simple robot face images from a 2021 research paper:
Goals for FaceBot 2.0
With these limitations in mind, we wanted to design our next-generation kid-friendly low-cost FaceBot to have the following characteristics:
- It must be 100% programmed in Python (technical MicroPython for microcontrollers). This is the popular programming language our kids love.
- It should limit the amount of soldering and connections.
- It should have enough RAM to support a frame buffer for a 128X64 monochrome display.
- It should support the lovely OLED displays and minimize the number of wires.
Raspberry Pi Pico and the Cytron Maker Pi RP2040
In January of 2021, we were presently surprised that the Raspberry Pi Foundation announced their RP2040 processor and the Pico board. Not only did it have plenty of RAM (264K), but it could be programmed directly in Python. These processors were also much faster (133 MHz than the old 16 MHz Arduino Nano), giving them plenty of power to do complex drawings on the faces. The dual-core also offered the possibility of dedicating an entire core to keep the display up-to-day without interrupting sensor readings. It was a great fit for our FaceBot 2.0.
A few months later, Cytron launched a RP2040-based robot controller board with motor drivers and power management directly on a board that cost only $9.99. I reviewed this board back in August of 2021. It is fantastic to see such a fully-integrated and feature-rich board for under $10. Anyone spending more than $10 on robot controllers needs to look at this board!
Connecting SPI to the Cytron Boards Grove Connectors
We did connect OLEDs to this board, but there was one big problem—the default connectors for our board from DIYMORE.CC required seven wires! One for GND, one for VCC, and five data wires. That caused us to use three of our Grove connectors to be used up. This was inefficient and limited the number of free connectors we had left in our robots. We were frustrated! So close but yet so far from realizing the vision of our FaceBot 2.0!
Failed Ventures into I2C Conversion
The back of the OLED displays had instructions for converting the boards from the default SPI to using the simpler 4-wire I2C interface. But despite my hours of struggling I could NOT get the SPI interfaces to work with our Raspberry Pi Pico or the Cytron Maker Pi RP2040 boards. I would follow the instructions exactly but every time I did this the basic i2c-scanner would come up empty. I tried tying the CS, DC, and RES signals to various positions — but no luck. I didn’t know if my hardware was bad, my wires were not connected correctly or the I2C Python driver was just not compatible with the board. When I hooked up a logic analyzer to the lines I could see both data and clock signals were going into the display, but I could not get anything to display.
A Little Help from A Friend
Then at the beginning of March, I expressed my frustration to a friend who I will just call WP. WP also had a brother that has some good debugging chops. They ordered similar parts and one day I got an email telling me they finally got it to work! Although they couldn't just use the standard 4-wire Grove connector like our other smaller OLED displays, they could get it to work by adding one extra RESET wire to the display.
The Solution: I2C + 1
The problem with the way we were using the device was that we were not resetting the display driver when the display powered up. This is because most other I2C devices only need four wires: GND, VCC, Data, and Clock. When the devices are powered on they are “smart” in that they reset themselves to a known start just a few milliseconds after power-up. The DIYMORE OLED device requires us to always pull the reset pin high just after power-up and just before the display is used. The MicroPython code to do this is shown below.
Although we could use up another Grove connector to do this reset, there is one other option available to us. That is to just wire the RESET pin to the Servo jumper in the corner of the Maker Pi RP2040 board. A simple female-to-female jumper is all we need! As long as your robot is not using all four servo motors we are good to go!
Details on how to move the resistors on the rear of the board
The one challenge about this project is that moving the jumpers on the rear of the DIYMORE board requires a soldering iron, fine motor skills, and a steady hand. Here is a summary of the changes that we need to make:
There is a video of these steps here provided by the user retrofriends on YouTube:
We have now finally realized our vision of a low-cost and easy-to hookup interface for our FaceBot 2.0.
Closing with Gratitude for Friends
Looking back on this project, I realized that I might have theoretically figured this out myself if I had been more patient and spent the time reading the datasheets for the SSD1309 chip. But perhaps I never would have figured it out! What this taught me is that having a good group of friends in your network with the right skills and experiences to complement your own skills will get you a lot further along in reaching your goals than trying to do everything yourself.
I just want to express my heartfelt thanks and gratitude to both WP and his brother for helping our little CoderDojo club out. I hope everyone else teaching kids how to code can benefit from this work.
More to Explore
You can find more about our Beginning Python, MicroPython, and our new generation of low-cost Robots at the CoderDojoTC microsites. Keep an eye out for our future FaceBot 2.0 lessons by following me on LinkedIn or my Medium blog.