Arduino環境でロジックレベルコンバータを使う

コンピュータ、組み込み

マイコンでよく使う電圧(5V または 3.3V)のレベル変換を行う基板です。
Raspberry Pi Pico(ロジックレベル3.3V)とArduino Nano(ロジックレベル5V)でのI2C通信で使ってみます。

今回紹介するもの

双方向ロジックレベルコンバータ

特徴

異なる信号レベルの通信を行う場合に、それぞれの信号レベルに電圧を変換します。

電源電圧5V, 3.3V
出力5V -> 3.3V
3.3V -> 5V
チャンネル数4ch

AVR系のAtmega328 や Atmega2560 などのロジックレベルが5Vのマイコンと、RP2040, ESP32などのようにロジックレベルが3.3Vのマイコン同士の通信のレベル変換に使えます。
I2CやSPI、またはモジュールの出力レベルが5Vのものを3.3Vに降圧、3.3Vのものを5Vに昇圧して使用することができます。

外観

普段使用している4chモジュールを紹介します。

使用感

最近発売されるマイコンのロジックレベルは3.3Vで、5Vマイコンの新規品は見なくなりました。
当時ものの入出力モジュールは5V駆動、5V信号のものも少なくないためにロジックレベルの変換モジュールは役立ちます。

こちらでは、超音波距離計測モジュールの通信に使用しました。

マイコン同士を通信させるときにも、ロジックレベルの違うマイコン同士のレベル変換にも使用できるので、1,2個は持っておきたいモジュールです。

この記事ではロジックレベル3.3VのRaspberry Pi Picoとロジックレベル5VのArduino NanoでI2C通信してみました。

準備

使うもの

画像名称、型番用途
双方向ロジックレベル変換モジュールArduinoの5VとRaspberry Pi Picoの3.3Vのロジックレベル変換をします。
Raspberry Pi Picoロジックレベル3.3Vの代表としてI2Cスレーブにします。
Arduino Nanoロジックレベル5Vの代表としてI2Cマスターにします。
ブレッドボード配線します
ジャンパワイヤ数本配線します

動作

説明

ロジックレベルの違うArduino Nano(5V)とRaspberry Pi Pico(3.3V)でI2C通信をします。
今回、Arduino NanoをI2Cマスター側、Raspberry Pi Pico をスレーブ側で使用します。

参考記事、マイコン同士のI2C通信

配線

ロジックレベル変換モジュールのL側のシルクがある方をRaspberry Pi Pico側、H側のシルクがある方をArduino Nano側になるよう配線します。

Raspberry Pi Pico配線ロジックレベル変換モジュール配線Arduino Nano
3V3LV <-> HV5V
GNDGND <-> GNDGND
GPIO0(I2C0 SDA)LV1 <-> HV1A4(I2C SDA)
GPIO1(I2C0 SCL)LV2 <-> HV2A5(I2C SCL)

スケッチ

 /**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
Arduino Nano

【スケッチの説明】
◆◆本スケッチはマスター側です。◆◆
マイコン基板同士でI2C通信を行うためのマスター側です。
COMから読み取った文字をI2Cスレーブ側に送信します。
I2Cスレーブ側からの返答を読み取り、COMに送信します。

【ライブラリ】
Arduino AVR Board > Arduino Nano

【準備】
このスケッチのI2C通信相手はRaspberry Pi Picoを前提としています。
異なるロジックレベルの通信を行うためのロジックレベル変換モジュールを使用します。

ArduinoNano <-> LogicLV変換モジュール <-> Raspberry Pi Pico
5V          <-> HV, LV               <-> 3V3
GND         <-> GND, GND             <-> GND
A4(I2C SDA) <-> HV1, LV1             <-> GPIO0(I2C0 SDA)
A5(I2C SCL) <-> HV2, LV2             <-> GPIO1(I2C0 SCL)

【バージョン情報】
2023/6/15 : 新規
**********************************************************************/
#include "Wire.h"

#define I2C_ADDR  0x01            //スレーブ側に指定するI2Cアドレス

uint32_t i = 0;

void setup() 
{

  Serial.begin(115200);           //パソコン側からの読み取りと書き込みに使用します。

  Wire.begin();
}

