WaveShareからRaspberry Pi Pico互換ボードでESP32-S2を搭載した基板を入手したので評価してみます。
Arduino環境でのセットアップ、トラブル事例と、基本的な入出力、通信機能(UART, I2C, SPI)を使ってみます。
紹介するもの
ESP32-S2-Pico
特徴
電源とGND、GPIOピン位置は互換であるが、ピン番号互換は無い。
ESP32-S2搭載であるため、処理速度は高い。
技適未対応です。
ライブラリはRP2040のものは使用できないので、ESPライブラリを使用することになります。
接続 | Type C |
CPU | ESP32-S2 Xtensa LX7 (240MHz) |
フラッシュMemory | 4MB |
PSRAM | 8MB |
GPIO | 26 |
PWM | 26 同時に8本まで使用可能 (8bit 255まで) |
DAC | 1 (8bit 0 ~ 255, 3.3V) |
ADC | 15 (13bit 0 ~ 8191, 3.3V) |
UART | 2 |
I2C | 1 |
SPI | 2 |
ボタン | RESET |
LED | 1 赤 (GP9) |
ピン配置


外観


400穴ブレッドボードでは、左右2列ずつ使用することができます。

Raspberry Pi Pico と比べても電源、GND、IOピン位置は同じです。
ピン番号と通信ピンが違うのでボードライブラリを変更しても互換にはなりません。

使ってみて
技適がないので電波は出せませんが、高性能マイコン基板としては十分使用できます。
Ali Expressでも\1,000強で、入手性も悪くありません。
Raspberry Pi Picoの互換製品としては電源とGND位置は共通ですが、ピン番号違い以外にもADCの位置や分解能の違いがありますが、ソフトウエアで吸収できる範囲だと思います。
無線を使用することができませんが、ピン設定はRP2040より自由度が高く処理性能も高いので、単純な置き換えとして以外にも高いパフォーマンスと使い勝手の良さは感じられます。
Waveshare ESP32-S3-Picoの記事
準備
ライブラリ
ボードライブラリ
Arduino IDEのボードマネージャからESP32用のライブラリのインストールとボードの選択をします。
ボードマネージャのURL | https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json |
検索 | ESP |
ボードライブラリ | esp32 by Espressif Systems バージョン x.x.x※ |
選択するボード | esp32 > ESP32S2 Dev Module |
モジュールライブラリ
機能やモジュールを使用しない場合インストールの必要はありません。
機能/モジュール | ライブラリ名 | 検索 | 確認時のバージョン |
---|---|---|---|
SSD1306 | Adafruit SSD1306 by Adafruit | SSD1306 | 2.5.1 |
ST7735 | Adafruit ST7735 and ST7789 Library by Adafruit | ST7735 | 1.9.3 |
関連 SSD1306 ST7735 | Adafruit GFX Library by Adafruit | GFX | 1.11.3 |
スケッチの書き込み
一度スケッチを書きこむとCOMポートの認識をしなくなる。
スケッチを書き込むときは、次の2通りの方法で行う。
・BOOTボタンを押しながら電源を投入する。
・電源投入後にBOOTボタンを押しながらRESETボタンを押す。
COMポートが認識されるようになるので、ArduinoIDEからCOMポートを選択して書き込みを行う。
トラブル
現象(OLEDでの表示で意図した通りの動作をしない)
OLEDでの表示で、意図したとおりの描画ができず表示速度が遅い。

原因
詳しい原因はわかりません。
I2CのSDA, SCLのGPIO番号の指定先に GPIO6, GPIO7を指定したことによると推測。
公式のピン配置表では、I2C1で使用できることになっているがWireでもWire1を使用しても同結果。
また、SDA, SCLを反対に使用しても同結果。
すべての組み合わせを調査していないが、GPIO6, GPIO7, GPIO8を含むI2Cのピン設定を行うことで発生する。
対応
当該GPIOピン番号の使用を避ける。
そのほか情報
確認日 : 2022.11.13
ライブラリ : esp32 by Espressif Systems バージョン 2.0.5
ボード : ESP32S2 Dev Module
基本スケッチ
LEDチカ
説明
基板上のLEDを点滅させます。
ESP32-S2-PicoのビルトインLEDのGPIO番号はGP9です。
スケッチ
#define LED1 9 //BuiltINLED1 (赤)
void setup()
{
pinMode(LED1, OUTPUT); //ピン出力設定
}
void loop()
{
digitalWrite(LED1, HIGH);
delay(500);
digitalWrite(LED1, LOW);
delay(500);
}
結果
LEDが点滅しました。

