The following post describes how to use the DVID screen to write text on it
or to draw pictures on it.
Arduino IDE and libraries
IDE
First things first, we will need the Arduino IDE installed.
When this is done we will need to select the proper programmer in
Tools > Programmer
. Since we use a USBAsp to program the Atmega328p, we
select USBAsp.
Libraries
Now we will need to install the Adafruit libraries.
To do so, we navigate in Tools > Manage libraries.
Then we search for adafruit SSD1306 and install Adafruit SSD1306.
We then search adafruit GFX and install Adafruit GFX Library.
We now have everything needed to start playing with the screen.
Example sketch
Adafruit provides examples of how to use their library.
We have the choice between four scripts :
- ssd1306_128x32_i2c
- ssd1306_128x32_spi
- ssd1306_128x64_i2c
- ssd1306_128x64_spi
The OLED screen used by DVID has the following characteristics :
- Resolution: 128*64
- Control chip: SSH1106
- Display area: 29.42 x 14.7mm
- Driving voltage: 3.3-5V
- Operating temperature: -40 ℃ to 70 ℃
- Interface type: IIC/I2C interface
According to our screen characteristics, we use the script ssd1306_128x64_i2c
.
We copy it in our arduino IDE, and start a compilation (Sketch > Verify/Compile).
Then we upload the sketch to the board with Sketch > Upload using programmer.
And … tada ! Nothing happens.
Why is that ?
I2C address
After some research we find that the problem lies in this line :
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
This bit of code leads us to believe that the parameter 0x3D
is linked to
the resolution of the screen, but it is not. Actually if we replace 0x3D
by 0x3C
as suggested in the blog post linked above, our example will work
perfectly (in my case, at least).
If we look at the source code of the Adafruit library we see that the prototype
for the begin
function is :
boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
boolean periphBegin)
The documentation specifies that
@param addr
I2C address of corresponding SSD1306 display (or pass 0 to use
default of 0x3C for 128x32 display, 0x3D for all others).
SPI displays (hardware or software) do not use addresses, but
this argument is still required (pass 0 or any value really,
it will simply be ignored). Default if unspecified is 0.
So 0x3D
is supposed to be the I2C address of the SSD1306
display.
The issue is the 0x3D
does not seem to be the address of our display.
So how do we find the I2C ? Some quick DDG
search gives us the tool
I2cScanner.
So we just have to copy the script into our Arduino IDE and upload it with the
USBAsp programmer.
Then we use a serial connection to connect to the board and we will get the
information we are looking for :
cu -l /dev/ttyUSB0 -s 9600
Connected.
Scanning...
I2C device found at address 0x3C !
done
Now if we replace the 0x3D
address by the one displayed we will have a working
demo.
About I2C
We’ve been talking about I2C but what is it exactly ?
The Inter-integrated Circuit (I2C) Protocol is a protocol intended to allow
multiple “slave” digital integrated circuits (“chips”) to communicate with one
or more “master” chips. Like the Serial Peripheral Interface (SPI), it is only
intended for short distance communications within a single device.
Like Asynchronous Serial Interfaces (such as RS-232 or UARTs), it only requires
two signal wires to exchange information.
A full introduction can be found on [sparkfun.com](https://learn.sparkfun.com/tutorials/i2c/all).
## Drawing a bitmap
Now that we've seen how to make the example sketch work, let's do one of our
own.
In this sketch we will attempt to draw a logo from a bitmap.
First we create a logo in Gimp. To do this we create a new project for
a `128x64` pixels image and we do some pixel art with a hardbrush pencil with
a size of 1 pixel.
Once this is done we export the logo as a `*.xbm` file.
We then rename the file as `*.c` and open it in an editor.
We retrieve the array and paste it in our sketch.
We just have to [modify the type](https://github.com/adafruit/Adafruit-GFX-Library/pull/31) to `static const uint8_t PROGMEM` then we can use it in our code.
To use it we just have to call `drawXBitmap` and give it our bitmap to display
it.
~~~c
#include
#include
#include
#include
#include <Fonts/FreeSans9pt7b.h>
#define DVID_logo_width 128
#define DVID_logo_height 64
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
static const uint8_t PROGMEM DVID_logo_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1c, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x01, 0x80, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf2, 0x1f,
0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x12, 0x10, 0x00, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x12, 0xf0, 0xff, 0x17, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x12, 0x00,
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0xff, 0x3f, 0x00,
0xf8, 0x00, 0x00, 0x3e, 0x78, 0x80, 0xff, 0x0f, 0x00, 0xc0, 0x7f, 0x04,
0x00, 0xff, 0xff, 0x00, 0xf8, 0x00, 0x00, 0x3e, 0x78, 0x80, 0xff, 0x3f,
0x00, 0x40, 0x40, 0x04, 0x00, 0xff, 0xff, 0x03, 0xf8, 0x01, 0x00, 0x3f,
0x78, 0x80, 0xff, 0xff, 0x00, 0x40, 0x40, 0x04, 0x00, 0xff, 0xff, 0x07,
0xf8, 0x01, 0x00, 0x1f, 0x78, 0x80, 0x07, 0xf8, 0x01, 0x40, 0x40, 0x04,
0x00, 0x0f, 0xf0, 0x0f, 0xf0, 0x01, 0x00, 0x1f, 0x78, 0x80, 0x07, 0xe0,
0x03, 0x40, 0x40, 0x04, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x03, 0x80, 0x0f,
0x78, 0x80, 0x07, 0xc0, 0x07, 0x40, 0x40, 0x04, 0x00, 0x0f, 0x80, 0x1f,
0xe0, 0x03, 0x80, 0x0f, 0x78, 0x80, 0x07, 0x80, 0x07, 0x40, 0x40, 0x04,
0x00, 0x0f, 0x00, 0x3f, 0xe0, 0x03, 0x80, 0x0f, 0x78, 0x80, 0x07, 0x00,
0x0f, 0x40, 0x40, 0x04, 0x00, 0x0f, 0x00, 0x3e, 0xe0, 0x07, 0xc0, 0x07,
0x78, 0x80, 0x07, 0x00, 0x0e, 0x40, 0xe0, 0x04, 0x00, 0x0f, 0x00, 0x3e,
0xc0, 0x07, 0xc0, 0x07, 0x78, 0x80, 0x07, 0x00, 0x1e, 0x40, 0xa0, 0x04,
0x00, 0x0f, 0x00, 0x7c, 0xc0, 0x07, 0xc0, 0x07, 0x78, 0x80, 0x07, 0x00,
0x1c, 0x40, 0xe0, 0x04, 0x00, 0x0f, 0x00, 0x7c, 0xc0, 0x0f, 0xe0, 0x03,
0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x7c,
0x80, 0x0f, 0xe0, 0x03, 0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x00, 0x04,
0x00, 0x0f, 0x00, 0x7c, 0x80, 0x0f, 0xe0, 0x01, 0x78, 0x80, 0x07, 0x00,
0x1c, 0x40, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x7c, 0x80, 0x1f, 0xf0, 0x01,
0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x7c,
0x00, 0x1f, 0xf0, 0x01, 0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x00, 0x04,
0x00, 0x0f, 0x00, 0x7c, 0x00, 0x1f, 0xf0, 0x00, 0x78, 0x80, 0x07, 0x00,
0x1c, 0x40, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x7c, 0x00, 0x3e, 0xf8, 0x00,
0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x7c,
0x00, 0x3e, 0xf8, 0x00, 0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x38, 0x04,
0x00, 0x0f, 0x00, 0x7c, 0x00, 0x3e, 0x78, 0x00, 0x78, 0x80, 0x07, 0x00,
0x1c, 0x40, 0x2e, 0x0e, 0x00, 0x0f, 0x00, 0x7c, 0x00, 0x7c, 0x7c, 0x00,
0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x3a, 0x0a, 0x00, 0x0f, 0x00, 0x7c,
0x00, 0x7c, 0x7c, 0x00, 0x78, 0x80, 0x07, 0x00, 0x1c, 0x40, 0x02, 0x0e,
0x00, 0x0f, 0x00, 0x7e, 0x00, 0x7c, 0x3c, 0x00, 0x78, 0x80, 0x07, 0x00,
0x1c, 0x40, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0xf8, 0x3e, 0x00,
0x78, 0x80, 0x07, 0x00, 0x1e, 0x40, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x3f,
0x00, 0xf8, 0x1f, 0x00, 0x78, 0x80, 0x07, 0x00, 0x0e, 0x40, 0x02, 0x00,
0x00, 0x0f, 0x80, 0x1f, 0x00, 0xf0, 0x1f, 0x00, 0x78, 0x80, 0x07, 0x80,
0x0f, 0x40, 0x02, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0x00, 0xf0, 0x1f, 0x00,
0x78, 0x80, 0x07, 0x80, 0x03, 0x40, 0x02, 0x00, 0x00, 0x0f, 0xf0, 0x0f,
0x00, 0xf0, 0x0f, 0x00, 0x78, 0x80, 0x07, 0xe0, 0x03, 0x40, 0xe2, 0x00,
0x00, 0xff, 0xff, 0x07, 0x00, 0xe0, 0x0f, 0x00, 0x78, 0x80, 0x07, 0xf8,
0x00, 0x40, 0xa2, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xe0, 0x0f, 0x00,
0x78, 0x80, 0xff, 0xff, 0x00, 0x40, 0xe2, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0xc0, 0x07, 0x00, 0x78, 0x80, 0xff, 0x3f, 0x00, 0x40, 0x42, 0x00,
0x00, 0xff, 0x3f, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x78, 0x80, 0xff, 0x0f,
0x00, 0x40, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x40, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
void setup()
{
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.drawXBitmap(0, 0, DVID_logo_bits, DVID_logo_width, DVID_logo_height, 1);
display.display();
}
void loop() {}
~~~
And it works !
## Adding some animation
Now how about we add some animation to our logo ?
https://fccid.io/2AQ5YJDY-18/User-Manual/User-manual-4032434.pdf