Week 9: Output Devices

"What are the prices of dots per inch these days?" -Leo

This week we were tasked with adding an output device to a microcontroller board we've designed, and programming it to do something. I wanted to get a screen to work. Sounds easy enough, right?

I really liked the OLED display shown in class, it gives off the retro 16-bit feel I want for my final project display. I found an OLED screen at our Harvard fablab <3! Next up was to connect it to my adapted SAMD21 microcontroller board.

Here is an image of my microcontroller board... I want you all to wag your finger at it. Shame on you, microcontroller board.

All I had to do was connect the screen's pins to my board's headers. The OLED screen has only 4 pins: GND, VCC, SCL, SDA. Here are their clarifications for pinning:


GND: ground (obviously)
VCC: Output power supply (3.3v)
SCL (Serial Clock): CLK

SDA (Serial Data): Data

As I was figuring out where to connect the pins to my board, I realized that the output power supply pin on the samd21 (pin29) did not lead to a header port in my design. Instead the pin lead to a capacitor. *I thought* this meant that I could not breakout to the screen because it would have no power source. I then emailed Quentin, who replied and told me to attach it to the third pin from the left. Which is the VDD pin on the samd21. I tried that and still no dice.
Here's how I got around that ->

Proof of concept

At this point I realized something was faulty with my microcontroller board, which I could not fix in that moment. I had to put a pin in it (pun unintended) and so I grabbed an arduino board from the cabinet and got to pinning.

Connecting the OLED screen to the Arduino board was super easy and self-explanatory. This sparkfun redboard has labels for power voltage, SCL, SDA, and GND, of course. I pinned it in 5 seconds.

Update: I got my samd21 dev board to work! VCC is pin 9 on SAMD21

After uploading a tweaking code for scrolling text (changed SerialUSB.begin to just Serial.begin) from one of Quentin's students linked here I got the screen to do some fun stuff.

I also wanted to display an image of myself to elevate my ego motivated serotonin high. In order to do that I found code online that displays a bitmap on the .96 OLED screen. The image I'm using has to be 128x64 px. So I edited a photo of myself in photoshop, added black and white threshhold and converted the image to code using this online tool. I then copied the code and pasted it in arduino. Here is the code which displays a pic of me:

#include 
#include 
#include 
#include 

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LOGO_HEIGHT   64
#define LOGO_WIDTH    128

//image bitmap data
const unsigned char logo_bmp [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7c, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x08, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x06, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0e, 0x00, 0x03, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x08, 0x3f, 0xf8, 0x03, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x10, 0xff, 0xfc, 0x01, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x90, 0x61, 0xff, 0xfe, 0x01, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x43, 0xff, 0xfe, 0x05, 0x97, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0x02, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0x03, 0xff, 0xff, 0x02, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x87, 0xff, 0xff, 0x02, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x0f, 0xff, 0xff, 0x80, 0x10, 0xbf, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfe, 0xc0, 0x0f, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfe, 0x80, 0x0f, 0xff, 0xfc, 0x00, 0x01, 0xef, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x0f, 0xff, 0xf8, 0x00, 0x00, 0xf7, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0x00, 0xf0, 0x70, 0x04, 0x3b, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf9, 0x00, 0x1e, 0x00, 0xf0, 0x00, 0x84, 0x3f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf9, 0x00, 0x1c, 0xf7, 0xf0, 0x00, 0x82, 0x3f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1d, 0xc0, 0xf0, 0x40, 0x02, 0x3f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0x00, 0x70, 0x00, 0x06, 0x3b, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1e, 0x0c, 0x78, 0x00, 0x00, 0x3b, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1e, 0x00, 0xf9, 0x1c, 0x00, 0x36, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfd, 0x00, 0x1f, 0x21, 0xff, 0xfc, 0x00, 0x17, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf8, 0x04, 0x1f, 0xff, 0xff, 0xfe, 0x00, 0x57, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x82, 0x1f, 0xff, 0xff, 0xfe, 0x03, 0xc7, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf8, 0x02, 0x1f, 0xff, 0xfe, 0xfe, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfb, 0x02, 0x4f, 0xff, 0xff, 0x7c, 0x08, 0xcf, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xcf, 0xff, 0xfc, 0x38, 0x01, 0x4f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xee, 0x03, 0xef, 0xfd, 0xf8, 0xc0, 0x00, 0xe7, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xe4, 0x81, 0xa7, 0xfb, 0x91, 0xc0, 0x04, 0x2f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xf7, 0xf3, 0xf7, 0x88, 0x04, 0x7f, 0xbf, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x77, 0xf7, 0xfc, 0x18, 0x01, 0x7f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfa, 0x20, 0x67, 0xef, 0x00, 0x30, 0x00, 0x27, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf7, 0x40, 0x07, 0xf0, 0x02, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf7, 0x40, 0x03, 0xfe, 0x3c, 0x00, 0x02, 0xfb, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xee, 0x00, 0x03, 0xff, 0x80, 0x60, 0x0d, 0xfb, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xde, 0x00, 0x81, 0xff, 0xf3, 0xe0, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xdf, 0x40, 0x00, 0xff, 0xff, 0xc0, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xe5, 0x40, 0x00, 0x7f, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf3, 0x20, 0x00, 0x1f, 0xff, 0x80, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x07, 0xff, 0x82, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xe7, 0x00, 0x00, 0xc1, 0xfe, 0x06, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0xe0, 0x30, 0x06, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0xfc, 0x00, 0x02, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xbd, 0xc0, 0x00, 0x7f, 0xec, 0x03, 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x3f, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0xfc, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xef, 0xc0, 0x10, 0x1f, 0xfe, 0x03, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xef, 0xf0, 0x00, 0x1f, 0xfc, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfb, 0xf8, 0x00, 0x1f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x48, 0xf0, 0x0f, 0xc0, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xfd, 0xaf, 0xfc, 0x17, 0xc3, 0x8b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x0f, 0x08, 0xc1, 0x83, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x80, 0x61, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xc0, 0x01, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0x01, 0x93, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xc0, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  testdrawbitmap();    // Draw the required image
}

void loop() {
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

BYE!