This week we played with screens! I checked out the SSD1306 OLED screen and e-paper screen from the shop, and Tom lent me his ST7789 TFT LCD screen.
I only ended up playing with the OLED and TFT screens and didn't get to the e-paper.
SSD1306 OLED screen
This OLED screen operated via the I2C protocol, and was thankfully quite straightforward to wire up:
SDA
(Serial Data) to Nano's A4SCL
(Serial Clock) to Nano's A5- Power and Ground
I followed both Tom's example Arduino code and cross-referenced it with the PCOMP lab for this screen.
I did have some notes and questions about the code:
!display.begin(...)
starts the display but if anything goes wrong with the startup then presumably returns falsey so that we can deal with the error- How do we know the I2C address for the display?
- I read on some StackOverflow that for I2C devices we should have pull-up resistors for the
SCL
andSDA
pins—is the Adafruit library declaring pin modeINPUT_PULLUP
for us and that's why we don't need to physically wire the resistors?
ST7789 TFT LCD screen
omg the TFT gave me so much more trouble.
It uses SPI communication, and my first issue was that I couldn't quite figure out the wiring. I started with Tom's example code which gave me a starting point:
- Screen SDI <-> microcontroller SPI SDO
- Screen SCK <-> microcontroller SPI SCK
- Screen CS <-> microcontroller SPI CS
- Screen D/C <-> microcontroller digital output pin
- Screen Reset <-> microcontroller TFT_RST output pin
But other than the SCK
(D13) pin I just couldn't find the other corresponding pins on the Nano pinout diagram. I was able to figure it out after much googling, and these were the pages I ended up cross-referencing and finding helpful:
- Tom's display-examples resource, specifically the SPI Connections section
- Adafruit's Breakout Wiring & Test page for their 1.8" TFT Display Breakout and Shield
- Arduino's page explaining their decolonization of terminology: I super appreciated this! I cringed everytime I read MISO, MOSI, and SS.
- An Instructable for Adding CS Pin to ST7789 1.3" IPS LCD: this helped explain to me what the CS pin was for and verified that some TFT screens don't have it
The wiring
SCK
(Serial Clock) to Nano's D13.SDI
(Serial Data In) to Nano's D11 (aka. COPI, Controller Out Peripheral In)RES
(Reset) to whichever pin we specify in the codeD/C
(Data/Command) to whichever pin we specify in the codeCS
(Chip Select) to whichever pin we specify in the code- Helps control which SPI device is getting instructions if we want to hook up multiple of them in a row
- My TFT didn't have this pin, which was one of the reasons why I was so confused for a while (this becomes important later lol)
BLK
(Backlight)- Doesn't need to be wired unless we want programmatic control of the backlight
- Power and Ground
But even after I figured out the wiring, my TFT wouldn't display anything. I knew it wasn't a power issue because I could see that the screen was lit up, I thought perhaps it was a backlight issue but my googling told me that I shouldn't need to wire that pin since the screen defaults to backlight on. I even faithfully followed Adafruit's wiring guide for what seemed to be the exact screen dimensions I had (1.3", 240x240) on both the Nano and Uno, but nothing.
After much searching and banging my head and almost giving up, I started to have a sneaking suspicion that perhaps it was because of the missing CS
pin. And as soon as I had that thought, I noticed this line in Tom's page on TFT examples:
MakerFocus 1.3” LCD Display, no MicroSD, Amazon link - This display does not have a CS pin, so it can’t be used with other SPI devices at the same time. It works with the Adafruit_ST7789 library, but you have to change the
init()
function to include the SPI mode like so:display.init(width, height, SPI_MODE3);
.
So after fixing the code in two places, first to set CS pin to -1 and second to update the SPI Mode for display initialization, IT WOOOOOOOOOORKED!
After I got it working, I started diving into Tom's code that was using an offscreen buffer to make the rendering to screen more performant. I first wondered what it'd look like if I printed directly to the screen, which resulted in unbearable flashing (left video below). So I put the offscreen canvas back in and played around with the text size.
Here's my final (mostly unedited) code for TFT screen
OLED + TFT together
Once I had the TFT going, I knew that I wanted to get the OLED and TFT running at the same time off the same Arduino. I had a minor bug where the OLED screen wasn't displaying once I had ported the TFT code in, but quickly figured out it was because in the porting process I changed the OLED font color to the same light blue as the TFT...which of course wouldn't work since the OLED is monochrome and thus I can only draw black and white.
Once I got the two screens going, I hooked up a Force Sensing Resistor (with this PCOMP lab to remind me the wiring) and VOILÀ:
It was so much work to get here 🥲
Line chart
While struggling with the wiring I came across the Adafruit GFX library and their graphics primitives, and I was like, I got this 😏 I'm gonna draw a line chart of the sensor reading.
Funnily enough drawing the line was the easy part, the hard part was storing the values to draw. To save memory I decided to create an array with the exact size of the number of points on screen, and when I go over that number I wrap back around and overwrite the first numbers in the array. This proved a bit too much for my brain and though I was able to mostly get it, there's a very obvious visual glitch that indicates where the wrap-around happens. I gave up trying to debug it.
Anyways, here's the final wiring: