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

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

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

RTOS(リアルタイムOS)は、リアルタイムシステムのためのOSです。実時間システムや実時間OSとも呼ばれ、時間的な制限のある処理を行うための機能・特性を備えています。組み込みシステムの制御に多く用いられています。

Q&A

解決済

2回答

1382閲覧

【ESP32+RTOS】割り込み処理がうまくいきません

Uka

総合スコア28

RTOS

RTOS(リアルタイムOS)は、リアルタイムシステムのためのOSです。実時間システムや実時間OSとも呼ばれ、時間的な制限のある処理を行うための機能・特性を備えています。組み込みシステムの制御に多く用いられています。

0グッド

0クリップ

投稿2023/05/07 15:23

編集2023/05/07 15:54

実現したいこと

ESP32のFreeRTOS機能を使って「モーター制御」を行いながら「センシング+データ解析」を同時に行いたいと考えています(並列処理)

前提

モーター制御部分についてはスイッチを2つ用意し、スイッチが押されるたびに割り込み処理で速度や移動距離が変わることを想定しています。

マルチタスクの割り当て:
Task1: モーター制御+割り込み処理(速度または移動距離の切り替え)
Task2: センシング+データ解析

しかし現状では下記のプログラムにおいて、一方のスイッチを押すともう一方のスイッチも連動してしまう不具合が起こっています(速度スイッチを押すと速度も変わるが、同時に距離も変わってしまう)

該当のソースコード

C

