Xiao ESP32C3 display on SSD1306 128x64 OLED (I2C & SPI) using U8g2 Library
Xiao ESP32C3 (arduino-esp32 framework) exercise to display 128x64 SSD1306 OLED, both
I2C and SPI. Tested on XIAO Expansion board, SSD1315 I2C OLED (SSD1306 compatible)
and SSD1306 SPI OLED.
U8g2 Library is used to drive the OLEDs, make sure it's installed in Arduino IDE.
Connection
Exercise Code:
XiaoESP32C3_Serial_Terminal.ino
Accept user input from Serial Monitor, and display on OLED as a terminal (U8X8LOG).
XiaoESP32C3_u8x8_GraphicsTest_128x64_SSD1306_I2C_and_SPI.ino
Modified from u8x8 example GraphicsTest, tested on both I2C and SPI OLED.
XiaoESP32C3_u8g2_128x64_SSD1306.ino
U8g2lib exercise to draw something on both OLEDs, compare the duration of sendBuffer() function between SPI and I2C.
U8g2 Library is used to drive the OLEDs, make sure it's installed in Arduino IDE.
Connection
for SPI interface:
OLED SPI Xiao ESP32C3
GND GND
VCC 3V3
SCL GPIO8
SDA GPIO10
RST GPIO2
D/C GPIO3
for I2C interface:
OLED I2C Xiao ESP32C3
GND GND
VCC 3V3
SCL GPIO7
SDA GPIO6
XiaoESP32C3_Serial_Terminal.ino
Accept user input from Serial Monitor, and display on OLED as a terminal (U8X8LOG).
/*
* Read from Serial and display on
* XIAO Expansion board I2C SSD1306 OLED (128x64)
* using U8g2 library.
* In this exercise, the OLED act as a terminal (U8X8LOG).
*/
#include <Arduino.h>
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
// U8x8 Contructor
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
// setup the terminal (U8X8LOG) and connect to u8g2 for automatic refresh of the display
// The size (width * height) depends on the display
#define U8LOG_WIDTH 16
#define U8LOG_HEIGHT 8
uint8_t u8log_buffer[U8LOG_WIDTH*U8LOG_HEIGHT];
U8X8LOG u8x8log;
void setup(void)
{
Serial.begin(115200);
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8log.begin(u8x8, U8LOG_WIDTH, U8LOG_HEIGHT, u8log_buffer);
u8x8log.setRedrawMode(1); // 0: Update screen with newline, 1: Update screen for every char
u8x8log.println("- Xiao ESP32C3 -");
u8x8log.println("Read from Serial and display on I2C SSD1306 OLED using U8g2 library.");
Serial.println("\nEnter something and Send");
}
void loop(void) {
while (Serial.available() > 0) {
String term_in = Serial.readString();
Serial.print(term_in);
u8x8log.print(term_in);
}
delay(100);
}
XiaoESP32C3_u8x8_GraphicsTest_128x64_SSD1306_I2C_and_SPI.ino
Modified from u8x8 example GraphicsTest, tested on both I2C and SPI OLED.
/*
* Modified from Exampls > U8g2 > u8x8 > GraphicsTest
* Run on Xiao ESP32C3 to display on 128x64 SSD1306 (I2C/SPI)
*
*/
/*
GraphicsTest.ino
Some graphics/text output for U8x8 API
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <Arduino.h>
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define TFTspi_RST 2
#define TFTspi_DC 3
// U8x8 Contructor
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
//- For SPI SSD1306 -
U8X8_SSD1306_128X64_NONAME_4W_HW_SPI u8x8(/* cs=*/ U8X8_PIN_NONE, /* dc=*/ TFTspi_DC, /* reset=*/ TFTspi_RST);
//- For I2C SSD1306 -
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
/*
This example will probably not work with the SSD1606, because of the
internal buffer swapping
*/
void setup(void)
{
delay(500);
Serial.begin(115200);
delay(500);
//I2C & SPI pins assigment
Serial.println("\n- For I2C SSD1306 -");
Serial.println("I2C pins:");
Serial.printf("\tSDA: GPIO%d\n", SDA);
Serial.printf("\tSCL: GPIO%d\n", SCL);
Serial.println("\n- For SPI SSD1306 -");
Serial.println("SPI pins:");
Serial.printf("\tSS : GPIO%d \t(not used)\n", SS);
Serial.printf("\tMOSI: GPIO%d\n", MOSI);
Serial.printf("\tMISO: GPIO%d \t(not used)\n", MISO);
Serial.printf("\tSCK : GPIO%d\n", SCK);
Serial.printf("\tRST : GPIO%d\n", TFTspi_RST);
Serial.printf("\tD/C : GPIO%d\n", TFTspi_DC);
u8x8.begin();
//u8x8.setFlipMode(1);
}
void pre(void)
{
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
u8x8.clear();
u8x8.inverse();
u8x8.print(" U8x8 Library ");
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.noInverse();
u8x8.setCursor(0,1);
}
void draw_bar(uint8_t c, uint8_t is_inverse)
{
uint8_t r;
u8x8.setInverseFont(is_inverse);
for( r = 0; r < u8x8.getRows(); r++ )
{
u8x8.setCursor(c, r);
u8x8.print(" ");
}
}
void draw_ascii_row(uint8_t r, int start)
{
int a;
uint8_t c;
for( c = 0; c < u8x8.getCols(); c++ )
{
u8x8.setCursor(c,r);
a = start + c;
if ( a <= 255 )
u8x8.write(a);
}
}
void loop(void)
{
int i;
uint8_t c, r, d;
pre();
u8x8.print("github.com/");
u8x8.setCursor(0,2);
u8x8.print("olikraus/u8g2");
delay(2000);
u8x8.setCursor(0,3);
u8x8.print("Tile size:");
u8x8.print((int)u8x8.getCols());
u8x8.print("x");
u8x8.print((int)u8x8.getRows());
delay(2000);
pre();
for( i = 19; i > 0; i-- )
{
u8x8.setCursor(3,2);
u8x8.print(i);
u8x8.print(" ");
delay(150);
}
draw_bar(0, 1);
for( c = 1; c < u8x8.getCols(); c++ )
{
draw_bar(c, 1);
draw_bar(c-1, 0);
delay(50);
}
draw_bar(u8x8.getCols()-1, 0);
pre();
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
for( d = 0; d < 8; d ++ )
{
for( r = 1; r < u8x8.getRows(); r++ )
{
draw_ascii_row(r, (r-1+d)*u8x8.getCols() + 32);
}
delay(400);
}
draw_bar(u8x8.getCols()-1, 1);
for( c = u8x8.getCols()-1; c > 0; c--)
{
draw_bar(c-1, 1);
draw_bar(c, 0);
delay(50);
}
draw_bar(0, 0);
pre();
u8x8.drawString(0, 2, "Small");
u8x8.draw2x2String(0, 5, "Scale Up");
delay(3000);
pre();
u8x8.drawString(0, 2, "Small");
u8x8.setFont(u8x8_font_px437wyse700b_2x2_r);
u8x8.drawString(0, 5, "2x2 Font");
delay(3000);
pre();
u8x8.drawString(0, 1, "3x6 Font");
u8x8.setFont(u8x8_font_inb33_3x6_n);
for(i = 0; i < 100; i++ )
{
u8x8.setCursor(0, 2);
u8x8.print(i); // Arduino Print function
delay(10);
}
for(i = 0; i < 100; i++ )
{
u8x8.drawString(0, 2, u8x8_u16toa(i, 5)); // U8g2 Build-In functions
delay(10);
}
pre();
u8x8.drawString(0, 2, "Weather");
u8x8.setFont(u8x8_font_open_iconic_weather_4x4);
for(c = 0; c < 6; c++ )
{
u8x8.drawGlyph(0, 4, '@'+c);
delay(300);
}
pre();
u8x8.print("print \\n\n");
delay(500);
u8x8.println("println");
delay(500);
u8x8.println("done");
delay(1500);
pre();
u8x8.fillDisplay();
for( r = 0; r < u8x8.getRows(); r++ )
{
u8x8.clearLine(r);
delay(100);
}
delay(1000);
}
XiaoESP32C3_u8g2_128x64_SSD1306.ino
U8g2lib exercise to draw something on both OLEDs, compare the duration of sendBuffer() function between SPI and I2C.
/*
* Run on Xiao ESP32C3 to display on 128x64 SSD1306 (I2C/SPI)
* U8g2lib exercise
* Compare the running duration of sendBuffer() function between SPI and I2C
*
*/
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define TFTspi_RST 2
#define TFTspi_DC 3
// U8g2 Contructor (Frame Buffer)
//- For SPI SSD1306 -
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2_spi(U8G2_R0, /* cs=*/ U8X8_PIN_NONE, /* dc=*/ TFTspi_DC, /* reset=*/ TFTspi_RST);
//- For I2C SSD1306 -
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2_i2c(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
int step_cnt = 0;
int step_x = 2;
int step_y = 1;
int pt0_x = 0;
int pt0_y;
int pt1_x;
int pt1_y;
int pt2_x;
int pt2_y;
int pt3_x;
int pt3_y;
void walkStep(){
if (step_cnt==0){
pt0_x = 0;
pt0_y = 0;
pt1_x = 127;
pt1_y = 0;
pt2_x = 127;
pt2_y = 63;
pt3_x = 0;
pt3_y = 63;
}else{
pt0_x = pt0_x + step_x;
pt1_y = pt1_y + step_y;
pt2_x = pt2_x - step_x;
pt3_y = pt3_y - step_y;
}
step_cnt++;
if(step_cnt == 64){
step_cnt=0;
u8g2_spi.clearBuffer();
u8g2_i2c.clearBuffer();
}
}
void setup(void) {
delay(500);
Serial.begin(115200);
delay(500);
//I2C & SPI pins assigment
Serial.println("\n- For I2C SSD1306 -");
Serial.println("I2C pins:");
Serial.printf("\tSDA: GPIO%d\n", SDA);
Serial.printf("\tSCL: GPIO%d\n", SCL);
Serial.println("\n- For SPI SSD1306 -");
Serial.println("SPI pins:");
Serial.printf("\tSS : GPIO%d \t(not used)\n", SS);
Serial.printf("\tMOSI: GPIO%d\n", MOSI);
Serial.printf("\tMISO: GPIO%d \t(not used)\n", MISO);
Serial.printf("\tSCK : GPIO%d\n", SCK);
Serial.printf("\tRST : GPIO%d\n", TFTspi_RST);
Serial.printf("\tD/C : GPIO%d\n", TFTspi_DC);
u8g2_spi.begin();
u8g2_i2c.begin();
Serial.println("\n- SPI SSD1306 Display -");
Serial.printf("width : %d\n", u8g2_spi.getDisplayWidth());
Serial.printf("height : %d\n", u8g2_spi.getDisplayHeight());
Serial.println("\n- I2C SSD1306 Display -");
Serial.printf("width : %d\n", u8g2_i2c.getDisplayWidth());
Serial.printf("height : %d\n", u8g2_i2c.getDisplayHeight());
Serial.println();
Serial.println("duration of sendBuffer() micros:\tSPI\tI2C");
u8g2_spi.clearBuffer(); // clear the internal memory
u8g2_i2c.clearBuffer();
u8g2_spi.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
u8g2_i2c.setFont(u8g2_font_ncenB08_tr);
u8g2_spi.drawStr(0,10,"Hello World!"); // write something to the internal memory
u8g2_i2c.drawStr(0,10,"Hello World!");
u8g2_spi.sendBuffer();
u8g2_i2c.sendBuffer();
delay(2000);
}
void drawSomething(){
u8g2_spi.drawLine(pt0_x, pt0_y, pt1_x, pt1_y);
u8g2_spi.drawLine(pt1_x, pt1_y, pt2_x, pt2_y);
u8g2_spi.drawLine(pt2_x, pt2_y, pt3_x, pt3_y);
u8g2_spi.drawLine(pt3_x, pt3_y, pt0_x, pt0_y);
u8g2_i2c.drawLine(pt0_x, pt0_y, pt1_x, pt1_y);
u8g2_i2c.drawLine(pt1_x, pt1_y, pt2_x, pt2_y);
u8g2_i2c.drawLine(pt2_x, pt2_y, pt3_x, pt3_y);
u8g2_i2c.drawLine(pt3_x, pt3_y, pt0_x, pt0_y);
}
void loop(void) {
drawSomething();
walkStep();
unsigned long start_time_spi = micros();
u8g2_spi.sendBuffer(); // transfer internal memory to the display
unsigned long end_time_spi = micros();
unsigned long start_time_i2c = micros();
u8g2_i2c.sendBuffer(); // transfer internal memory to the display
unsigned long end_time_i2c = micros();
Serial.printf("\t\t\t\t\t%lu\t%lu\n", end_time_spi-start_time_spi, end_time_i2c-start_time_i2c);
delay(200);
}
Comments
Post a Comment