質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

1回答

1190閲覧

Arduino Nano EveryのZIGBEE通信が初回だけ文字化けする

beginner_nano

総合スコア2

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2023/11/06 07:32

実現したいこと

  • Arduino Nano Everyと、ZIGBEE無線モジュールを使って、下記のような構成での状態監視を実現したいです。

Arduino Nano Every
↓(シリアル通信)
ZIGBEE無線子機

ZIGBEE無線親機

PC(モニタリング用)

質問の概要

Arduino Nano Every → ZIGBEE無線子機 のシリアル通信にて、
初回の通信のみ、データの一部が文字化けしてしまいます。
これを、初回も文字化けせずに送信できるようにしたいです。
(例)String型の"abcdefg"を送ると、初回のみ"X宴defg"となってしまう

なお、全く同じプログラムを、Arduinoファミリーである、
Arduino NANO、Arduino MEGA、Arduino UNOに書き込むと、
初回の通信でも文字化けは起こらず、正しく通信できるため、解決策がわからず、悩んでいます。

該当のソースコード

#include <SoftwareSerial.h> // ソフトウェアシリアルのライブラリ SoftwareSerial softwareSerialForZIGBEE(4,5); // ZIGBEE用に、IO4をRX, IO5をTXとして割り当て void setup() { } void loop() { String str = "abcdefg"; softwareSerialForZIGBEE.begin(38400); // ソフトウェアシリアル開始 softwareSerialForZIGBEE.println(str + str); softwareSerialForZIGBEE.end(); // ソフトウェアシリアル終了 delay(1000); }

モニタリング用PCで表示されるもの

X宴defgabcdefg abcdefgabcdefg abcdefgabcdefg ・ ・ ・ (Nano Everyをリセット) X宴defgabcdefg abcdefgabcdefg abcdefgabcdefg ・ ・ ・

初心者なりの考察

ソフトウェアシリアルによる、無線子機への書き込みは、
ソースコードの通り、文字列strを、「str+str」という形式としております。
同じ文字列strを使っているにも関わらず、初回roopの、前半のstrだけで、文字化けが起こっています。

また、roop毎に、ソフトウェアシリアルのbeginとendを入れていますが、
初回のroop以降は文字化けしません。

これらのことから、Nano Everyを起動した際、
ソフトウェアシリアルのバッファーに、既に余分なデータが入っており、
それが初回通信にて送信されてしまうのではないかと予想しています。

気になっていること

質問の概要の項目に記載しましたように、手元にあるArduinoファミリーでは、
Nano Everyのみで発生します。

また、Nano Everyにプログラムを書き込んだときのみ、
「avrdude: jtagmkII_initialize(): Cannot locate "flash" and "boot" memories in description」
という警告文が出ます。

Arduinoの公式サポートサイトには、この警告文について、
コンパイルと書き込みが正常に成功していれば、無視しても問題ないという旨の記載がされておりますが、
このエラーが出ないArduinoファミリーでは、通信に不具合が発生しないため、
気になっています。
https://support.arduino.cc/hc/en-us/articles/4405239282578-avrdude-jtagmkII-initialize-Cannot-locate-flash-and-boot-memories-in-description

補足情報

・PC側ではTera Termを使い、ボーレートを38400に設定
・使用しているArduino Nano Everyは、正規品かつ新品
・ZIGBEE無線機は、MONO WIRELESS社の製品を使用

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2023/11/06 12:38

本質ではないですけれど、SoftwareSerialをどうしても使いたいのですか? (他のArduino類と全く共通のソースで処理したいとか...) nano EveryならそのままでもHardware Serialをペリフェラル専用に使える(Serial1)はずなので、「ごまかし」のSoftware Serialを使わなきゃいけない理由はないはずです。
guest

回答1

0

ベストアンサー

とりあえず結論

nano Everyは、ボードライブラリとして(UNO r3等とは違って)megaAVRライブラリ(現時点でバージョンは1.8.8)を使用しています。
このライブラリのdigitalWrite関数は(UNO r3等とは違って)pinModeがOUTPUTでない場合、OUTレジスタを変更せずにPULL UPを設定するようになっています(328とかの動作を再現するためでしょう)。
一方、softwareSerialはTxが一瞬Lになることを防ぐため、先にdigtalWriteでピンをHにする(はずの)操作をしてからpinModeで出力にしています...UNO r3ならこれでよかったのですが、nano Everyの場合はこれが裏目に出て、TxピンがLになってしまい文字化けが発生する...ということのようです。

