PR

M5stackで複数モジュールを付けるとUARTが競合する問題の解決法

組み込み機器

通信ができません…

こうした悩みを解決します。

姫野秀徳

組み込みエンジニアとしてメーカー勤務10年。
第二種電工事士、基本情報技術者、Code.org認定教師。
microbitを用いた電子工作&プログラミング教室を開校。
組み込み開発の実際を発信するyoutube活動も行う。

無料で学べる組み込み開発オンラインスクールはじめました!
https://kumicla.tatepro.com

姫野秀徳をフォローする

問題

M5stack basicにM5Stack用 3G 拡張ボード(SORACOM)M5Stack用GPSモジュール V2 [M003]を接続しました。

それでGPSモジュールの製品ぺージに下記の記載がされていることを確認しました。

本製品のような専用の拡張モジュールを縦に積み重ねていくことで機能を追加することができます。

この時は何も考えずに、積み重ねて機能追加できるなんて便利だなあと思ってましたが、いざ積み重ねるとどちらも動作しないのです。

そしてモジュールを1つだけ接続して動作させるのは、いずれも問題ないことを確認しました。

これは2つのモジュールが互いに影響してるんだな、と思い両者の仕様を見たところ…

それぞれUARTでESP32マイコンと通信してデータ送受信を行うもので、これが同じSerial2というUARTポートを使って競合していたのです。

Serial0に切り替えてみる

M5stack(厳密にはESP32マイコン)には、serial0, serial1, serial2の3つのUARTがあります。

UARTを使うにはHardwareSerial.cppから番号指定して、begin()で設定という流れですね。

//GPSモジュールのサンプルコード抜粋
HardwareSerial GPS_s(2); //この引数と、後述するbegin関数の_uart_nrが等しい
GPS_s.begin(9600); //9600bps

begin関数ではswitch文でピン設定を行っています。

//begin関数一部抜粋
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd)
{
    if (!uartIsDriverInstalled(_uart)) {
        switch (_uart_nr) {
            case UART_NUM_0:
                if (rxPin < 0 && txPin < 0) rxPin = SOC_RX0; /*3*/  txPin = SOC_TX0; /*1*/
            break;
#if SOC_UART_NUM > 1                   // may save some flash bytes...
            case UART_NUM_1:
               if (rxPin < 0 && txPin < 0) {
                    rxPin = RX1; /*9*/  txPin = TX1; /*10*/
//                    rxPin = 2;  txPin = 5;
                }
            break;
#endif
#if SOC_UART_NUM > 2                   // may save some flash bytes...
            case UART_NUM_2:
               if (rxPin < 0 && txPin < 0) rxPin = RX2; /*16*/  txPin = TX2; /*17*/
            break;
#endif
        }
    }
//後段の処理...
}

で、よくよくGPSモジュールのマニュアルを見ると必要に応じて自分で配線を切り替えてください、と書いてるんですね。
※M5stack Fireでは16,17番ピンがPSRAMに割り当てられていることの対策です。

モジュールの基板を見たら、たしかに16,17を使っていて、半田の間に切欠きがありました。

そしてありがたいことに別ピンを近接配置してくれており、RXDを1、TXDに3をつなげばSerial0が使えそう!

ってことで早速カッターで16,17の間を切って、1,3をつなげます。

余談ですが日置電機のテスタを使って導通確認しています。安心、安全、高速、高精度で私の好きなメーカーです。

ソフト側もSerial0を指定して、いざ書き込み…ができない!

なんと、Serial0はUSBと共通の端子になっていたようで書き込みができない仕様だったのです!

後になって気づいて未確認ではありますが、たぶんSerial0自体は使えます。

Serial0に初期設定されている1,3番ピンがUSBと共通になっているだけなので、Serial0のピン配置を例えば、2,5番ピンに設定して動かすことはできるはず。

これは困った…Serial1につなぐとしてもソフト側初期指定の9,10番ピンは出てないし、GPSモジュールは5,13番ピンにしかつなげない…

結局何にもつながってないと思われる2,5番ピンを使ってSerial1で設定することにしました。

Serial1を使う

2,5番ピンを使う選択をしたものの、配線を自分でつなぐ必要がありました。

HardwareSerial.cppのbegin関数、UART_NUM_1部分のTXD,RXDのピン配置を指定しなおして、書込み…がまたできない!!

そこでモジュールを切り離して本体だけにしたところ…書き込みができました。

よく分かりませんが、2,5番ピンもUSBに影響を与えるようです。全く独立してる気がするがなぜ…?

結局ソフト書き込む際は毎回モジュールを外してから書き込んでます…。

まとめ

とりあえず結論としては下記のとおりとなります。

  • Serial0、Serial1, Serial2いずれも使用可(のはず、Serial0は未確認)
  • Serial0初期設定の1,3番ピンはUSBと共通端子になっていて書き込みエラーとなる
    (1,3番ピンを指定しなければSerial0も使えるはず、ピン指定はHardwareSerial.cppにて)
  • 2,5番ピンは独立GPIOのはずだが書き込みエラーとなる、書込み後の動作は問題なし

この内容が良いと思ったら、いいね💖を押して教えてください!

組みクラ – 組み込み開発を学び、未来を創るエンジニアへ
無料で学べる!組み込み開発の基礎から応用までをマスターできるオンラインスクール「組みクラ」

組み込みエンジニアは、あらゆる産業の基盤を支える重要な職業です。
私たちタテプロは、次世代の組み込みエンジニアを育成し、業界の競争力を高めるために活動しています。
あなたも、無料で学べる「組みクラ」で、組み込み開発のスキルをしっかり身につけ、キャリアを加速させましょう!
今すぐ学び始めて、将来の自分をステップアップさせる第一歩を踏み出しませんか?

\立プロとLINEで友だちになりませんか/
立プロと友だちになる
組み込み機器
シェアしていただけると嬉しいです!

コメント

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