質問: 0.97 * valueOld + 0.03 * value[i];//フィルタ係数を0.97とし、eNowへ書き出す valueOld=eNow;//書き出し終了後、次回処理へ向けてeNowを更新しておく Serial.println(eNow);//eNowの結果をプリントする } Serial.println("end");//400個のRCフィルタを完了し、ループ関数が1セットしたことをendでプリントして知らせる } ![イメージ説明](https://teratail.storage.googleapis.com/uploads/contributed_images/bfed353e7705044bb5648c1f858fee81.jpeg) ![イメージ説明](https://teratail.storage.googleapis.com/uploads/contributed_images/090b3f04e5715f24b4d982d3aad4dd3d.png) 進捗として上記のプログラムでRCフィルタをかけたものが以上のグラフとなっております。
回答: > > MVn = MVn-1 + ΔMVn > > ΔMVn = Kp(en-en-1) + Ki en + Kd((en-en-1) - (en-1-en-2)) > > MVn、MVn-1:今回、前回操作量 ΔMVn:今回操作量差分 > > en,en-1,en-2:今回、前回、前々回の偏差 > > > から順序立てて考えてみます。 まずこの操作は逐次行うものなので ``` for (int i = 0; i < 400; i++){ // ループ処理 for文以下の処理を400回繰り返す value[i] = analogRead(A0);//iの要素をA0から流れる電圧の値に設定し、読み取る delay(5);//5msec間隔で電圧を記録していく } ``` の中に書いていきます。 やりたいことはモーターの操作量`MVn`を求めて実際に出力することなので ``` MVn = ... analogWrite(10, MVn); ``` `MVn`は `MVn = MVn-1 + ΔMVn`で求めたいわけですが、 操作量の履歴は今回必要なく、前回値は`MVn`の更新にしか使わないので、 ``` dMV = ... MV += dMV; analogWrite(10, MV); ``` で済みますね。 みたいな感じで何を次のループに持ち越す/持ち越さないを決めていくと だいたいこんな感じになるはずです。 ``` float Kp = 1.0; // とりあえずP制御 float Ki = 0.0; float Kd = 0.0; int vo = 150; float e_0 = 0; // 配列でもいい float e_1 = 0; float e_2 = 0; flaot MV = 0; for (int i = 0; i < 400; i++){ int v = analogRead(A0); e_0 = (float)(vo - v); dMV = Kp * (e_0 - e_1) + Ki * e_0 + Kd * ((e_0 - e_1) - (e_1 - e_2)); MV += dMV; analogWrite(10, MV); e_2 = e_1; e_1 = e_0; value[i] = v; delay(5); } ```