質問の内容
先ず、以下のタイミングチャートに従って動作するスケッチを作成してみました。
①は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により動作しない場合がある」とう現象自体が理解できないので、原因を知りたく存じます。
・このような割込み処理プログラムの使い方自体が間違っているのでしょうか(逆に正常に動いているということ自体が奇跡であり、たまたま動作しているだけ?)
原因と対策をご教示いただけないでしょうか?
どうぞよろしくお願い致します。

回答1件
あなたの回答
tips
プレビュー