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

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

新規登録して質問してみよう
ただいま回答率
87.20%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

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

解決済

M5StackC-Plusに書込んだスケッチの挙動が「書込みに使用したPCにより異なる」原因と対策をご教示願います。

Yasu0421
Yasu0421

総合スコア27

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

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

1回答

0評価

0クリップ

295閲覧

投稿2022/06/09 12:34

質問の内容

先ず、以下のタイミングチャートに従って動作するスケッチを作成してみました。
イメージ説明

①は500mSec毎に定期的にデータが送信されてくるUART(1線式)信号です。
②は①の信号変化(エッジ)を検知したら、割込みを発生する「信号割込み」です。
③は②の信号割込みのタスクとして「1mSec毎のタイマー割込み」を始動します。また、タイマー始動後は②の信号割込みを一旦、停止させます
④は③によるカウンターとなります
⑤は①の500mSec毎の定期通信の合間を狙って、UART信号にWrite信号を重畳させる為に④のカウンタが40になったらイネーブル(ゲートオープン)出力するようにしています
⑥は⑤の信号がイネーブルになった後、④のカウンタ値が41になったらシリアルライトコマンドを発行します。
⑦は⑥によって出力される「ライトデータ信号」で、その出力時間は通信速度とライトするバイト数に依存して変化しますが、ここでは10mSecの時間データが出力されている場合と仮定しています。(つまり、⑦のWriteData信号が出力されている時間分だけ、⑤のゲートを開いておく)

最後に、処理するタスク時間によりカウンタの時間もずれてくるため、約10秒間隔で②の信号割込みを有効化しタイミングの整合性を保持しています。この10秒と言う時間も別カウンターでカウントしたエイヤ的な時間です

発生している問題

さて、作成したスケッチは無事コンパイルも完了し、M5StickCPlusへの書き込みもできたのですが、書き込みに使用したPCに依存して、期待通りの動作を行ってくれるものもあれば、エラーを発生するモノもあるといった少々理解しがたい現象が発生しております。

エラーメッセージ(書込みに使用したPC1の例)

M5StickCPlus initializing.... OK E (633) ledc: freq_hz=0 duty_resolution=13 E (633) ledc: ledc_get_freq(533): LEDC is not initialized

エラーメッセージ(書込みに使用したPC2の例)

21:02:53.370 -> Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1). 21:02:53.417 -> 21:02:53.417 -> Core 1 register dump: 21:02:53.466 -> PC : 0x4008aa30 PS : 0x00060a35 A0 : 0x80089ca2 A1 : 0x3ffbee1c 21:02:53.551 -> A2 : 0x3ffb8a00 A3 : 0x3ffb8890 A4 : 0x00000004 A5 : 0x00060a23 21:02:53.633 -> A6 : 0x00060a23 A7 : 0x00000001 A8 : 0x3ffb8890 A9 : 0x00000018 21:02:53.748 -> A10 : 0x3ffb8890 A11 : 0x00000018 A12 : 0x00000004 A13 : 0x00060a23 21:02:53.832 -> A14 : 0x007bef78 A15 : 0x003fffff SAR : 0x00000007 EXCCAUSE: 0x00000006 21:02:53.917 -> EXCVADDR: 0x00000000 LBEG : 0x40086729 LEND : 0x40086739 LCOUNT : 0xfffffffd 21:02:54.050 -> Core 1 was running in ISR context: 21:02:54.050 -> EPC1 : 0x400dfc1b EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x00000000 21:02:54.136 -> 21:02:54.136 -> 21:02:54.136 -> Backtrace:0x4008aa2d:0x3ffbee1c |<-CORRUPTED 21:02:54.183 -> 21:02:54.183 -> 21:02:54.229 -> Core 0 register dump: 21:02:54.229 -> PC : 0x4008abb1 PS : 0x00060035 A0 : 0x800898cf A1 : 0x3ffbe8cc 21:02:54.324 -> A2 : 0x3ffbef78 A3 ⸮

そして、もう1つのPCでは、期待通りの動作している

実現したいこと

「M5StickCPlusへのスケッチ書き込みに使用するPC」に依存することなく、上記タイミングチャート通りに動作できるようにしたいです。

該当のソースコード

