PR

ESP32-WROOM-32EのSPIでBME280の情報を取得

組み込みエンジニア
本記事はプロモーションが含まれています。

こんにちは、ENGかぴです。

Arduino環境ではSPIライブラリを使うと簡単にSPI通信が実現できます。BME280は温湿度・気圧センサーでありI2C/SPIの双方の通信に対応しておりSPIで情報の取得ができます。SPIでセンサー情報を取得する方法をまとめました。

ESP32-WROOM-32E開発ボード(秋月電子)を使用しArduino IDEで開発を行います。また、AE-BME280(秋月電子)を使用しています。

BME280の製作メーカーが提供しているBME280用のAPIを組み込んで動作させる方法とライブラリマネージャからインストールした「Adafruit BME280」を使用する方法を紹介しています。

ESP32-WROOM-32Eを使って動作確認したことをまとめています。

ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方

ESP32-WROOM-32EでSPIを使用する

標準ライブラリである「SPI.h」をインクルードして使用します。SPIライブラリを使用した送信と受信の方法を中心に説明しています。

BME280のAPIを使用する方法

Arduino環境にBME280APIを追加する方法については下記記事にまとめています。

ArduinoのSPIライブラリを使ってBME280のデータを取得する

以下の説明はBME280APIが作業フォルダに準備されていることを前提にしてSPIライブラリを組み込む方法を中心に説明しています。

SPIを使用する場合のピン配置

ESP32-WROOM-32EはSPIはVSPIとHSPIが実装されています。ソフトウェアSPIを使用する場合は任意のピンで動作させることができます。特に指定しない場合はVSPIを使用するように設定されます。

信号名ピン番号:シルク説明
VSPI_SCK30ピン:18SPIデバイスへのクロックを出力する
VSPI_MISO31ピン:19マスタが入力でスレーブが出力
VSPI_MOSI37ピン:23マスタが出力でスレーブが入力
VSPI_SS29ピン:5SPIデバイス(スレーブ)の選択
SPIの配線の組み合わせ(VSPI)
信号名ピン番号:シルク説明
HSPI_SCK12ピン:14SPIデバイスへのクロックを出力する
HSPI_MISO13ピン:12マスタが入力でスレーブが出力
HSPI_MOSI15ピン:13マスタが出力でスレーブが入力
HSPI_SS23ピン:15SPIデバイス(スレーブ)の選択
SPIの配線の組み合わせ(HSPI)

ピン番号はESP32-WROOM-32Eの左上から反時計回りにピンを数えた場合の番号です。シルクはピンの横に印刷された番号で主にGPIOの番号になります。

VSPI_SSやHSPI_SS(スレーブセレクト)は任意のDOを指定しても問題ありません。SPI通信を行う最初にスレーブ(BME280)に対してデバイスが選択されたことを通知するために使用します。

BME280はESP32-WROOM-32EのSCKのクロックの供給によってデータの返信をします。クロックが供給されなければデータを返信することができません。

SPI通信は基本的にマスター(クロックを出す側)がスレーブ(クロックを受けて動作する側)に対してクロックを供給する関係になります。

PR:わからないを放置せず、あなたにあった最低限のスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!

SPIライブラリのセットアップ

#include <SPI.h>

#define SPI_SS 5 //SSのDOに使用する番号
SPIClass *spi = NULL; //SPIクラスのポインタを準備

最初に「SPI.h」をインクルードする必要があります。SPI_SSはスレーブセレクトに使用するDOの番号を定義しています。SPIクラスのポインタを宣言しているのはVSPIとHSPIを切り替える際に使用するためです。VSPIに固定する場合は必要ありません。

void setup() {

  pinMode(SPI_SS,OUTPUT);
  digitalWrite(SPI_SS, HIGH); //HにしてSS選択を解除
  spi = new SPIClass(HSPI); //HSPIを選択する場合
  spi->begin();
//SPI.begin(SPI_SCLK,SPI_MISO,SPI_MOSI,SPI_SS); ソフトウェアSPIの場合の例
}
//使用例
spi->transfer(reg_addr); //ポインタに対するアクセスなので->となる

HSPIを使用するためにはSPIクラスにおいてHSPIを指定する必要があります。SPIクラスのポインタで宣言してspiにNewでSPIクラスのインスタンス(実体)を作ってアドレスを渡しています。spiがSPIの実体として動くため以降のソースではspiを使用します。