PWM
説明
PWMを使ってLEDのフェード点灯(ゆっくり点灯)とフェード消灯(ゆっくり消灯)を行います。
スケッチ
//ESP32-S2 picoで使用できる PWMは
// 2, 3, 4, 5, 43, 44, 14, 15
#define LED 2 //
void setup()
{
pinMode(LED , OUTPUT);
}
void loop()
{
int i;
for (i = 0; i < 256; i ++)
{
analogWrite(LED , i);
delay(5);
}
for (i = 0; i < 256; i ++)
{
analogWrite(LED , 255 - i);
delay(5);
}
}
結果
動作結果の動画は用意していませんが、LEDがゆっくり点灯とゆっくり消灯を繰り返しました。

ADC
説明
スライド抵抗通過後の電圧値を読み取ります。
USB-シリアル変換アダプタとしてFT232RLを使用していますが、ESP32-S2-Picoはスケッチ書き込み後USBからのCOMが認識されなくなるので、UART0を使用して結果を読み取ります。
UART0はGP43(TX), 44(RX)ですので、FT232RLを配線しています。
配線
ESP32-S2-Pico | 配線 | スライド抵抗 | 配線 | FT232RL |
---|---|---|---|---|
3.3V | 赤 | + | ||
GND | 黒 | – | ||
GP6(Analog Input) | 白 | S | ||
GP43(TX) | 黄 | 黄 | RX | |
GP44(RX) | 緑 | 緑 | TX |

スケッチ
#define PIN_ADC0 6 //ADC0
#define PIN_ADC1 7 //ADC1
#define PIN_ADC2 8 //ADC2
void setup()
{
delay(1000);
Serial.begin(115200); //結果はCOMに出力
//ESP32-S2 picoの場合、書き込み後にUSB のCOM出力が認識されなくなるので、UART0(GP43 TX, GP44 RX)から読み取りを行う。
//ADCは3個読み取りで使用する
pinMode(PIN_ADC0, INPUT);
pinMode(PIN_ADC1, INPUT);
pinMode(PIN_ADC2, INPUT);
}
void loop()
{
//ESP32-S2 picoのADCは13bit (0 ~ 8191)
long ADC0 = 0;
long ADC1 = 0;
long ADC2 = 0;
ADC0 = analogRead(PIN_ADC0);
ADC1 = analogRead(PIN_ADC1);
ADC2 = analogRead(PIN_ADC2);
//100msごとに読み取った値を表示する。
Serial.printf("ADC0, ADC1, ADC2 = %4ld, %4ld, %4ld\r\n", ADC0, ADC1, ADC2);
delay(100);
}
結果
スライド抵抗の持ち合わせが一つしかないので、画像の結果はGP6(ADC0)に接続しているときのものです。
スライド抵抗のつまみを変化させることで、A/Dの読み取り値に変化がありました。
ADC1とADC2はオープン状態ですので何らかのノイズを拾っています。
スライド抵抗を接続すれば、正常なAD値を読み取ることはできます。

