LoginSignup
alyn
@alyn

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

digitalWrite()とSerial1.write()の切り替えについて

Q&AClosed

実現したいこと

Arduino DueでdigitalWrite()とSerial1.write()の切り替えをしたいです。
しかしdigitalWrite()からSerial1.write()を実行すると正しくシリアル通信をすることができません。
シリアルデータを送信すると1回目の送信には成功しますが、2回目以降は0が送信されてしまいます。
ちなみにArduino Megaでは切り替えをすることができていて、通信することができます。
原因と下記の理想の受信データにする方法を教えていただきたいです。
※この対象Dueの通信相手は別DueのSerial1のtx/rxで、その別DueはSerial1で受信したデータをそのまま16進数でUSBケーブルで接続したPCのシリアルモニタに送っています。

該当のソースコード

void setup() {
    const byte txData[6] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };

    //Serial1.write (1回目)
    Serial1.begin(9600);
    Serial1.write(txData, 6);
    Serial1.end();
    delay(1000);

    //digitalWrite
    pinMode(18, OUTPUT);
    digitalWrite(18, LOW);
    delay(50);
    digitalWrite(18, HIGH);
    delay(100);

    //Serial1.write (2回目以降)
    for(byte i = 0; i < 5; i++)
    {
        Serial1.begin(9600);
        Serial1.write(txData, 3);
        Serial1.flush();
        Serial1.end();
        delay(1000);
    }
}

void loop() {
    
}

シリアルモニタ(理想の受信データ)

AA BB CC DD EE FF
AA BB CC
AA BB CC
AA BB CC
AA BB CC
AA BB CC

シリアルモニタ(実際の受信データ)

AA BB CC DD EE FF
00

接続図

無題.png

補足情報

【Arduino Due】
https://store-usa.arduino.cc/collections/boards/products/arduino-due
https://content.arduino.cc/assets/A000056-full-pinout.pdf

【データシート】
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf

マルチポスト

https://teratail.com/questions/h3km9w6nkmhjgm
https://qiita.com/alyn/questions/78d9963e81f53ab13f75
https://ja.stackoverflow.com/questions/91802/digitalwrite%e3%81%a8serial1-write%e3%81%ae%e5%88%87%e3%82%8a%e6%9b%bf%e3%81%88%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6

0

2Answer

ちなみにArduino Megaでは切り替えをすることができていて

こちらが謎ですが…

たぶんD18(TX)ではなくD19(RX)であればうまくいくと思います。
送信線側でdigitalWriteすると余計な信号も送信されるはずなので、回避策として
・受信側で変なデータが来た時に通信をリセットする
・電子回路にて通信線を切り替えるような回路を作る
などの対応が考えられると思います。

0Like

Comments

  1. @alyn

    Questioner
    UARTを利用した別の通信プロトコルにおいて、LOW信号を一定時間送信する必要があり、pinMode()とSerial1.begin()を切り替える処理が必要となります
  2. UARTを利用した別の通信プロトコルが何であるのかわかりませんが、Megaでも同様に特殊な通信をされていた?現在もDueにて別の通信プロトコルを使用して通信をしているという事でしょうか。

    オシロスコープを使用して通信波形の計測済みでしょうか?
  3. @alyn

    Questioner
    接続図のDueをMegaに置き換え、それぞれに同じプログラムを書き込んだ場合は問題なかったです。DueとMegaでは電圧が異なるので直接通信できないので、電圧変換のためにその別プロトコルのトランシーバーを挟んで使用しています。なのでビット単位で全く同じ信号を送信していますので、オシロスコープで波形を見た時にはUARTと同じ波形になるはずです。恐らくDueの入出力レジスタか何かのレジスタに原因があると思われます。
  4. > オシロスコープで波形を見た時にはUARTと同じ波形になるはずです
    なるはずですが、なっていないので出力が正しくないと思います。
    どのあたりで信号が正常では無い状態となっているのかまずはオシロスコープにて計測する事をお勧めします。

    内部レジスタが気になるという事であればこのあたりが参考になると思います。
    ただ、writeやflushの実行中に発生しているという事であればかなりわかりずらい。
    このArduinoコアプログラムを改修しなければならないかも。
    https://forum.arduino.cc/t/arduino-due-how-to-direrct-port-access/251656
    https://github.com/arduino/ArduinoCore-sam/blob/master/cores/arduino/UARTClass.cpp

    こちらの質問とは離れますが、ArduinoStudioではなくレジスタを直接操作しやすいAtmel Studioなどを使用した開発を検討されるのも一つの手段だと思います。

「digitalWrite(18, LOW); delay(50);」を「uint8_t Zero[1] = { 0 }; Serial1.begin(160); Serial1.write(Zero, 1);」に書き換えれば同じ動作をさせることができそうです。根本的な解決ではありませんが、これで解決にします。

0Like

Comments

Your answer might help someone💌