BME280はアクティブL(CSがLレベルの時動作)なので初期状態としてHレベルにしています。ソフトウェアSPIはGPIOをSPI通信を模擬して動作させるもので任意のGPIOピンを指定して動作させることができますが、速度をあまり高速にできません。使用する場合はbegin()の引数でピン番号を指定します。

SPI通信のモードと開始

初期条件から変更しない場合はbeginTransaction()及びSPISettings()による設定は必要ありません。初期条件は通信速度が1MHzでありSPIモード0でMSBFISTでデータを送信するようになっています。

spi->beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE0)); //設定して開始

SPI通信の設定はSPISetting()で行います。第1引数にSPI通信の速度を設定します。第2引数にデータのビット構成を指定します。最上ビットから送る場合はMSBFIRST、最下位ビットから送る場合はLSBFIRSTを指定します。第3引数にSPIモードを指定します。

beginTransaction()はSPISettings()の戻り値を指定することで設定した条件でSPI通信を開始します。

PR:RUNTEQ(ランテック )- マイベスト3年連続1位を獲得した実績を持つWebエンジニア養成プログラミングスクール

SPIの4つのモード(参考)

SPIには4つのモードがありCPOLビットとCPHAビットの組み合わせによって動作が決まります。

CPOLビットはマスタがアイドル状態(何もせず待機している)ときはのクロックの極性を決めるものです。0にするとクロックがLレベルでアイドルとなり1にするとクロックがHレベルでアイドルとなります。

CPHAビットはクロックの位相を選択するものです。0にするデータをクロックの立上がりでサンプリング(データを確定)し立下りでデータをシフト(次のビットの値をセット)します。1にするとデータをクロックの立下りでサンプリングし立上がりでデータをシフトします。

モードCPOL:CPHA説明
00:0クロックはアイドル時Lレベル
クロックの立上がりでデータをサンプリングし、
立上りでシフトする
10:1クロックはアイドル時Lレベル
クロックの立下りでデータをサンプリングし、
立上がりでシフトする
21:0クロックはアイドル時Hレベル
クロックの立上りでデータをサンプリングし、
立下りでシフトとする
31:1クロックはアイドル時Hレベル
クロックの立下りでデータをサンプリングし、
立上りでシフトする
SPIモードのまとめ

基本的に制約がない限りモードを気にせずに使用できますが、スレーブの仕様によってデータの準備のタイミングなどの影響を受けるためスレーブ側の通信仕様を確認しておくことが必要です。

SPIによるデータ送信の例

BME280APIのデータ送信関数にArduinoのSPIを組み込んで送信する例を示します。

int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len){
    int8_t rslt = 0;

    spi->beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE0)); //設定して開始
    digitalWrite(SPI_SS, LOW);

    spi->transfer(reg_addr);

    for(uint16_t i = 0; i < len; i++){
        spi->transfer(*reg_data);
        ++reg_data;
    }
    digitalWrite(SPI_SS, HIGH);
    spi->endTransaction();
    
    return rslt;
}

最初にSPIスレーブとの通信条件を設定します。通信条件が初期値から変更しない場合は特に必要ありません。通信条件を設定するとSPI通信開始のためSSをLレベルにしてデバイスが選択されていることを通知します。

transfer(reg_addr)で対象のアドレスを指定し、lenサイズ分だけtransfer(*reg_data)によってデータを送信(書き込み)しています。書き込むアドレスとサイズやデータはBME280APIが引数として指定しています。

データを送信が完了するとSSをHレベルしてデバイスの選択を解除しendTransaction()によって通信を終了します。

PR:スキマ時間で自己啓発!スマホで学べる人気のオンライン資格講座【スタディング】まずは気になる講座を無料で体験しよう!

SPIによるデータ受信の例

BME280APIのデータ受信関数にArduinoのSPIを組み込んでデータ受信する例を示します。受信も送信と同様にSPI.transfer()を使用しますがアドレス指定した後データを読み込む際の用途が異なります。

int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len){
    int8_t rslt = 0;

    spi->beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE0)); //設定して開始
    digitalWrite(SPI_SS, LOW);
    spi->transfer(reg_addr);

    for(uint16_t i = 0; i < len; i++){
        *reg_data = spi->transfer(0x00);
        ++reg_data;
    }
    digitalWrite(SPI_SS, HIGH);
    spi->endTransaction();

    return rslt;
}