UART
説明
UARTは2系統ありますが、UART0はCOMになります。
ESP32-S2-Picoはスケッチ書き込み後にUSBのCOMは認識されなくなるので、UART0を使用するにはGP43(TX)とGP44(RX)を使用します。
UART1はそのままでは内部フラッシュに接続されているので、そのままでは使用できません。
スケッチでピン指定して使用しています。
UART0(COM)から読み取ったデータをUART1に送信します。
UART1から読み取ったデータをUART0(COM)に送信真します。
配線
ESP32-S2-Pico | 配線 | FT232RL(UART0側) | 配線 | FT232RL(UART1側) |
---|---|---|---|---|
GP2(UART1TX) | 緑 | RX | ||
GP3(UART1RX) | 黄 | TX | ||
GP43(UART0TX) | 橙 | 橙 | RX | |
GP44(UART0TX | 紫 | 紫 | TX |

スケッチ
void setup()
{
Serial.begin(115200); //SerialオブジェクトはUART0 (COM)
Serial1.begin(115200, SERIAL_8N1, 2, 3); //Serial1 オブジェクトは ピン指定で、RX = GP2, TX = GP3 で設定する
}
void loop()
{
if(Serial1.available() != 0) //UART1にデータがあれば、読み取った内容をUART0に送信
{
Serial.write(Serial1.read());
}
if(Serial.available() != 0) //UART0にデータがあれば、読み取った内容をUART1に送信
{
Serial1.write(Serial.read());
}
}
結果
結果はTeratermを起動して確認します。
Teratermから送信した文字は、エコーバックにより表示されます。
UART0にUSBのCOMが使用できないので、FT232RLを使って送受信を行います。
橙と紫の配線がUART0, 黄と緑の配線がUART1です。

今回UART1はCOM9、UART0はCOM151と認識されました。
UART1側から青の実線枠の入力を行うと、UART0側の青の点線枠のように入力した文字が出力されました。
UART0側から赤の実線枠の入力を行うと、UART1側の赤の点線枠のように入力した文字が出力されました。

I2C(I2C0 : SSD1306)
説明
I2Cを使ってSSD1306(OLED 0.96inch)モニタのサンプルを動作させます。
ESP32-S2-PicoにはI2Cが2系統あるので、まずI2C0を使ってみます。
使用するサンプルスケッチはAdafruit SSD1306のサンプルを使用しますが、ピン番号を設定するために、Wireオブジェクトのbegin()メソッドに、使用するピン番号を指定します。
サンプルスケッチ62行目
Wire.begin(16, 17, 1000000 );
配線
ESP32-S2-Pico | 配線 | SSD1306(0.96inch) |
---|---|---|
3.3V | 赤 | VCC |
GND | 黒 | GND |
GP16 | 黄 | SDA |
GP17 | 白 | SCL |

[2022.11.13追記]
GPIO6, GPIO7, GPIO8 を使用すると意図した通りの描画を行わない現象が確認されたのでピン指定しないでください。
スケッチ
Arduinoサンプルスケッチを掲載します。
ファイル(F) > スケッチ例 > Adafruit SSD1306 > ssd1306_128x64_i2c
変更箇所
使用しているSSD1306 OLEDのI2Cアドレスを変更して使用してください。
35行目 : 当方 0x3cで使用しているため変更しています。
Wireオブジェクトのbegin()メソッドに、使用するピン番号を指定します。
SDAをGP16, SCLをGP17, I2Cクロックを1000000(100kHz)
62行目 : Wire.begin(16, 17, 1000000 );
/**************************************************************************
This is an example for our Monochrome OLEDs based on SSD1306 drivers
Pick one up today in the adafruit shop!
------> http://www.adafruit.com/category/63_98
This example is for a 128x64 pixel display using I2C to communicate
3 pins are required to interface (two I2C and one reset).
Adafruit invests time and resources providing this open
source code, please support Adafruit and open-source
hardware by purchasing products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries,
with contributions from the open source community.
BSD license, check license.txt for more information
All text above, and the splash screen below must be
included in any redistribution.
**************************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#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)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
0b00000001, 0b11000000,
0b00000001, 0b11000000,
0b00000011, 0b11100000,
0b11110011, 0b11100000,
0b11111110, 0b11111000,
0b01111110, 0b11111111,
0b00110011, 0b10011111,
0b00011111, 0b11111100,
0b00001101, 0b01110000,
0b00011011, 0b10100000,
0b00111111, 0b11100000,
0b00111111, 0b11110000,
0b01111100, 0b11110000,
0b01110000, 0b01110000,
0b00000000, 0b00110000 };
void setup() {
Serial.begin(115200);
Wire.begin(16, 17, 1000000 );
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Draw a single pixel in white
display.drawPixel(10, 10, SSD1306_WHITE);
// Show the display buffer on the screen. You MUST call display() after
// drawing commands to make them visible on screen!
display.display();
delay(2000);
// display.display() is NOT necessary after every single drawing command,
// unless that's what you want...rather, you can batch up a bunch of
// drawing operations and then update the screen all at once by calling
// display.display(). These examples demonstrate both approaches...
testdrawline(); // Draw many lines
testdrawrect(); // Draw rectangles (outlines)
testfillrect(); // Draw rectangles (filled)
testdrawcircle(); // Draw circles (outlines)
testfillcircle(); // Draw circles (filled)
testdrawroundrect(); // Draw rounded rectangles (outlines)
testfillroundrect(); // Draw rounded rectangles (filled)
testdrawtriangle(); // Draw triangles (outlines)
testfilltriangle(); // Draw triangles (filled)
testdrawchar(); // Draw characters of the default font
testdrawstyles(); // Draw 'stylized' characters
testscrolltext(); // Draw scrolling text
testdrawbitmap(); // Draw a small bitmap image
// Invert and restore display, pausing in-between
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}
void loop() {
}
void testdrawline() {
int16_t i;
display.clearDisplay(); // Clear display buffer
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
display.display(); // Update screen with each newly-drawn line
delay(1);
}
for(i=0; i<display.height(); i+=4) {
display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=0; i<display.height(); i+=4) {
display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=0; i<display.width(); i+=4) {
display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000); // Pause for 2 seconds
}
void testdrawrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=2) {
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(2000);
}
void testfillrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=3) {
// The INVERSE color is used so rectangles alternate white/black
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(2000);
}
void testdrawcircle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000);
}
void testfillcircle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
// The INVERSE color is used so circles alternate white/black
display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
display.display(); // Update screen with each newly-drawn circle
delay(1);
}
delay(2000);
}
void testdrawroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000);
}
void testfillroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
// The INVERSE color is used so round-rects alternate white/black
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000);
}
void testdrawtriangle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
display.drawTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000);
}
void testfilltriangle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
// The INVERSE color is used so triangles alternate white/black
display.fillTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000);
}
void testdrawchar(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
// Not all the characters will fit on the display. This is normal.
// Library will draw what it can and the rest will be clipped.
for(int16_t i=0; i<256; i++) {
if(i == '\n') display.write(' ');
else display.write(i);
}
display.display();
delay(2000);
}
void testdrawstyles(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.println(F("Hello, world!"));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
display.println(3.141592);
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.print(F("0x")); display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
}
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 0);
display.println(F("scroll"));
display.display(); // Show initial text
delay(100);
// Scroll in various directions, pausing in-between:
display.startscrollright(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
}
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);
}
#define XPOS 0 // Indexes into the 'icons' array in function below
#define YPOS 1
#define DELTAY 2
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
int8_t f, icons[NUMFLAKES][3];
// Initialize 'snowflake' positions
for(f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
Serial.print(F("x: "));
Serial.print(icons[f][XPOS], DEC);
Serial.print(F(" y: "));
Serial.print(icons[f][YPOS], DEC);
Serial.print(F(" dy: "));
Serial.println(icons[f][DELTAY], DEC);
}
for(;;) { // Loop forever...
display.clearDisplay(); // Clear the display buffer
// Draw each snowflake:
for(f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
}
display.display(); // Show the display buffer on the screen
delay(200); // Pause for 1/10 second
// Then update coordinates of each flake...
for(f=0; f< NUMFLAKES; f++) {
icons[f][YPOS] += icons[f][DELTAY];
// If snowflake is off the bottom of the screen...
if (icons[f][YPOS] >= display.height()) {
// Reinitialize to a random position, just off the top
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
}
}
}
}
結果
SSD1306のサンプルスケッチが動作しました。

ピン表ではI2C0で使用できるピンとI2C1で使用できるピンでは区別されていますが、サンプル62行目で設定する方法では、I2C1のピンを設定してもI2Cの割り当てのないピン(例 GP2, GP3)を設定しても動作してしまいます。
おそらくソフトウエアI2Cで動作しているものと思います。
H/W I2Cの設定方法が見つかっていないのでわかり次第更新します。
I2C(I2C0 & I2C1 : SSD1306)
説明
I2C0とI2C1 を使ってデュアルモニタで動作させます。
I2C(I2C0 : SSD1306)で紹介した通り、I2C0、I2C1ともにどのピンでも設定できてしまいますが、それでもピン表に従い、I2C0はGP16(SDA), GP17(SCL)を使用し、I2C1はGP14(SDA), GP15(SCL)を使用することとします。
配線
ESP32-S2-Pico | 配線 | I2C0側 SSD1306(0.96inch) | 配線 | I2C1側 SSD1306(1.54inch) |
---|---|---|---|---|
3.3V | 赤 | VCC | 赤 | VCC |
GND | 黒 | GND | 黒 | GND |
GP16(I2C0 SDA) | 黄 | SDA | ||
GP17(I2C0 SCL) | 白 | SCL | ||
GP14(I2C1 SDA) | 橙 | 橙 | SDA | |
GP15(I2C1 SCL) | 緑 | 緑 | SCL |

SSD1306 0.96inchが手元に2個なかったので、SSD1306(1.54inch)を使用しています。
両方とも同じスケッチで動作します。
1.54inch にはReset端子ありますが接続しなくても動作するので配線していません。
[2022.11.13追記]
GPIO6, GPIO7, GPIO8 を使用すると意図した通りの描画を行わない現象が確認されたのでピン指定しないでください。
スケッチ
I2C(I2C0 : SSD1306) で紹介したサンプルスケッチを修正します。
重複箇所が多いので変更点のみを掲載します。
変更箇所
I2C1 を使用するためのWire1を追加。(37行目)

I2C1のピンを設定するための追加。(64行目)

I2C1 SSD1306を開始するための処理追加(72 から75行目)と、表示(80行目)

結果
SSD1306のサンプルスケッチが動作しました。
デュアルモニタの確認だけなので、I2C1側(1.54inch側)はAdafruitのタイトルだけですが、display1オブジェクトを使用することでI2C0側と独立して描画を行うことができます。

SPI(ST7735)
説明
SPIを使ってST7735(LCD 1.8inch)モニタのサンプルを動作させます。
ESP32-S2 picoではSPIを2系統使用できます。
1系統目(VSPI)はデフォルトのピン設定は、GP35(MOSI), GP36(CLK)です。
1系統目(VSPI)、2系統目(HSPI)ともに自由にピン設定ができる。
そのほかのグラフィックのサンプルはArduinoサンプルスケッチを参照してください。
ファイル(F) > スケッチ例 > Adafruit ST7735 and ST7789 Library > graphicstest
配線
デフォルトのH/W FSPI GP35(MOSI), GP36(CLK)を使用する配線。
ESP32-S2-pico | 配線 | ST7735(1.8inch) |
---|---|---|
3.3V | 赤 | VCC |
3.3V | 赤 | LED |
GND | 黒 | GND |
GP2 | 紫 | CS |
GP3 | 橙 | RESET |
GP4 | 白 | AO |
GP35(FSPI0 MOSI) | 青 | SDA |
GP36(FSPI0 CLK) | 黄 | SCK |

H/W FSPI を GP15(MOSI), GP16(CLK)に変更して使用する配線。
スケッチ
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/
【マイコン基板】
ESP32-S2-Pico で利用できます。
【スケッチの説明】
ST7735 LCDの表示制御します。
ESP32-PICO-KIT にはH/W SPIが2系統あります。(VSPI, HSPI)
H/W SPI(VSPI, HSPI)を使用するための方法についてサンプル記載します。
【ライブラリ】
esp32 > ESP32S2 Dev Module
Adafruit ST7735 and ST7789 Library
Adafruit GFX Library
【準備】
VSPIを使用する場合
ESP32-S2-Pico <-> ST7735
3V3 <-> VCC
GND <-> GND
GPIO2(CS) <-> CS
GPIO3(Reset) <-> Reset
GPIO4(DC) <-> AO
GPIO35(MOSI) <-> SDA
GPIO36(SCK) <-> SCK
HSPIを使用する場合
自由に設定できるが、例としてVSPIと同じピン番号を示す。
ESP32-S2-Pico <-> ST7735
3V3 <-> VCC
GND <-> GND
GPIO2(CS) <-> CS
GPIO3(Reset) <-> Reset
GPIO4(DC) <-> AO
GPIO35(MOSI) <-> SDA
GPIO36(SCK) <-> SCK
【バージョン情報】
2022/10/8 : 新規
2022/12/11 : hspi 制御追記
**********************************************************************/
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
//CS, RST, DCは任意のピンを指定可
//MOSI(35), SCK(36)はデフォルトで指定しなくても使用可能。
//ピン変更する場合は SPI.begin()を使用する。
//VSPI(SPIオブジェクト), HVSPI(hspiオブジェクト)ともにピン設定は自由
#define TFT_CS 2
#define TFT_RST 3
#define TFT_DC 4
#define TFT_MOSI 35
#define TFT_SCK 36
#define SPI0
#ifdef SPI0
//デフォルトVSPIを使用する場合
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
#else
//もう一系統のSPIを使用する場合
SPIClass hspi(HSPI);
Adafruit_ST7735 tft = Adafruit_ST7735(&hspi, TFT_CS, TFT_DC, TFT_RST);
#endif
//S/W SPIはこちら。遅いが任意のピンを使用できる。
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
void setup(void)
{
// SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS); //VSPIピンを変更して使用する場合、この行のコメントを解除
// hspi.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS); //HSPIピンを変更して使用する場合、この行のコメントを解除
tft.initR(INITR_BLACKTAB); //Init ST7735S初期化
tft.fillScreen(ST77XX_BLACK); //背景の塗りつぶし
//テキスト表示
tft.setRotation(3); //画面回転
tft.setTextSize(3); //サイズ
tft.setCursor(0, 20); //カーソル位置
tft.setTextColor(ST77XX_RED); //赤
tft.printf("TAMANEGI\n");
tft.setTextColor(ST77XX_GREEN); //緑
tft.printf("TAMANEGI\n");
tft.setTextColor(ST77XX_BLUE); //青
tft.printf("TAMANEGI\n");
tft.setTextColor(ST77XX_YELLOW); //黄
tft.printf("TAMANEGI\n");
}
void loop()
{
tft.setTextColor(ST77XX_YELLOW); //黄
tft.printf("TAMANEGI\n");
}
結果
ST7735のサンプルスケッチが動作しました。

コメント