1#include <freertos/FreeRTOS.h> 2#include "SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h" 3NAU7802 myScale; 4#include <SPI.h> 5 6volatile float Hz = 1000; //この変数は割り込み処理とモーター制御(osc_stdで共有) 7volatile float distance = 20; //この変数は割り込み処理とモーター制御(osc_stdで共有) 8int strain_level = 1; 9int Hz_level = 1; 10 11void distance_controll() { //移動距離を3段階で切替可能 12 if (strain_level == 0) { 13 distance = 10; 14 strain_level = 1; 15 delay(100); 16 } 17 else if (strain_level == 1) { 18 distance = 20; 19 strain_level = 2; 20 delay(100); 21 } 22 else if (strain_level == 2) { 23 distance = 30; 24 strain_level = 0; 25 delay(100); 26 } 27} 28 29void Hz_controll() { //速度を5段階で切替可能 30 if (Hz_level == 0) { 31 Hz = 1000; //速度1 32 Hz_level = 1; 33 delay(100); 34 } 35 else if (Hz_level == 1) { 36 Hz = 450; //速度2 37 Hz_level = 2; 38 delay(100); 39 } 40 else if (Hz_level == 2) { 41 Hz = 260; //速度3 42 Hz_level = 3; 43 delay(100); 44 } 45 else if (Hz_level == 3) { 46 Hz = 125; //速度4 47 Hz_level = 4; 48 delay(100); 49 } 50 else if (Hz_level == 4) { 51 Hz = 47; //速度5 52 Hz_level = 0; 53 delay(100); 54 } 55} 56 57// 割り込みハンドラ 58// IMPUT_PIN HIGH→LOW 59// 60void IRAM_ATTR switchON_dist() { 61 62 // 割り込みフラグ設定 63 interruptState_dist = 1; 64} 65 66void IRAM_ATTR switchON_hz() { 67 68 // 割り込みフラグ設定 69 interruptState_hz = 1; 70} 71 72void task1( void *param ) //モーター制御+割り込み処理 73{ 74 while ( 1 ) { 75 osc_std(); //モーター制御関数 76 if (interruptState_dist) { // 割り込み発生 77 if ((millis() - msTime_dist) > 50) { // 50ミリ秒以下の割り込みは無視する 78 distance_controll(); 79 osc_std(); 80 msTime_dist = millis(); // 割り込み時刻更新 81 } 82 interruptState_dist = 0; // 割り込みフラグOFF 83 } 84 85 if (interruptState_hz) { // 割り込み発生 86 if ((millis() - msTime_hz) > 50) { // 50ミリ秒以下の割り込みは無視する(チャタリング回避) 87 Hz_controll(); 88 osc_std(); 89 msTime_hz = millis(); // 割り込み時刻更新 90 91 } 92 interruptState_hz = 0; // 割り込みフラグOFF 93 } 94 delay(1); 95 } 96} 97 98void task2( void *param ) //センシング+データ解析 99{ 100 while ( 1 ) { 101//プログラム省略(センシング+データ解析部分) 102 delay(1); 103 } 104} 105 106void setup() 107{ 108 // ウォッチドッグタイマ無効 109 disableCore0WDT(); 110 111 Serial.begin(115200); 112 Wire.begin(); 113 delay(50); 114 115 pinMode(33, OUTPUT); //motor driver dir 116 pinMode(25, OUTPUT); //motor driver stp 117 pinMode(14, OUTPUT); //M0 118 pinMode(27, OUTPUT); //M1 119 pinMode(26, OUTPUT); //M2 120 pinMode(32, INPUT); // 121 pinMode(35, INPUT); // 122 pinMode(36, INPUT); //Hz 123 pinMode(39, INPUT); //distance 124 125 digitalWrite(14, LOW); 126 digitalWrite(27, HIGH); 127 digitalWrite(26, LOW); 128 129//荷重センサの初期化 130 if (myScale.begin() == false) 131 { 132 Serial.println("Scale not detected. Please check wiring. Freezing..."); 133 while (1); 134 } 135 Serial.println("Scale detected!"); 136 137 myScale.setGain(NAU7802_GAIN_128); //Gain can be set to 1, 2, 4, 8, 16, 32, 64, or 128. 138 myScale.setSampleRate(NAU7802_SPS_320); //Sample rate can be set to 10, 20, 40, 80, or 320Hz 139 140 myScale.calibrateAFE(); //Does an internal calibration. Recommended after power up, gain changes, sample rate changes, or channel changes. 141 142 /* create task */ 143 xTaskCreatePinnedToCore( task1, 144 "TASK1", /* タスクの入口となる関数名 */ 145 0x800, /* スタックサイズ */ 146 NULL, /* パラメータのポインタ */ 147 1, /* プライオリティ */ 148 NULL, /* ハンドル構造体のポインタ */ 149 1 ); /* 割り当てるコア (0/1) */ 150 151 xTaskCreatePinnedToCore( task2, 152 "TASK2", /* タスクの入口となる関数名 */ 153 0x800, /* スタックサイズ */ 154 NULL, /* パラメータのポインタ */ 155 0, /* プライオリティ */ 156 NULL, /* ハンドル構造体のポインタ */ 157 0 ); /* 割り当てるコア (0/1) */ 158 159 attachInterrupt(39, switchON_dist, FALLING); //移動距離スイッチを押したときに割り込み処理を実行 160 attachInterrupt(36, switchON_hz, FALLING); //速度スイッチを押したときに割り込み処理を実行 161 msTime_dist = millis(); 162 msTime_hz = millis(); 163} 164 165void loop() 166{ 167 delay(10); 168} 169 170void osc_std() { 171//省略(モーター駆動) 172} 173 174

試したこと(下記プログラム)

RTOSを使用せず、Task1の内容(モーター制御+割り込み)を単独で動作させることはできています(速度スイッチを押すと速度だけが変化し、距離スイッチを押すと移動距離だけが変化)

C

