改良前のプログラム
void LpIn() { if (digitalRead(1) == LOW) { DownOld[0] = DownNew[0]; //Lpの信号を保存 DownNew[0] = micros(); } else { UpOld[0] = UpNew[0]; UpNew[0] = micros(); } } void RsIn() { if (digitalRead(0) == LOW) { DownOld[1] = DownNew[1]; //Rsの信号を保存 DownNew[1] = micros(); } else { UpOld[1] = UpNew[1]; UpNew[1] = micros(); } } void ThIn() { if (digitalRead(2) == LOW) { DownOld[2] = DownNew[2]; //Thの信号を保存 DownNew[2] = micros(); } else { UpOld[2] = UpNew[2]; UpNew[2] = micros(); } } void FsIn() { if (digitalRead(3) == LOW) { DownOld[3] = DownNew[3]; //Fsの信号を保存 DownNew[3] = micros(); } else { UpOld[3] = UpNew[3]; UpNew[3] = micros(); } } int Angle(byte i) { //受信した信号からサーボ角度を計算する関数 if (UpNew[i] <= DownNew[i]) { //もしDownNewの更新が新しかったら{}内を実行 Val[i] = ((((DownNew[i] - UpNew[i]) * 10000) / ((UpNew[i] - UpOld[i])) * 0.01) - 6) * 22.25; } else { //もしUpNewの更新が新しかったら{}内を実行 Val[i] = ((((DownNew[i] - UpOld[i]) * 10000) / (UpNew[i] - UpOld[i]) * 0.01) - 6) * 22.25; } return Val[i]; }
改良後のプログラム その①
割り込み処理ルーチンについてですが、unsigned long Tdmy;なる変数を定義しておいて、
void LpIn(){Tdmy=micros(); if(digitalRead(1)==LOW){DownOld[0]=DownNew[0];DownNew[0]=Tdmy;}else{UpOld[0]=UpNew[0];UpNew[0]=Tdmy;}}
のようにすると、時間を計る精度が、ちょっとだけ良くなるかもしれません。
サーボのブルブルとは関係ないかもしれませんが。。。
void LpIn() { if (digitalRead(1) == LOW) { DownOld[0] = DownNew[0]; //Lpの信号を保存 DownNew[0] = micros(); } else { UpOld[0] = UpNew[0]; UpNew[0] = micros(); } } void RsIn() { if (digitalRead(0) == LOW) { DownOld[1] = DownNew[1]; //Rsの信号を保存 DownNew[1] = micros(); } else { UpOld[1] = UpNew[1]; UpNew[1] = micros(); } } void ThIn() { if (digitalRead(2) == LOW) { DownOld[2] = DownNew[2]; //Thの信号を保存 DownNew[2] = micros(); } else { UpOld[2] = UpNew[2]; UpNew[2] = micros(); } } void FsIn() { if (digitalRead(3) == LOW) { DownOld[3] = DownNew[3]; //Fsの信号を保存 DownNew[3] = micros(); } else { UpOld[3] = UpNew[3]; UpNew[3] = micros(); } }
時間を測る精度は測れていませんが、見た感じサーボのブルブル同じぐらいでした。
改良後のプログラム その②
void LpIn(){
if(digitalRead(1)==LOW){DownOld[0]=DownNew[0];DownNew[0]=micros(); LastIR[0]=0;}
else{UpOld[0]=UpNew[0];UpNew[0]=micros(); LastIR[0]=1;}} //Lpの信号を保存
void RsIn(){
if(digitalRead(0)==LOW){DownOld[1]=DownNew[1];DownNew[1]=micros(); LastIR[1]=0;}
else{UpOld[1]=UpNew[1];UpNew[1]=micros(); LastIR[1]=1;}} //Rsの信号を保存
void ThIn(){
if(digitalRead(2)==LOW){DownOld[2]=DownNew[2];DownNew[2]=micros(); LastIR[2]=0;}
else{UpOld[2]=UpNew[2];UpNew[2]=micros(); LastIR[2]=1;}} //Thの信号を保存
void FsIn(){
if(digitalRead(3)==LOW){DownOld[3]=DownNew[3];DownNew[3]=micros(); LastIR[3]=0;}
else{UpOld[3]=UpNew[3];UpNew[3]=micros(); LastIR[3]=1;}} //Fsの信号を保存
Angle()関数の書き直し、(ここ重要!)
int Angle(byte i) { //受信した信号からサーボ角度を計算する関数
const unsigned long cntLim = 4294967295; //32ビットの限界の値
unsigned long PW0 , PW1;
if(UpNew[i] >= UpOld[i]){ // 通常の状態なら
PW0 = UpNew[i] - UpOld[i];
}
else{
PW0 = cntLim- UpOld[i]; PW0 += UpNew[i]+1;
}
if( LastIR[i] ==0 ){ // DownNewが最も新しいなら
if(DownNew[i] >= UpNew[i]){ // 通常の状態なら
PW1 = DownNew[i] - UpNew[i];
}
else{
PW1 = cntLim- UpNew[i]; PW1 += DownNew[i]+1;
}
else{ // UpNewが最も新しいなら
if(DownNew[i] >= UpOld[i]){ // 通常の状態なら
PW1 = DownNew[i] - UpOld[i];
}
else{
PW1 = cntLim- UpOld[i]; PW1 += DownNew[i]+1;
}
}
PW1 *= 10000;
Val[i]=(PW1/PW0-600)*2225/10000;
return Val[i];
}
void LpIn() { Tdmy = micros(); //○ if (digitalRead(1) == LOW) { DownOld[0] = DownNew[0]; DownNew[0] = Tdmy; LastIR[0] = 0; } else { UpOld[0] = UpNew[0]; UpNew[0] = Tdmy; LastIR[0] = 1; } } void RsIn() { Tdmy = micros(); //○ if (digitalRead(0) == LOW) { DownOld[1] = DownNew[1]; DownNew[1] = Tdmy; LastIR[1] = 0; } else { UpOld[1] = UpNew[1]; UpNew[1] = Tdmy; LastIR[1] = 1; } } void ThIn() { Tdmy = micros(); //○ if (digitalRead(2) == LOW) { DownOld[2] = DownNew[2]; DownNew[2] = Tdmy; LastIR[2] = 0; } else { UpOld[2] = UpNew[2]; UpNew[2] = Tdmy; LastIR[2] = 1; } } void FsIn() { Tdmy = micros(); //○ if (digitalRead(3) == LOW) { DownOld[3] = DownNew[3]; DownNew[3] = Tdmy; LastIR[3] = 0; } else { UpOld[3] = UpNew[3]; UpNew[3] = Tdmy; LastIR[3] = 1; } } int Angle(byte i) { //受信した信号からサーボ角度を計算する関数 //○ const unsigned long cntLim = 4294967295; //32ビットの限界の値 //○ unsigned long PW0 , PW1; //○ if (UpNew[i] >= UpOld[i]) { // 通常の状態なら //○ PW0 = UpNew[i] - UpOld[i]; //○ } else { //○ PW0 = cntLim - UpOld[i]; PW0 += UpNew[i] + 1; //○ } //○ if ( LastIR[i] == 0 ) { // DownNewが最も新しいなら //○ if (DownNew[i] >= UpNew[i]) { // 通常の状態なら //○ PW1 = DownNew[i] - UpNew[i]; //○ } else { //○ PW1 = cntLim - UpNew[i]; PW1 += DownNew[i] + 1; //○ } //○ } else { // UpNewが最も新しいなら //○ if (DownNew[i] >= UpOld[i]) { // 通常の状態なら //○ PW1 = DownNew[i] - UpOld[i]; //○ } else { //○ PW1 = cntLim - UpOld[i]; PW1 += DownNew[i] + 1; //○ } //○ } //○ PW1 *= 10000; //○ Val[i] = (PW1 / PW0 - 600) * 2225 / 10000; //○ return Val[i]; //○ } //○
改良後のプログラム その③
Angle()関数の、さらに、書き直し、(ここも重要!)
int Angle(byte i) { //受信した信号からサーボ角度を計算する関数
const unsigned long cntLim = 4294967295; //32ビットの限界の値
unsigned long PW0 , PW1;
if(UpNew[i] >= UpOld[i]){ // 通常の状態なら
PW0 = UpNew[i] - UpOld[i];
}
else{
PW0 = cntLim- UpOld[i]; PW0 += UpNew[i]+1;
}
if( LastIR[i] ==0 ){ // DownNewが最も新しいなら
if(DownNew[i] >= UpNew[i]){ // 通常の状態なら
PW1 = DownNew[i] - UpNew[i];
}
else{
PW1 = cntLim- UpNew[i]; PW1 += DownNew[i]+1;
}
PW1 *= 10000;
Val[i]=(PW1/PW0-600)*2225/10000;
else{ // UpNewが最も新しいなら
// Angleの値は更新せずに、1つ前のVal[i]を戻り値にする。
}
return Val[i];
}
void LpIn() { Tdmy = micros(); //○ if (digitalRead(1) == LOW) { DownOld[0] = DownNew[0]; DownNew[0] = Tdmy; LastIR[0] = 0; } else { UpOld[0] = UpNew[0]; UpNew[0] = Tdmy; LastIR[0] = 1; } } void RsIn() { Tdmy = micros(); //○ if (digitalRead(0) == LOW) { DownOld[1] = DownNew[1]; DownNew[1] = Tdmy; LastIR[1] = 0; } else { UpOld[1] = UpNew[1]; UpNew[1] = Tdmy; LastIR[1] = 1; } } void ThIn() { Tdmy = micros(); //○ if (digitalRead(2) == LOW) { DownOld[2] = DownNew[2]; DownNew[2] = Tdmy; LastIR[2] = 0; } else { UpOld[2] = UpNew[2]; UpNew[2] = Tdmy; LastIR[2] = 1; } } void FsIn() { Tdmy = micros(); //○ if (digitalRead(3) == LOW) { DownOld[3] = DownNew[3]; DownNew[3] = Tdmy; LastIR[3] = 0; } else { UpOld[3] = UpNew[3]; UpNew[3] = Tdmy; LastIR[3] = 1; } } int Angle(byte i) { //受信した信号からサーボ角度を計算する関数 //○○ const unsigned long cntLim = 4294967295; //32ビットの限界の値 //○○ unsigned long PW0 , PW1; //○○ if (UpNew[i] >= UpOld[i]) { // 通常の状態なら //○○ PW0 = UpNew[i] - UpOld[i]; //○○ } else { //○○ PW0 = cntLim - UpOld[i]; PW0 += UpNew[i] + 1; //○○ } //○○ if ( LastIR[i] == 0 ) { // DownNewが最も新しいなら //○○ if (DownNew[i] >= UpNew[i]) { // 通常の状態なら //○○ PW1 = DownNew[i] - UpNew[i]; //○○ } else { //○○ PW1 = cntLim - UpNew[i]; PW1 += DownNew[i] + 1; //○○ } //○○ PW1 *= 10000; //○○ Val[i] = (PW1 / PW0 - 600) * 2225 / 10000; //○○ } else { // UpNewが最も新しいなら //○○ // Angleの値は更新せずに、1つ前のVal[i]を戻り値にする。 //○○ } //○○ return Val[i]; //○○ } //○○
半分無視して計算式を統一する方法が一番効くかと思いましたが、これも残念ながら改良前と同じ位でした。
改良後のプログラム その④(2016.08.01追記)
また提案ですが、Angel( );関数を実行している間、割り込みを禁止することはできないでしょうか?
計算している最中にもとになる値が更新されてしまうとマズいことになりそうな気がします。
int Angle(byte i) { //受信した信号からサーボ角度を計算する関数 noInterrupts();//〇 if (UpNew[3] <= DownNew[i]) { //もしDownNewの更新が新しかったら{}内を実行 Val[i] = ((((DownNew[i] - UpNew[3]) * 10000) / ((UpNew[3] - UpOld[i])) * 0.01) - 6) * 22.25; } else { //もしUpNewの更新が新しかったら{}内を実行 Val[i] = ((((DownNew[i] - UpOld[i]) * 10000) / (UpNew[i] - UpOld[i]) * 0.01) - 6) * 22.25; } interrupts(); return Val[i]; }