Skip to content

TinyScreen TinyShield

Do you need an amazingly small and colorful screen in your next project? I think you do.

In this tutorial, we will be setting up the TinyScreen TinyShield and uploading sample code for testing.

Learn more about the TinyDuino Platform


Description

Be sure to check out the TinyScreen+, an updated version that puts the processor, USB, battery charging and TinyScreen into a single board!

Originally Launched on Kickstarter!

TinyScreen is a beautiful color OLED display for your TinyDuino system. Create video games, a video player, or your own smartwatch using this Tiny OLED screen! The screen is 0.96" diagonal with a resolution of 96x64 RGB pixels, each with 16-bit color. Since this is an OLED, there is no backlight needed and the screen is very bright with excellent colors. Four buttons are located along the side of the screen to allow for user input - like for playing games or creating menus for your projects (like is done on the TinyScreen Smartwatch project). The screen has a built-in IO expander over I2C for control signals and button control, which eliminates the need to use extra pins on the TinyDuino for this.

The screen uses an SSD1331 driver for the OLED display. Based on this driver, we have written a highly optimized and easy to use library which supports both the OLED screen and the buttons on the board. This optimization even allows for 20FPS+ video playback from a microSD when using the TinyDuino. It's also very easy to create your own projects to display text and graphics or create your own tiny games.

To see what other TinyShields are compatible with this TinyShield, see the TinyShield Compatibility Matrix

Technical Details TinyScreen Specs
  • 96x64 OLED display, 16-bit color depth
  • 0.96" (24.4mm) viewable area
  • Total Size: 1.02" x 0.98" (25.8mm x 25.0mm)
  • SSD1331 display controller
  • Software controllable backlight (OLED brightness)
  • Power down mode
  • Four push buttons along the sides (connected to IO pins)
TinyDuino Power Requirements
  • Voltage: 3.0V - 5.5V
  • Current:  20 - 45mA (depending on brightness), due to the current requirements, this board cannot be run using the TinyDuino coin cell option
Pins Used
    SPI and I2C Interface used:
    • **A5/SCL** - I2C Serial Clock line
    • **A4/SDA** - I2C Serial Data line
    • **11 - SCLK: **This signal is the serial SPI clock out of the TinyDuino and into the TinyScreen.
    • **13 - MOSI:** This signal is the serial SPI data out of the TinyDuino and into the TinyScreen.
    • Note: SPI Chip select and button inputs are handled by the on-board I2C GPIO expander.
    Dimensions
    • Dimensions: 25.8mm x 25mm (1.01 inches x .984 inches)
    • Max Height (screen surface to bottom of TinyShield connector): 4.40mm (0.173inches)
    • Weight: 3.2 grams (.113 ounces)

Notes

  • The TinyScreen library can be downloaded through the Arduino IDE menu at Sketch->Include Library->Manage Libraries... "TinyScreen" 
  • TinyScreen Revision 5 boards can shut down the OLED boost converter for better power-down consumption, supported by our latest software library.
  • TinyScreen is also available with an alternative device address, which allows two TinyScreens to be used on the same TinyDuino stack when used with a Ribbon Cable Extender or with a TinyScreen+.

Materials

TinyZero and TinyScreen TinyShield

Hardware

Software


Hardware Assembly

Include pictures and detailed explanation on assembly

An assembled stack of a TinyZero and TinyScreen TinyShield.


Software setup

First, open the Arduino IDE. If you don't have it installed or are unfamiliar with how to upload the code, check out the TinyDuino Setup Tutorial or TinyZero Setup Tutorial depending on which processor you're using.

You will also need to install the TinyScreen library for this tutorial.


Upload Program

Code
/*
  TinyCircuits TinyScreen/TinyScreen+ Basic Example

  This example shows the basic functionality of the TinyScreen library,
  including drawing, writing bitmaps, and printing text

  Written 26 January 2016
  by Ben Rose
  Written 26 January 2016
  By Ben Rose
  Modified 20 May 2019
  By Hunter Hykes

  https://TinyCircuits.com
*/

#include <Wire.h>
#include <SPI.h>
#include <TinyScreen.h>