1//#include <freertos/FreeRTOS.h> 2//#include "SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h" 3//NAU7802 myScale; 4#include <SPI.h> 5 6volatile float Hz = 1000; //この変数は割り込み処理とモーター制御(osc_stdで共有) 7volatile float distance = 20; //この変数は割り込み処理とモーター制御(osc_stdで共有) 8int strain_level = 1; 9int Hz_level = 1; 10 11void distance_controll() { //移動距離を3段階で切替可能 12 if (strain_level == 0) { 13 distance = 10; 14 strain_level = 1; 15 delay(100); 16 } 17 else if (strain_level == 1) { 18 distance = 20; 19 strain_level = 2; 20 delay(100); 21 } 22 else if (strain_level == 2) { 23 distance = 30; 24 strain_level = 0; 25 delay(100); 26 } 27} 28 29void Hz_controll() { //速度を5段階で切替可能 30 if (Hz_level == 0) { 31 Hz = 1000; //速度1 32 Hz_level = 1; 33 delay(100); 34 } 35 else if (Hz_level == 1) { 36 Hz = 450; //速度2 37 Hz_level = 2; 38 delay(100); 39 } 40 else if (Hz_level == 2) { 41 Hz = 260; //速度3 42 Hz_level = 3; 43 delay(100); 44 } 45 else if (Hz_level == 3) { 46 Hz = 125; //速度4 47 Hz_level = 4; 48 delay(100); 49 } 50 else if (Hz_level == 4) { 51 Hz = 47; //速度5 52 Hz_level = 0; 53 delay(100); 54 } 55} 56 57// 割り込みハンドラ 58// IMPUT_PIN HIGH→LOW 59// 60void switchON_dist() { 61 62 // 割り込みフラグ設定 63 interruptState_dist = 1; 64} 65 66void switchON_hz() { 67 68 // 割り込みフラグ設定 69 interruptState_hz = 1; 70} 71 72 73void setup() 74{ 75 Serial.begin(115200); 76 Wire.begin(); 77 delay(50); 78 79 pinMode(33, OUTPUT); //motor driver dir 80 pinMode(25, OUTPUT); //motor driver stp 81 pinMode(14, OUTPUT); //M0 82 pinMode(27, OUTPUT); //M1 83 pinMode(26, OUTPUT); //M2 84 pinMode(32, INPUT); // 85 pinMode(35, INPUT); // 86 pinMode(36, INPUT); //Hz 87 pinMode(39, INPUT); //distance 88 89 digitalWrite(14, LOW); 90 digitalWrite(27, HIGH); 91 digitalWrite(26, LOW); 92 93 attachInterrupt(39, switchON_dist, FALLING); //移動距離スイッチを押したときに割り込み処理を実行 94 attachInterrupt(36, switchON_hz, FALLING); //速度スイッチを押したときに割り込み処理を実行 95 msTime_dist = millis(); 96 msTime_hz = millis(); 97} 98 99void loop() 100{ 101 osc_std(); //モーター制御関数 102 if (interruptState_dist) { // 割り込み発生 103 if ((millis() - msTime_dist) > 50) { // 50ミリ秒以下の割り込みは無視する 104 distance_controll(); 105 osc_std(); 106 msTime_dist = millis(); // 割り込み時刻更新 107 } 108 interruptState_dist = 0; // 割り込みフラグOFF 109 } 110 111 if (interruptState_hz) { // 割り込み発生 112 if ((millis() - msTime_hz) > 50) { // 50ミリ秒以下の割り込みは無視する(チャタリング回避) 113 Hz_controll(); 114 osc_std(); 115 msTime_hz = millis(); // 割り込み時刻更新 116 117 } 118 interruptState_hz = 0; // 割り込みフラグOFF 119 } 120} 121 122void osc_std() { 123//省略(モーター駆動) 124}

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

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

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

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

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

y_waiwai

2023/05/07 15:35

回路図を提示しよう
guest

回答2

0

私のてもとで以下のプログラムを走らせてGPIO36/39を叩いても

一方のスイッチを押すともう一方のスイッチも連動してしまう

という現象は出ません。

RTOSを使用せず

なんてことは不可能で結局内部でFreeRTOSは走っているわけで、「試したこと」のプログラムではむしろモーターを駆動していないことが効いているということはないでしょうか。
つまり、モーターのノイズが回り込んでいるとか。

Arduino

