Arduino環境でXIAO ESP32C3を使う

it

SeeedStudioのXIAOシリーズ XIAO ESP32C3を使ってみました。
Arduino環境での準備や基本的な使い方をまとめました。
IOの設定、通信(UART, I2C, SPI)、BLEサンプルを記載します。

記事の目的と内容

この記事ではArduino環境で XIAO ESP32C3を使ってみた感想と使い方について記載します。
内容は
・XIAO ESP32C3の主な仕様
・使用するための準備、スケッチの書き込み方
・I/O マイコン通信の使い方
・BLEのUART通信

Arduino 環境の作成方法はこちら

XIAO ESP32C3について

SeeedStudioのXIAOシリーズでピン互換があり、小型の基板でも多くの機能を使えます。
技適付きで手軽に無線による通信制御ができます。
比較的入手性もよく、技適付きマイコンでは安価な部類。

主なスペック

接続Type C
CPUESP32 C3 RISC-V 160MHz
メモリSRAM 400KB
フラッシュ 4MB
GPIOI/O 11
PWM 11(8bit 0 ~ 255)同時に6chまで使用可能
ADC 4(12bit 0 ~ 4095)
通信UART 1
I2C 1
SPI 1
2.4GHz Wi-fi
Bluetooth 5.0
そのほかBOOT
RESET
参考価格\1,100 ~ \1,500
入手性:主観です。
参考価格:変動することがあります。保証価格ではありません。単品、送料税込み価格です。

XIAOの公式サイトです。

◆XIAOシリーズの記事

XIAO SAMD21XIAO SAMD21を使った記事。
基本的なGPIOの操作とDAC出力、書き込み時のトラブルについてまとめた記事です。
XIAO RP2040XIAO RP2040を使った記事。
使っている時に発生したI2CのWireとWire1問題、WS2812の点灯などトラブルを中心に記載しました。
XIAO ESP32-C3XIAO ESP32-C3を使った記事。
GPIOを使った基本スケッチ、BLE UARTを使った内容を記事にしました。
XIAO ESP32-S3XIAO ESP32-S3/XIAO ESP32-S3 Sense を使った記事。
GPIOを使った基本スケッチの他静電容量タッチセンサ、カメラWebサーバーを使った内容を記事にしました。
XIAO nRF52840XIAO nRF52840/XIAO nRF52840 Senseを使った記事。
GPIOを使った基本スケッチ、BLE UART他、XIAO nRF52840 SenseのIMU 6軸センサ、PDM Microphoneを使った内容を記事にしました。
XIAO RA4M1XIAO RA4M1を使った記事。
基板特有のトラブルと基本的なGPIOの操作について記事にしました。
XIAO RP2350XIAO RP2350を使った記事。
XIAO RP2040との比較を中心に搭載機能を使った内容を記事しました。
XIAO ESP32C6XIAO ESP32C6を使った記事。
基本的なGPIOの使い方からWiFiServerにして読み取ったDA値を表示してみた内容を記事にしました。

◆関連記事

ESP32C3搭載 小型で安価なSuperMini ESP32C3の記事

ピン配置

外観

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

使ってみて

Good
XIAO規格なので、XIAOシリーズとの高い互換性があります。
小型の基板ながら必要な線はすべて使えて、ブレッドボード上でも面積が小さいのでとても使いやすい。
技適付きの無線が\1,000程度の低価格で使用できるのがうれしい。
アンテナをつけなくても2m程度ならBLE通信ができました。

Bad
規模の大きな開発ではピン数が不足します。
現在のBLEを使うライブラリは、クラッシックBluetoothのスケッチと比べると手軽さがない。
ペーパーアンテナはなくても使えますが、接続すると邪魔です。

USB-UART変換ドライバがないため、USBケーブルからのシリアル通信ができません。
デバッグ出力やマイコン基板とのUARTを行うためには別途USB-UART変換モジュールが必要です。

そのほか
マイコンの勉強やモジュールの実験などの小さなプロジェクトならほとんどのことが手軽にできます。
価格面や入手性の高さも好ポイントです。
国内の多くの電子部品オンラインショップで扱っており、ESP32C3自体の価格もお値打ちです。
総合的に一推しの基板です。

準備

ライブラリのインストール

Arduino IDEでESP32 C3を開発するために、ESP32ボードライブラリをインストールします。
この作業をするために、ArduinoIDEがインストールされている必要があります。

ボードライブラリ

ボードマネージャのURLhttps://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
検索ESP
ボードライブラリesp32 by Espressif Systems バージョン x.x.x※
選択するボードツール > ボード > esp32 > XIAO_ESP32C3
※ x.x.x Sep/2022 動作確認は2.0.3を使用しています