#include <M5StickCPlus.h> hw_timer_t * timer1 = NULL; int onemicro; unsigned long exe_time; int t_count=0; int synchro_count = 0; int loop_count = 0; bool data_flg = false; String hexdata(""); byte cmd[8] = {0xFF,0xFF,0x86,0x04,0x05,0x06,0x07,0x08}; void IRAM_ATTR interrupt(){ data_flg = true; loop_count = 0; detachInterrupt(digitalPinToInterrupt(0)); Serial.println("timerAlarmWrite is started......"); timerAlarmWrite(timer1, 1000, true); //1msec毎に実施 timerAlarmEnable(timer1); } void IRAM_ATTR onTimer() { char buf[16]; //「0xXX」なので終端含めて最低6byte byte get1bytedata; if(synchro_count == 10000){ //10秒毎に同期処理を実行 data_flg = false; loop_count = 0; timerAlarmDisable(timer1); //タイマーを停止する t_count = 0; synchro_count = 0; attachInterrupt(0,interrupt,CHANGE); }else if((t_count == 0)&& (synchro_count != 10000)){ digitalWrite(25, 1);//Writeゲートを閉じる t_count++; synchro_count++; }else if((t_count == 40)&& (synchro_count != 10000)){ digitalWrite(25, 0);//Writeゲートを開く t_count++; synchro_count++; }else if((t_count == 41)&& (synchro_count != 10000)){//Serial1ポートからWriteコマンド発行 Serial1.write(cmd,8); t_count++; synchro_count++; }else if((t_count == 51)&& (synchro_count != 10000)){//Writeデータの終了タイミング digitalWrite(25, 1);//OE off t_count++; synchro_count++; }else if((t_count == 100)&&(synchro_count != 10000)){//Serial1リード処理な if(Serial1.available()){ int availableNum = Serial1.available(); Serial.print("Serial Available return value = "); Serial.println(availableNum); for(int i = 0; i<16; i++){ get1bytedata = Serial1.read(); sprintf(buf,"0x%02X,",get1bytedata); hexdata.concat(buf); } Serial.print("HEXDATA = "); Serial.println(hexdata); Serial1.flush(); hexdata = ""; } t_count++; synchro_count++; }else if((t_count == 499)&& (synchro_count != 10000)){//同期処理 t_count=0; synchro_count++; }else{ t_count++; synchro_count++; } } void setup() { M5.begin(); Serial.begin(9600); Serial1.begin(9600, SERIAL_8N1, 0, 26); Serial2.begin(9600, SERIAL_8N1, 32, 33); pinMode(25, OUTPUT); digitalWrite(25, 1);//Writeゲートを閉じる onemicro =getApbFrequency()/1000000; timer1 = timerBegin(0, onemicro, true); timerAttachInterrupt(timer1, &onTimer, true); digitalWrite(GPIO_NUM_10, 1); attachInterrupt(0,interrupt,CHANGE); } void loop() { if((loop_count == 1000)&&(data_flg==false)){//ハード割込みが発生してこない場合の対応 detachInterrupt(digitalPinToInterrupt(0)); timerAlarmDisable(timer1); //タイマーを停止する Serial.println(); Serial.println("Communication signal not available....."); attachInterrupt(0,interrupt,CHANGE); loop_count=0; String hexdata(""); }else{ loop_count++; } }

尚、上記動作確認のために、もう1個M5StickCPlusを用意し、GPIO33からシリアルデータを500mSec毎に出力させるスケッチを作成し、上記タイミングチャートのUART信号としております。

試したこと

Arduino-IDEの環境設定や、インストールライブラリを全PCで統一させてりしましたが、変化はありませんでした。

・ボードに書き込まれた内容は同じはずなのに「書込みに使用したPCにより動作しない場合がある」とう現象自体が理解できないので、原因を知りたく存じます。
・このような割込み処理プログラムの使い方自体が間違っているのでしょうか(逆に正常に動いているということ自体が奇跡であり、たまたま動作しているだけ?)

原因と対策をご教示いただけないでしょうか?
どうぞよろしくお願い致します。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

thkana

2022/06/09 13:12

> Arduino-IDEの環境設定や、インストールライブラリを全PCで統一させてりしました 「確認しました」ではなく、具体的に観察された事実を記載してください。 とりあえずボードライブラリのバージョンを一番に疑うところと思います。 本件とは関係ない(症状が違う)とは思いますが、G0はブートモードの決定に関わるため、入力端子として使用する(=外部からレベルが変更される)のは意図しない動作のもとになりそうに思います。
ozwk

2022/06/10 01:25

一応補足しておくと、9600bpsでは1文字送信するのに約1msかかります。
Yasu0421

2022/06/10 03:47

ご回答ありがとうございます。 回答表示が折りたたまれた状態で展開されておらず、気が付きませんでした。 申し訳ございません。 一応、Serialコマンドや、Serial.print系などすべて削除してみてどうなるかも 確認したのですが、結果は変わらず・・・でした。
thkana

2022/06/10 04:54

ここは「回答」ではなくて「質問への追記・修正の依頼」の欄です。本来はこの欄への記入は質問者に「お知らせ」として通知されるはずなのですが、そこがteratailのシステム不具合でスムーズにいかないようですね。 別にSerial.printの類が今回の現象の原因だなんて言ってません。それはそれとしてダメだというだけです。 Serialの話はともかくとして、 あなたがそれぞれのPCについて確認した項目とその結果はどうだったのでしょう。
Yasu0421

2022/06/10 07:00

「ダメだということです」も踏まえて、外してみて確認したという事をいいたかったのですが、 ここに書くべきことでなかったらならば、失礼しました。
thkana

2022/06/11 08:03

結局「PC間の違いの何を確認してどうだったか」の話は無し? まぁいいや。では、ばっさりと全部... 正常に動いている(と思われる)PC(Windowsということで良いかしら?)の "C:\Users\ユーザー名\AppData\Local\Arduino15\packages\esp32" で、他のPCの同ディレクトリを置き換えてからコンパイル/書き込みしたらどうなるかしら。(そこにコンパイラや設定一式が入っています) 一応、現状データは他の場所に逃がすなどして戻せるようにしておくことを推奨しますが、特に手をいれていないのならボードライブラリを一旦削除してインストールしなおし(あるいはバージョンを一旦ロールバックしてから最新に戻す)すれば通常状態には復帰するので神経質になることもないと思います。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

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