基本的な手順は送信と同じですがデータの取得部分が.transfer(reg_addr)で対象のアドレスを指定し、lenサイズ分だけデータを取得するためにダミーで0を送信しています。

ダミーで0を送信しているのはスレーブに対してクロックを供給するためです。スレーブはマスタのクロックに同期して返信データをセットするためダミーで0を送信すると同時にスレーブが応答し、そのデータをreg_dataに格納しています。

スレーブに対してクロックを供給することが目的なのでダミーデータは任意の1バイトデータで問題ありません。SPIは基本的に送信と受信が同時に処理される仕様であることがポイントです。

データを受信が完了するとSSをHレベルしてデバイスの選択を解除しendTransaction()によって通信を終了します。

Adafruit BME280 ライブラリを使用する

Arduino IDEのライブラリマネージャの検索欄にbme280を入力するとBME280ライブラリの候補が表示されます。候補の中からAdafruit BME280 Libraryをインストールします。

Adafruit BME280 Libraryをインストールする際に他の追加ライブラリをインストールするか選択するメッセージが表示されることがあります。

Adafruit BME280 Libraryは他のライブラリと関連性があるため単体では使用できないためインストールを勧められています。Install allを選択してその他のライブラリも追加します。

#include <Adafruit_BME280.h>
#include <SPI.h>
#define BME_SS 5

//変数宣言
Adafruit_BME280 bme280(BME_SS); //測定情報などを格納する変数を宣言
//初期化
bme280.begin();
//使用例
bme280data[0] = bme280.readTemperature(); //温度情報を取得
bme280data[1] = bme280.readPressure() / 100.0F; //気圧情報を取得
bme280data[2] = bme280.readHumidity(); //湿度情報を取得

Adafruit BME280 Libraryをインクルードします。setup()関数内でbme28.begin()でライブラリの初期化を行います。BME280をSPIで使用する場合は変数でAdafruit_BMEの型で宣言した変数に引数としてSS番号を指定します。

Adafruit_BMEライブラリではVSPIを使用するように初期化されます。begin()において引数にSPIライブラリのように各種ピン番号を指定することでソフトウェアSPIによる動作も可能です。

温度情報の取得はreadTemperature()、気圧情報の取得はreadPressure()、湿度情報の取得はreadHumidity()を使用します。

使用例のようにデータを取得した場所で関数をコールするだけで簡単に測定値が取得できるため手短に動作確認したい場合にお勧めのライブラリです。

PR:無料トライアル実施中【PC専用】AIスライド資料作成ツールの利用:イルシル

動作確認

動作確認用の回路図(SPI通信)
動作確認用の回路図(SPI通信)

ESP32-WROOM-32EとBME280の配線例を示しています。初期化時に指定しなければVSPIになります。VSPIは黒線の配線になりますが、HSPIを選択した場合は青線の配線となります。

回路図の番号はESP32-WROOM-32Eの左上を1ピンとした時反時計回りにピンを数えた場合の番号としています。ピン番号横の()内の番号はシルク印刷されているピンの名称です。

VSPI_SS及びHSPI_SSは任意のDOを選択しても良いのですが可能な限りSSピンに配線するようにしておくと確認がしやすくなります。

電源ONしてから1秒間隔でBME280の測定とデータの取得を行います。シリアルモニタの表示を確認するとデータが取得できていることが分かりました。

BME280のデータをSPIで取得した場合の結果
BME280のデータをSPIで取得した場合の結果

温度(Temperature)は部屋に置いている温度計によると24.5℃であり、気圧(Pressure)はスマホを見ると998hPa=998mBarで湿度(Humidity)についてはスマホのデータでは66%でした。設置する環境にも左右されますがSPI通信でデータが取得できていることが確認できたため良好な結果です。

スポンサーリンク

ソースコード全体

ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。

リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。

ソースコードをダウンロード

上記のスケッチ例のみでは動作しません。関連記事である ArduinoのSPIライブラリを使ってBME280のデータを取得する で紹介しているBME280APIのソースを追加し、スケッチ例を上記のものと置き換えると動作します。

関連リンク

Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方

ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方

PR:わからないを放置せず、あなたにあった最低限のスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!

最後まで、読んでいただきありがとうございました。

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