I2C,SPIの記事では小型のOLEDとLCDの表示をします。
サンプルを利用する場合は以下のライブラリのインストールが必要です。

モジュールライブラリ

機能/モジュールライブラリ名検索確認時のバージョン
SSD1306Adafruit SSD1306 by AdafruitSSD13062.5.1
ST7735Adafruit ST7735 and ST7789
Library by Adafruit
ST77351.9.3
関連
SSD1306
ST7735
Adafruit GFX Library by AdafruitGFX1.11.3

スケッチの書き込み方法

XIAO ESP32C3のスケッチの書き込み方法について記載します。
ESP32C3搭載基板はUSBからの書き込みと、UARTピンを使った書き込みの方法があります。

■USBからの書き込み

スケッチの書き込みはESP32 のダウンロードモードにします。
BOOTボタンを押しながら電源を投入するか、BOOTボタンを押しながらリセットボタンを押して再起動します。
ArduinoIDEのスケッチ書き込みボタンを押すことで書き込みができます。
※COMの番号が変わりやすいので、Portが選択されていることを確認してください。

スケッチの書き込み後は電源を再投入するか、リセットボタンを押します。

■UARTピンからの書き込み

USB-UART変換アダプタを使いXIAO ESP32C3のUARTピンに接続します。
変換アダプタから電源を供給するためVCCとGNDを配線しています。

下図はFT232RLを使用した配線の例です。

スケッチの書き込みはESP32 のダウンロードモードにします。
BOOTボタンを押しながら電源を投入するか、BOOTボタンを押しながらリセットボタンを押して再起動します。
ArduinoIDEのスケッチ書き込みボタンを押すことで書き込みができます。

スケッチの書き込み後は電源を再投入するか、リセットボタンを押します。

基本スケッチ

LEDチカ

説明

GPIO2を使用したLチカ(点滅)を行います。

スケッチ

#define PIN_LED (2)

void setup()
{
  //PIN出力モード
  pinMode(PIN_LED, OUTPUT);
}

void loop()
{
  //1秒周期で点滅を行う(500ms点灯、500ms消灯)
  digitalWrite(PIN_LED, HIGH);
  delay(500);
  digitalWrite(PIN_LED, LOW);
  delay(500);
}

結果

LEDが点滅しました。

PWM

説明

PWMを使ってLEDのフェード点灯(ゆっくり点灯)とフェード消灯(ゆっくり消灯)を行います。

スケッチ

#define PWM (2)

void setup()
{
  pinMode(PWM , OUTPUT);
}

void loop()
{
  for(int i = 0; i < 256; i ++)
  {
    analogWrite(PWM, i);
    delay(2);
  }

  for(int i = 0; i < 256; i ++)
  {
    analogWrite(PWM, 255 - i);
    delay(2);
  }
}

結果

PWM制御(analogWrite)でゆっくり点灯、ゆっくり消灯しました。

ADC(アナログ入力)

説明

M5Stamp Pico Mateにはアナログ出力があります。
出力したアナログ信号をADCで読み取ります。

DACは8bit(0~255)で設定して最大で3.3V出力します。
ADCは12bit(0~4095)の最大3.3Vを読み出します。

配線

XIAO-ESP32C3配線スライド抵抗
3.3V+
GND
GPIO2(ADC0)S

スケッチ

#define PIN_ADC0 (2)

void setup()
{
  delay(1000);
  Serial.begin(115200);         //結果をUARTに出力

  pinMode(PIN_ADC0, INPUT);
}

void loop()
{
  long lADC0 = 0;

  lADC0 = analogRead(PIN_ADC0);

  Serial.printf("ADC0 = %4d\n", lADC0);
  delay(100); 
}

結果

結果はADC0にスライド抵抗を接続しています。
スライド抵抗のつまみを変化させることで、A/Dの読み取り値に変化がありました。

サンプルスケッチ

#define UART_TX (21)
#define UART_RX (20)

#define UART1_TX (2)
#define UART1_RX (3)

void setup() {

  Serial.begin(115200);
  //Serial.begin(115200, SERIAL_8N1, UART_RX, UART_TX);       //UARTピンを変更する場合

  Serial1.begin(115200, SERIAL_8N1, UART1_RX, UART1_TX);

}

void loop() {

  if(Serial.available()){
    Serial1.write(Serial.read());
  }

  if(Serial1.available()){
    Serial.write(Serial1.read());
  }
}

I2C(SSD1306)

説明

図形の描画やそのほかの命令はArduinoサンプルスケッチを参照してください。
ファイル(F) > スケッチ例 > Adafruit SSD1306 > ssd1306_128x64_i2c

配線