1volatile bool interruptState_dist; 2volatile bool interruptState_hz; 3volatile unsigned long msTime_dist; 4volatile unsigned long msTime_hz; 5 6// 割り込みハンドラ 7// IMPUT_PIN HIGH→LOW 8// 9void IRAM_ATTR switchON_dist() { 10 11 // 割り込みフラグ設定 12 interruptState_dist = 1; 13} 14 15void IRAM_ATTR switchON_hz() { 16 17 // 割り込みフラグ設定 18 interruptState_hz = 1; 19} 20 21void task1( void *param ) //モーター制御+割り込み処理 22{ 23 while ( 1 ) { 24 if (interruptState_dist) { // 割り込み発生 25 if ((millis() - msTime_dist) > 50) { // 50ミリ秒以下の割り込みは無視する 26 msTime_dist = millis(); // 割り込み時刻更新 27 Serial.print(millis()); 28 Serial.println("int_dist"); 29 } 30 interruptState_dist = 0; // 割り込みフラグOFF 31 } 32 33 if (interruptState_hz) { // 割り込み発生 34 if ((millis() - msTime_hz) > 50) { // 50ミリ秒以下の割り込みは無視する(チャタリング回避) 35 msTime_hz = millis(); // 割り込み時刻更新 36 Serial.print(millis()); 37 Serial.println("int_hz"); 38 } 39 interruptState_hz = 0; // 割り込みフラグOFF 40 } 41 delay(1); 42 } 43} 44 45void task2( void *param ) //センシング+データ解析 46{ 47 while ( 1 ) { 48//プログラム省略(センシング+データ解析部分) 49 delay(1); 50 } 51} 52 53void setup() 54{ 55 // ウォッチドッグタイマ無効 56 disableCore0WDT(); 57 58 Serial.begin(115200); 59 delay(50); 60 61 pinMode(36, INPUT); //Hz 62 pinMode(39, INPUT); //distance 63 64 /* create task */ 65 xTaskCreatePinnedToCore( task1, 66 "TASK1", /* タスクの入口となる関数名 */ 67 0x800, /* スタックサイズ */ 68 NULL, /* パラメータのポインタ */ 69 1, /* プライオリティ */ 70 NULL, /* ハンドル構造体のポインタ */ 71 1 ); /* 割り当てるコア (0/1) */ 72 73 xTaskCreatePinnedToCore( task2, 74 "TASK2", /* タスクの入口となる関数名 */ 75 0x800, /* スタックサイズ */ 76 NULL, /* パラメータのポインタ */ 77 0, /* プライオリティ */ 78 NULL, /* ハンドル構造体のポインタ */ 79 0 ); /* 割り当てるコア (0/1) */ 80 81 attachInterrupt(39, switchON_dist, FALLING); //移動距離スイッチを押したときに割り込み処理を実行 82 attachInterrupt(36, switchON_hz, FALLING); //速度スイッチを押したときに割り込み処理を実行 83 msTime_dist = millis(); 84 msTime_hz = millis(); 85} 86 87void loop() 88{ 89 delay(10); 90}

投稿2023/05/09 13:32

thkana

総合スコア7639

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

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

thkana

2023/05/09 13:33

ありゃ、リロードしないで放置してたら終わってたか。
Uka

2023/05/09 13:48

>thkanaさん プログラムの動作確認いただきありがとうございました。電源まわりのピン接続を間違えていたために誤動作していたようです。大変失礼いたしました。
guest

0

ベストアンサー

こういう場合にあるあるなのは、回路の接続をスカこいてうまく動かない、ってのが多いです。
いくらコードだけを見ても無駄でしかありません。
#例えばスイッチのプルアップ抵抗がないとか。。

で、スイッチ入力の割り込みを使う、ってのはちと筋が悪いです
チャタリングで余分な割り込みが発生したりしてませんか。
割り込みは使わないで、素直にポート入力でループ回しましょう

投稿2023/05/07 22:36

編集2023/05/07 23:12
y_waiwai

総合スコア87774

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

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

Uka

2023/05/09 11:20

ご回答ありがとうございます。 回路を再度確認したところ、おっしゃるとおり回路の接続(3.3Vで供給すべきところを5Vで接続してしまっていましまっていました)を間違えており、なおしたところRTOSのプログラムでも問題なく動作できました。ご指摘いただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問