とりあえずgithubのmegaAVRのリポジトリにIssue & pull requestを投げておきましたので、いつか修正されるかも知れません。

(ちょっとそれだけでは説明しきれない振る舞いもある気がしますが...)


対策としては先の回答で有効だったんですが、理屈は違うみたい(ちょっと追跡中)

(最初の回答)

SoftwareSerialの内部での初期化をしてからTXのラインがHである時間が十分でなくて、1文字目の波形が正しく調歩同期のデータとして解釈されないようです。
とりあえず、

Arduino

1void setup(){ 2 pinMode(5,OUTPUT); 3 digitalWrite(5,HIGH); 4}

としてTxの初期状態をHに保ってやれば動きそうです。
(なんか昔同じネタでなにかハマったかすかな記憶が...)

もちろん、質問へのコメントにも書きましたが、ハードウェアSerialが余っているのならそちらを使うべきと思います。

なお、言わせていただければ送信毎にシリアルポートをopen/close(begin/end)するのはあまり「普通の使い方」とは言えない気がします。

投稿2023/11/06 13:31

編集2023/11/12 00:15
thkana

総合スコア7733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

beginner_nano

2023/11/07 01:00

答ありがとうございます。 いただいた情報をもとに、下記のようにソースコードを修正してみました。 ```Arduino #include <SoftwareSerial.h> // ソフトウェアシリアルのライブラリ SoftwareSerial softwareSerialForZIGBEE(4,5); // ZIGBEE用に、IO4をRX, IO5をTXとして割り当て void setup() { pinMode(5,OUTPUT); digitalWrite(5,HIGH); softwareSerialForZIGBEE.begin(38400); // ソフトウェアシリアル開始 } void loop() { String str = "abcdefg"; softwareSerialForZIGBEE.println(str + str); delay(1000); } ``` 修正後の通信結果としましては、下記のようになりました。 若干文字化け部分に変化がありましたが、解決にはいたっていない状況です。 ``` xX宴defgabcdefg abcdefgabcdefg abcdefgabcdefg ``` なお、参考情報としまして、 setup関数の末尾に、delay(1000);を追記しましたところ、 結果が下記のように変化しました。 ``` ・bcdefgabcdefg abcdefgabcdefg abcdefgabcdefg ``` ハードウェアシリアルではなく、ソフトウェアシリアルを使った理由としましては、 本番環境では、状態監視に使うその他パーツでもシリアル通信を使用するためです。 また、送信毎にopen/closeをするソースとなっていた理由としましては、 open後の初回送信が問題となるわけではなく、Nano Every起動後の初回送信のみで発生することを、 確認したかったためです。 記載漏れとなっており、申し訳ございません。
beginner_nano

2023/11/07 02:45

先ほどの参考情報に対して追記です。 void setup() { pinMode(5,OUTPUT); digitalWrite(5,HIGH); softwareSerialForZIGBEE.begin(38400); // ソフトウェアシリアル開始 } ① setup関数が上記のとき →「xX宴defgabcdefg」 ② ①のsetup関数末尾にdelay(1000);を追加したとき →「・bcdefgabcdefg」 ③ ①のsetup関数の先頭に、Serial.begin(115200);を追記したとき →「abcdefgabcdefg」 ③の場合において、正しい出力となりました!
thkana

2023/11/07 04:09

フルサイズのボードならICEつないでデバッグしたくなるような状況ですが...そっちはもう少し頑張るとして > その他パーツでもシリアル通信を使用する 実はnano EveryのマイコンはUARTを4ch積んでいるので、ちょちょいのちょいでUARTを増設できるようですね(実験していないので伝聞)。
beginner_nano

2023/11/07 05:59

センサー等のパーツを組み込んだ状態のプログラムにも、 ハードウェアシリアルのbeginと、ソフトウェアシリアルのbeginとの間に、 ピンの動作設定OUTPUTと、初期状態Highを追記したところ、 初回の通信から、文字化けせずに、正しいデータが送信できることが確認できました。 ご回答ありがとうございました。 ベストアンサーに設定させていただきます。 Nano EveryのマイコンがUARTを4chも積んでいるとは知りませんでした。
thkana

2023/11/07 14:38

なんかポートのdirレジスタをOUTにするときにdataレジスタがクリアされてるような気がするのだけれど、そんな動作あったかなぁ...(とりあえず仕様書をざっと見ただけだと見つからない)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問