XIAO-ESP32C3配線SSD1306(0.96inch)
3.3VVCC
GNDGND
GPIO7SCL
GPIO6SDA

スケッチ


//XIAO ESP32C3では I2C SDA(GPIO6), SCL(GPIO7)

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128                //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT 64                //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     -1               //使用しないので -1を設定する。
#define SCREEN_ADDRESS 0x3C             //I2Cアドレスは 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
                                        //表示制御にはAdafruit製 SSD1306を使用する。
                                        
void setup()
{
  

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  display.clearDisplay();               //何か表示されている場合に備えて表示クリア

  display.setTextSize(2);               //フォントサイズは2(番目に小さい)
  display.setTextColor(SSD1306_WHITE);  //色指定はできないが必要
  display.setCursor(20, 5);             //テキストの表示開始位置
  display.print(F("TAMANEGI"));         //表示文字列
  display.setCursor(45, 25);
  display.print(F("XIAO"));
  display.setCursor(25, 45);
  display.print(F("ESP32C3"));

  display.display();                    //バッファ転送(表示)
}

void loop()
{
}

結果

SSD1306のサンプルスケッチが動作しました。

SPI(ST7735)

説明

SPIを使ってST7735(LCD 1.8inch)モニタのサンプルを動作させます。

図形の描画やそのほかの命令はArduinoサンプルスケッチを参照してください。
ファイル(F) > スケッチ例 > Adafruit ST7735 and ST7789 Library > graphicstest

配線

XIAO-ESP32C3配線ST7735(1.8inch)
3.3VVCC
3.3VLED
GNDGND
GPIO3Reset
GPIO4AO(DC)
GP8(SPI SCK)SCK
GP10(SPI MOSI)SDA
GPIO2CS

スケッチ

#include <Adafruit_GFX.h> 
#include <Adafruit_ST7735.h>
#include <SPI.h>

#define TFT_CS          (2)  // CS
#define TFT_RST         (3)  // Reset 
#define TFT_DC          (4)  // DC
#define TFT_MOSI        (10) // MOSI
#define TFT_SCK         (8)  // SCK

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

//S/W SPIはこちら。遅いが任意のピンを使用できる。
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);

void setup(void) 
{
//  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS);   //H/W SPIを使用する場合こちらでピン番号を指定する。
                                              //S/W SPIで使用する場合はコメントアウトする。
  

  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()
{
}

結果

ST7735のサンプルスケッチが動作しました。

特別な機能のスケッチ

BLE-UART

説明

スマートフォンからBTシリアル通信を行います。

XIAO-ESP32 C3のUARTから読み取ったデータを、BLEを使いスマートフォンに送信します。
スマートフォンから読み取ったBLEデータは、UARTへ出力します。

配線

XIAO-ESP32 C3にはUSBシリアルがないので、UARTを使用するためにはUSBシリアルモジュールとXIAO-ESP32 C3を配線します。
USBシリアルモジュールにはFT232RLを使用します。

XIAO-ESP32 C3配線FT232RL
GPIO21(TX)TX
GPIO20(RX)RX

スケッチ

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#define BUFFER 64

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue[BUFFER] = "";

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"


class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
          Serial.print(rxValue[i]);

        Serial.println();
        Serial.println("*********");
      }
    }
};


void setup() {
  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init("BLE UART");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
										CHARACTERISTIC_UUID_TX,
										BLECharacteristic::PROPERTY_NOTIFY
									);
                      
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
											 CHARACTERISTIC_UUID_RX,
											BLECharacteristic::PROPERTY_WRITE
										);

  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {

  //以下修正箇所 COMからデータを読み取り、BLEに送信
  if (deviceConnected == true)
  {
    if(Serial.available() != 0)
    {
      size_t bufSize = Serial.read(txValue, Serial.available());
      pTxCharacteristic->setValue(txValue, bufSize);
      pTxCharacteristic->notify();
    }

		delay(10); // bluetooth stack will go into congestion, if too many packets are sent
	}
  //ここまで

    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
		// do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}

結果

スマートフォンからBLE接続を行いました。
スマートフォンアプリケーションにはSerial Bluetoothを使用します。

アプリケーションを起動し、画面左上のメニューから「Devices」を選択します。
「Bluetooth LE」を選択し、SCANを押します。
スケッチが正常に動作していれば「BLE UART」が表示されるので選択することで接続できます。

パソコン側からはArduinoIDEのシリアルモニタを使用します。
シリアルモニタから入力した文字がアプリケーション上に表示(水色の楕円)されます。
「Serial Bluetooth」アプリケーションから入力した文字が、シリアルモニタに表示(赤色の楕円)されます。

付属のアンテナがない状態でも2m程度は通信ができました。

コメント

タイトルとURLをコピーしました