//Library must be passed the board type
//TinyScreenDefault for TinyScreen shields
//TinyScreenAlternate for alternate address TinyScreen shields
//TinyScreenPlus for TinyScreen+
TinyScreen display = TinyScreen(TinyScreenDefault);

//This is an example 17x12 pixel bitmap using TS library color definitions
unsigned char flappyBirdBitmap[204]={
  TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Blue,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_White,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_White,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Black,TS_8b_Yellow,TS_8b_White,TS_8b_White,TS_8b_White,TS_8b_Yellow,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Blue,
  TS_8b_Blue,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Black,
  TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_Red,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,
  TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Red,TS_8b_Black,TS_8b_Blue,
  TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_Black,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Yellow,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,
  TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Black,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue,TS_8b_Blue
};

void setup(void) {
  Wire.begin();//initialize I2C before we can initialize TinyScreen- not needed for TinyScreen+
  display.begin();
  //setBrightness(brightness);//sets main current level, valid levels are 0-15
  display.setBrightness(10);
}

void loop() {
  hardwareDrawCommands();
  drawPixels();
  drawBitmap();
  //setFlip(boolean);//done in hardware on the SSD1331
  display.setFlip(true);
  delay(1000);
  display.setFlip(false);
  delay(1000);
  writeText();
  delay(1000);
  readInput();
}

void hardwareDrawCommands(){
  //Accelerated drawing commands are executed by the display controller
  //clearScreen();//clears entire display- the same as clearWindow(0,0,96,64)
  display.clearScreen();
  //drawRect(x stary, y start, width, height, fill, 8bitcolor);//sets specified OLED controller memory to an 8 bit color, fill is a boolean- TSRectangleFilled or TSRectangleNoFill
  display.drawRect(10,10,76,44,TSRectangleFilled,TS_8b_Red);
  //drawRect(x stary, y start, width, height, fill, red, green, blue);//like above, but uses 6 bit color values. Red and blue ignore the LSB.
  display.drawRect(15,15,66,34,TSRectangleFilled,20,30,60);
  //clearWindow(x start, y start, width, height);//clears specified OLED controller memory
  display.clearWindow(20,20,56,24);
  //drawLine(x1, y1, x2, y2, 8bitcolor);//draw a line from (x1,y1) to (x2,y2) with an 8 bit color
  display.drawLine(0,0,95,63,TS_8b_Green);
  //drawLine(x1, y1, x2, y2, red, green, blue);//like above, but uses 6 bit color values. Red and blue ignore the LSB.
  display.drawLine(0,63,95,0,0,63,0);
  delay(1000);
  //use 16 bit version of drawLine to fade a rectangle from blue to green:
  for(int i=0;i<64;i++){
    display.drawLine(0,i,95,i,0,i,63-i);
  }
  delay(1000);
}

void drawPixels(){
  //writing pixels one by one is slow, but neccessary for drawing shapes other than lines and rectangles
  //we'll implement a simple circle drawing algorithm from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
  drawCircle(40,30,30,TS_8b_Red);
  drawCircle(45,30,25,TS_8b_Yellow);
  drawCircle(50,30,20,TS_8b_Blue);
  drawCircle(55,30,15,TS_8b_Brown);
  drawCircle(60,30,10,TS_8b_Green);
  drawCircle(65,30,5,TS_8b_Black);
  delay(1000);
}

void drawCircle(int x0, int y0, int radius, uint8_t color)
{
  int x = radius;
  int y = 0;
  int radiusError = 1-x;

  while(x >= y)
  {
    //drawPixel(x,y,color);//set pixel (x,y) to specified color. This is slow because we need to send commands setting the x and y, then send the pixel data.
    display.drawPixel(x + x0, y + y0, color);
    display.drawPixel(y + x0, x + y0, color);
    display.drawPixel(-x + x0, y + y0, color);
    display.drawPixel(-y + x0, x + y0, color);
    display.drawPixel(-x + x0, -y + y0, color);
    display.drawPixel(-y + x0, -x + y0, color);
    display.drawPixel(x + x0, -y + y0, color);
    display.drawPixel(y + x0, -x + y0, color);
    y++;
    if (radiusError<0)
    {
      radiusError += 2 * y + 1;
    }
    else
    {
      x--;
      radiusError += 2 * (y - x) + 1;
    }
  }
}

