The Adafruit 128x32 mono OLED FeatherWing consists of a 128x32 monochrome OLED and three user buttons. Stack it on top of a Feather with any microcontroller and then you can send graphics commands to it via I2C by using the Adafruit SSD1306 and GFX libraries. The display is small (~1" x 3/8"), but the text is very readable due to the high contrast of the OLED display.
Adafruit has a nice demo of the graphics commands on GitHub
Button Digital Inputs Vary By Microcontroller Core
Core | Button A | Button B | Button C | LED |
---|---|---|---|---|
ESP8266 | 0 | 16 | 2 | 0 |
ESP32 | 15 | 32 | 14 | 13 |
ARDUINO_STM32F2_FEATHER | PA15 | PC7 | PC5 | PB5 |
TEENSYDUINO | 4 | 3 | 8 | 13 |
ARDUINO_FEATHER52 | 31 | 30 | 27 | 17 |
32u4, M0, M4, and 328p | 9 [1] | 6 | 5 | 13 |
[1] #9 for BUTTON_A is also used for the battery voltage divider, so if you want to use them both, make sure to disable the pullup when you analog read, then turn on the pullup for button reads. See sample code that follows.
The code below is a more complete demonstration of the GFX Library commands to send text to the display, and to read the state of the three buttons on the FeatherWing.
/*
Adafruit 128x32 mono OLED FeatherWing
https://www.adafruit.com/product/2900
28x32 monochrome OLED + three user buttons.
Display area: ~25.8mm / ~1.0"
The OLED I2C address is 0x3C and cannot be changed
https://learn.adafruit.com/adafruit-oled-featherwing?view=all
https://learn.adafruit.com/adafruit-gfx-graphics-library?view=all
http://henrysbench.capnfatz.com/henrys-bench/arduino-adafruit-gfx-library-user-guide/
http://engineeringnotes.blogspot.com/2013/07/using-ssd1306-textgraphics-display.html
This sketch demonstrates writing text to the OLED
using the Adafruit GFX Graphics Library. It is derived
from the Adafruit example at: https://learn.adafruit.com/adafruit-oled-featherwing?view=all
*/
#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
Adafruit_SSD1306 display = Adafruit_SSD1306();
// Configure the buttons, based on the microcontroller core
#if defined(ESP8266)
#define BUTTON_A 0
#define BUTTON_B 16
#define BUTTON_C 2
#define LED 0
#elif defined(ESP32)
#define BUTTON_A 15
#define BUTTON_B 32
#define BUTTON_C 14
#define LED 13
#elif defined(ARDUINO_STM32F2_FEATHER)
#define BUTTON_A PA15
#define BUTTON_B PC7
#define BUTTON_C PC5
#define LED PB5
#elif defined(TEENSYDUINO)
#define BUTTON_A 4
#define BUTTON_B 3
#define BUTTON_C 8
#define LED 13
#elif defined(ARDUINO_FEATHER52)
#define BUTTON_A 31
#define BUTTON_B 30
#define BUTTON_C 27
#define LED 17
#else // 32u4, M0, M4, and 328p
// Note that #9 for BUTTON_A is also used for the battery
// voltage divider, so if you want to use them both, make
// sure to disable the pullup when you analog read, then
// turn on the pullup for button reads.
#define BUTTON_A 9
#define BUTTON_B 6
#define BUTTON_C 5
#define LED 13
#endif
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
// *************************************************************
// 3.7V Lithium polymer battery monitoring
// Note that GPIO #9 is also analog input A7.
// This pin naturally 'sits' at around 2VDC due to the resistor divider
#define VBATPIN A7
// *************************************************************
void setup() {
Serial.begin(9600);
Serial.println("Adafruit 128x32 mono OLED FeatherWing text command demo");
// by default, generate the high voltage from the 3.3v line internally.
// initialize with the I2C addr 0x3C (for the 128x32)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// init done
Serial.println("OLED begun");
// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
// The image buffer on the display hardware is initialized
// with an Adafruit splashscreen. If you execute the command
// display.display(), then the splashscreen will be shown.
// Disable this command if you don't want to display the
// splashscreen.
//display.display();
//delay(1000);
// Clear the display buffer.
display.clearDisplay();
display.display();
// Configure the three buttons on the OLED FeatherWing
pinMode(BUTTON_A, INPUT_PULLUP);
pinMode(BUTTON_B, INPUT_PULLUP);
pinMode(BUTTON_C, INPUT_PULLUP);
delay(10);
// text display tests
//Note that for .setTextSize(1), a character is 6 pixels wide by 8 pixels high.
//For a 128x32 OLED, 128/6 = 12 characters; 32/8 = 4 characters
display.setTextSize(1);
//display.setTextColor(); BLACK,BLUE,RED,GREEN,CYAN,MAGENTA,YELLOW,WHITE
//display.setTextColor(text color, background color);
//Sets the text color and background color the text will print on.
//For monochrome (single-color) displays, colors are always specified as simply 1 (set) or 0 (clear).
display.setTextColor(WHITE);
//display.setCursor(horizontal position, vertical position);
//For .setTextSize(1), rows are: 0, 8, 16, 24
// 21 characters horizontally for .setTextSize(1)
display.setCursor(0,0);
display.print("AF 128x32 mono OLED");
display.setCursor(0,15);
display.print("SSD1306 display");
// Call display.display() to make the prior drawing commands
// display on the OLED. It is slow, so use sparingly.
display.display();
delay(5000);
// Clear the display buffer.
display.clearDisplay();
display.display();
delay(1000);
// .setTextSize(1) demo
display.setCursor(0,0);
display.print("012345678901234567890");
//
display.setCursor(0,8);
display.print("setTextSize(1)");
//
display.setCursor(0,16);
display.print(" 21 characters");
//
display.setCursor(0,24);
display.print("x 4 rows");
display.display();
delay(5000);
// Clear the display buffer.
display.clearDisplay();
display.display();
delay(1000);
// .setTextSize(2) demo
//
// .setTextSize(2) will change the character sizes as follows:
// 2*6 x 2*8 = 12x16 pixels.
// For a 128x32 OLED, 128/12 = 10 chars wide; 32/16 = 2 characters tall
display.setTextSize(2);
display.setCursor(0,0);
display.print("0123456789");
//
display.setCursor(0,16);
display.print("10x2 chars");
display.display();
delay(5000);
display.clearDisplay();
display.display();
delay(1000);
// Mixed text sizes demo
// .setTextSize(2) & .setTextSize(1)
display.setTextSize(2);
display.setCursor(0,0);
display.print("0123456789");
//
display.setCursor(0,16);
display.setTextSize(1);
display.print(".setTextSize(2)");
//
display.setCursor(0,24);
display.setTextSize(1);
display.print("10 chars x 2 rows");
display.display();
delay(9000);
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setCursor(0,0);
display.print("Press btn A, B, or C");
} // setup()
void loop() {
if (digitalRead(BUTTON_A) != HIGH) {
display.clearDisplay();
display.display();
yield();
display.setTextSize(1);
display.setCursor(0,0);
display.print("Button A");
}
if (digitalRead(BUTTON_B) != HIGH) {
display.clearDisplay();
display.display();
yield();
display.setTextSize(1);
display.setCursor(0,8);
display.print("Button B");
}
if (digitalRead(BUTTON_C) != HIGH) {
display.clearDisplay();
display.display();
yield();
display.setTextSize(1);
display.setCursor(0,16);
display.print("Button C");
printLiPoBattV ();
}
delay(10);
// The yield() function allows ESP8266 microcontroller to run a
// number of utility functions in the background, without causing
// the ESP8266 to crash or reset. Include it within any
// while() + digitalRead() and other loops;
yield();
display.display();
} // loop()
void printLiPoBattV () {
// Note that #9 for BUTTON_A is also used for the battery
// voltage divider A7, so if you want to use them both, make
// sure to disable the pullup when you analog read, then
// turn on the pullup for button reads.
// Note that digitialWrite(9, HIGH) is the same as pinMode(9, INPUT_PULLUP)
// Disable pullup on analog pin #9
digitalWrite(9, LOW);
delay(1);
float measuredvbat = analogRead(VBATPIN);
// Enable pullup on analog pin #9 (for future reads of BUTTON_A)
delay(1);
pinMode(9, INPUT_PULLUP);
// NOTE:
// The M0 (ATSAMD21) pullup-selection register is the same as the
// output-selection register. For this reason, you should NOT
// use the following statements to turn on a pin as an input
// with a pullup:
// pinMode(pin, INPUT)
// digitalWrite(pin, HIGH)
// Instead, to this:
// pinMode(pin, INPUT_PULLUP)
//
measuredvbat *= 2; // voltage divided by 2 on board, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, the reference voltage
measuredvbat /= 1024; // convert to voltage
//Serial.print("VBat: " ); Serial.println(measuredvbat);
display.setTextSize(1);
display.setCursor(0,24);
display.print("Batt ");
display.print(measuredvbat);
display.print(" V");
} //printLiPoBattV ()
Do you need help developing or customizing a IoT product for your needs? Send me an email requesting a free one hour phone / web share consultation.
The information presented on this website is for the author's use only. Use of this information by anyone other than the author is offered as guidelines and non-professional advice only. No liability is assumed by the author or this web site.