void loop() 
{
  char buf_com = 0;
  char buf_i2c = 0;

  //パソコンからの受信処理
  if(Serial.available() == true)
  {
    buf_com = Serial.read();

    //I2Cスレーブへのデータ送信処理
    Wire.beginTransmission(I2C_ADDR);
    Wire.write(buf_com);
    if(Wire.endTransmission(true) != 0)
    {
      Serial.println("送信エラー");            //0 = 成功 / else = エラーとします
    }
    else
    {
      //スレーブへのデータ送信が成功したら、スレーブからの返答を要求する。
      //少し乱暴な書き方ですが、本件は1byte送信,1byte受信で行っています。
      if(Wire.requestFrom(I2C_ADDR, I2C_ADDR) != 0)
      {
        buf_i2c = Wire.read();
      }

      //パソコンへスレーブから読み取ったデータを送信する。
      if(Serial.availableForWrite())
      {
        Serial.write(buf_i2c);
      }
    }
  }  
}
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
Raspberry Pi Pico

【スケッチの説明】
◆◆本スケッチはスレーブ側です。◆◆
マイコン基板同士でI2C通信を行うためのスレーブ側です。
I2Cマスターから読み取った文字がASC英文字大文字と小文字を変換し、I2Cマスターへ送信します。

【ライブラリ】
Raspberry Pi Pico/RP2040 > Raspberry Pi Pico

【準備】
このスケッチのI2C通信相手はArduino Nanoを前提としています。
異なるロジックレベルの通信を行うためのロジックレベル変換モジュールを使用します。

ArduinoNano <-> LogicLV変換モジュール <-> Raspberry Pi Pico
5V          <-> HV, LV               <-> 3V3
GND         <-> GND, GND             <-> GND
A4(I2C SDA) <-> HV1, LV1             <-> GPIO0(I2C0 SDA)
A5(I2C SCL) <-> HV2, LV2             <-> GPIO1(I2C0 SCL)

【バージョン情報】
2023/6/15 : 新規
**********************************************************************/

#include "Wire.h"

#define I2C_ADDR  0x01            //スレーブ側に指定するI2Cアドレス
#define I2C_SDA   0               //SDAにはGP0を使用する
#define I2C_SCL   1               //SCLにはGP1を使用する

char gbuf = 0;                     //

//マスターから要求があれば返答する。
void onRequest()
{
  Wire.write(gbuf);
}

//マスターからデータ送られてくると読み取りをする。
//ASCコード上英文字であれば、大文字と小文字を入れ替えて保管する。
void onReceive(int len)
{
  while(Wire.available()){
    gbuf = Wire.read();

    //ASCコード上で、0b1000 0000ビットが0の時、0b0111 0000 のいずれかが 1なら英文字(正確ではありません。)
    if(((gbuf & 0x80) != 0x80) && ((gbuf & 0x40) == 0x40))
    {
      //ASCコード上で 0b0010 0000 のビットを反転させることで、大文字と小文字を入れ替える。
      gbuf = gbuf ^ 0x20;
    }
  }
}

void setup()
{
  //I2Cスレーブの設定
  Wire.setSDA(I2C_SDA);             //通信に使用するI2Cアドレスピンを指定する
  Wire.setSCL(I2C_SCL);
  Wire.onReceive(onReceive);        //マスターからデータを受信したときに呼び出される関数の登録
  Wire.onRequest(onRequest);        //マスターからデータを要求されたときに呼び出される関数の登録
  Wire.begin(I2C_ADDR);             //通信開始
}

void loop()
{
}

結果

結果はTeratermを起動しArduino Nano側と接続します。
ASC英文字の入力をし、大文字なら小文字、小文字なら大文字に変換されて表示されます。

こちらは通信時の電圧をオシロスコープ(HDS272)で確認しました。
青がArduino Nano の5Vの信号、黄色がRaspberry Pi Picoの3.3Vの信号です。
Arduino Nanoの5Vは2割ほど電圧が下がっていますが、双方向の通信ができました。
‘a’を送信し、’A’を読み取った時の波形ですが、分解能が足りていなくて波形が一部つぶれています。

この信号をロジックアナライザで解析しました。
紫のエリアには61(dec) ASCIIコードのキャラクターで’a’、青のエリアには41(dec) ASCIIコードのキャラクターでは’A’になり、異なるロジックレベルの変換ができたことで正常に通信ができました。

コメント

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