void drawBitmap(){
  //set a background that matches
  display.drawRect(0,0,96,64,TSRectangleFilled,TS_8b_Blue);
  //let's set up for a bitmap at (40,30) that is 17 pixels wide and 12 pixels tall:
  //setX(x start, x end);//set OLED RAM to x start, wrap around at x end
  display.setX(40,40+17-1);
  //setY(y start, y end);//set OLED RAM to y start, wrap around at y end
  display.setY(30,30+12-1);
  //now start a data transfer
  display.startData();
  //writeBuffer(buffer,count);//optimized write of a large buffer of 8 bit data.
  display.writeBuffer(flappyBirdBitmap,17*12);
  display.endTransfer();
  delay(1000);

}

void writeText(){
  display.clearScreen();
  //setFont sets a font info header from font.h
  //information for generating new fonts is included in font.h
  display.setFont(thinPixel7_10ptFontInfo);
  //getPrintWidth(character array);//get the pixel print width of a string
  int width=display.getPrintWidth("Example Text!");
  //setCursor(x,y);//set text cursor position to (x,y)- in this example, the example string is centered
  display.setCursor(48-(width/2),10);
  //fontColor(text color, background color);//sets text and background color
  display.fontColor(TS_8b_Green,TS_8b_Black);
  display.print("Example Text!");
  display.setCursor(15,25);
  display.fontColor(TS_8b_Blue,TS_8b_Black);
  display.print("More example Text!");
  display.setCursor(3,40);
  display.fontColor(TS_8b_Red,TS_8b_Black);
  display.print("(Does not wrap)");
  delay(1000);
}

void readInput() {
  display.fontColor(TS_8b_White,TS_8b_Black);
  display.clearScreen();
  display.setCursor(48 - (display.getPrintWidth("Press a Button!") / 2), 32 - (display.getFontHeight() / 2));
  display.print("Press a Button!");
  unsigned long startTime = millis();
  while (millis() - startTime < 3000)buttonLoop();
  display.clearScreen();
  display.setFlip(true);
  display.setCursor(48 - (display.getPrintWidth("Press a Button!") / 2), 32 - (display.getFontHeight() / 2));
  display.print("Press a Button!");
  startTime = millis();
  while (millis() - startTime < 3000)buttonLoop();
  display.clearScreen();
  display.setFlip(false);
}

void buttonLoop() {
  display.setCursor(0, 0);
  //getButtons() function can be used to test if any button is pressed, or used like:
  //getButtons(TSButtonUpperLeft) to test a particular button, or even like:
  //getButtons(TSButtonUpperLeft|TSButtonUpperRight) to test multiple buttons
  //results are flipped as you would expect when setFlip(true)
  if (display.getButtons(TSButtonUpperLeft)) {
    display.println("Pressed!");
  } else {
    display.println("          ");
  }
  display.setCursor(0, 54);
  if (display.getButtons(TSButtonLowerLeft)) {
    display.println("Pressed!");
  } else {
    display.println("          ");
  }
  display.setCursor(95 - display.getPrintWidth("Pressed!"), 0);
  if (display.getButtons(TSButtonUpperRight)) {
    display.println("Pressed!");
  } else {
    display.println("          ");
  }
  display.setCursor(95 - display.getPrintWidth("Pressed!"), 54);
  if (display.getButtons(TSButtonLowerRight)) {
    display.println("Pressed!");
  } else {
    display.println("          ");
  }
}

This program doesn't do a whole bunch, but it demonstrates the main functionalities of the board such as drawing shapes, displaying sprites, flipping the screen, and receiving button input.

There are many, many different things that can be done with the TinyScreen. If you're interested in making games for the TinyArcade, be sure to check out the How to Develop a Game for the Tiny Arcade Tutorial.


Downloads


Contact Us

If you have any questions or feedback, feel free to email us or make a post on our forum. Show us what you make by tagging @TinyCircuits on Instagram, Twitter, or Facebook so we can feature it.

Thanks for making with us!