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

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

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

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

Q&A

1回答

319閲覧

esp32を使用してADXL345のデータを10ms毎で取得し、DHT11のデータ10sec毎に取得する方法

tanak4444

総合スコア0

Arduino

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

0グッド

1クリップ

投稿2024/02/14 08:34

実現したいこと

esp32を使用し、
ADXL345センターのデータを10ms毎、
DHT11センサー(5個)のデータ10sec毎に取得
取得時間の間隔ががずれないようにしたい

そのため、割り込み内でで重い処理ができないものか又はほかの方法で間隔がずれないようにできないものか

発生している問題・分からないこと

DHT11センサーのデータ取得に約20mかかってしまうためどうしてもADXL345の取得周期がずれてしまう。
タイマー割り込みを使用し、割り込み内でADXL345のデータ取得を行おうとするとesp32が再起動を繰返す状態となってしまう。
エラー「Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).」

該当のソースコード

//通信関連 #include <WiFiClientSecure.h> #include <MQTTClient.h> #include <ArduinoJson.h> #include "WiFi.h" //加速度センサ関連 #include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_ADXL345_U.h> /* Assign a unique ID to this sensor at the same time */ Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); //温湿度センサー関連 #include "DHTesp.h" //デファイン #define DHTPIN_1 15 // #define DHTPIN_2 4 // #define DHTPIN_3 18 // #define DHTPIN_4 19 // #define DHTPIN_5 23 // DHTesp dht; //変数 int publish_cnt; float temp_1 = 0; float hemi_1 = 0; float temp_2 = 0; float hemi_2 = 0; float temp_3 = 0; float hemi_3 = 0; float temp_4 = 0; float hemi_4 = 0; float temp_5 = 0; float hemi_5 = 0; unsigned long e_time; // ESP32からパブリッシュするMQTTトピック WiFiClientSecure net = WiFiClientSecure(); MQTTClient client = MQTTClient(256); #define OFF 0 #define ON 1 hw_timer_t * timer = NULL; volatile SemaphoreHandle_t timerSemaphore; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; //volatile uint32_t lastIsrAt = 0; char main_flag; int main_cnt; void(*resetFunc)(void) = 0; void IRAM_ATTR onTimer(){ portENTER_CRITICAL(&timerMux); if(++main_cnt >= 4){ main_cnt = 0; main_flag = 1; } portEXIT_CRITICAL(&timerMux); xSemaphoreGiveFromISR(timerSemaphore, NULL); } //加速度センサーセットアップ void accel_setup() { if(!accel.begin()) { /* There was a problem detecting the ADXL345 ... check your connections */ Serial.println("Ooops, no ADXL345 detected ... Check your wiring!"); while(1); } /* 測定範囲誤差の設定 */ //accel.setRange(ADXL345_RANGE_16_G); // // accel.setRange(ADXL345_RANGE_8_G); // // accel.setRange(ADXL345_RANGE_4_G); // accel.setRange(ADXL345_RANGE_2_G); } //温湿度センサーデータ取得+データ送信 void publishMessage() { if(++publish_cnt >= 1000){ //10ms毎カウント publish_cnt = 0; Serial.print("DHT11_1 "); Serial.print(temp_1);Serial.print("℃ ");Serial.print(hemi_1);Serial.print("% "); //DHT11_2~5も同様 } switch(publish_cnt){ case(991):{ dht.setup(DHTPIN_1,DHTesp::DHT11); TempAndHumidity newValues = dht.getTempAndHumidity(); if (dht.getStatus() != 0) { Serial.println("DHT11 error status: " + String(dht.getStatusString())); } temp_1 = newValues.temperature; hemi_1 = newValues.humidity; break; } case(993):{ dht.setup(DHTPIN_2,DHTesp::DHT11); TempAndHumidity newValues = dht.getTempAndHumidity(); if (dht.getStatus() != 0) { Serial.println("DHT11 error status: " + String(dht.getStatusString())); } temp_2 = newValues.temperature; hemi_2 = newValues.humidity; break; } case(995):{ dht.setup(DHTPIN_3,DHTesp::DHT11); TempAndHumidity newValues = dht.getTempAndHumidity(); if (dht.getStatus() != 0) { Serial.println("DHT11 error status: " + String(dht.getStatusString())); } temp_3 = newValues.temperature; hemi_3 = newValues.humidity; break; } case(997):{ dht.setup(DHTPIN_4,DHTesp::DHT11); TempAndHumidity newValues = dht.getTempAndHumidity(); if (dht.getStatus() != 0) { Serial.println("DHT11 error status: " + String(dht.getStatusString())); } temp_4 = newValues.temperature; hemi_4 = newValues.humidity; break; } case(999):{ dht.setup(DHTPIN_5,DHTesp::DHT11); TempAndHumidity newValues = dht.getTempAndHumidity(); if (dht.getStatus() != 0) { Serial.println("DHT11 error status: " + String(dht.getStatusString())); } temp_5 = newValues.temperature; hemi_5 = newValues.humidity; break; } default : break; } //加速度センサーデータ取得 sensors_event_t event; accel.getEvent(&event); Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print(" "); Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" "); Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print(" ");Serial.println("m/s^2 "); } void setup() { Serial.begin(115200); //加速度センサー accel_setup(); portENTER_CRITICAL(&timerMux); //タイマー timerSemaphore = xSemaphoreCreateBinary(); timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &onTimer, true); timerAlarmWrite(timer, 2500, true); //1ms=1000 2.5ms = 2500 timerAlarmEnable(timer); publish_cnt = 1000; main_cnt = 0; main_flag = 0; portEXIT_CRITICAL(&timerMux); } void loop() { if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){ }//1ms動作 if(main_flag == 1){ main_flag = 0; e_time = millis(); Serial.print(e_time); publishMessage(); client.loop(); } }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

割り込みに関して以下のような記事を調べたりしているが割り込み内で重い処理をするようなものを発見できていない
https://lang-ship.com/blog/work/esp32-timer/

補足

使用しているボード:ESP32-WROOM-32
使用している開発環境:Arduino IDE ver2.2.1

貼り付けているソースコードは、センサー部分のみにしているため
コピペしただけでは動かない可能性があります。

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

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

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

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

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

guest

回答1

0

I2Cのライブラリが割り込みを使うために、割り込みハンドラ中ではI2Cへのアクセスが動作しない(止まってしまってWDTでリセット)、ということのような気がします。

大丈夫という自信を持てるのなら多重割り込みを許可するとか、
あるいはESP32が2コアなのですから、センサーの処理を二つのコアにそれぞれ割り振るとか
という手段はとれないのでしょうか。

(自分で実験はしていませんが...)

投稿2024/02/14 11:13

thkana

総合スコア7723

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

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

tanak4444

2024/02/15 01:44

回答ありがとうございます。 多重割込みやコアの振り分けを試してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

アカウントをお持ちの方は

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問