ロボット工作研究室のWikiです。マシンデータなどを公開しています。

#define TABLESIZE 128 //2の乗数であること
#define SUBBIT    8
#define SUBINDEX  (1 << SUBBIT)
#define I_PI      (TABLESIZE * SUBINDEX * 2)
#define I_HPI     (TABLESIZE * SUBINDEX)

#define PI 3.1415926f

//int(sin(index / (pi / 2) * 128) * 65535 + 0.5)
const unsigned short sin_table[] = {
    0,   804,  1608,  2412,  3216,  4019,  4821,  5623, 
 6424,  7223,  8022,  8820,  9616, 10411, 11204, 11996, 
12785, 13573, 14359, 15142, 15924, 16703, 17479, 18253, 
19024, 19792, 20557, 21319, 22078, 22834, 23586, 24334, 
25079, 25820, 26557, 27291, 28020, 28745, 29465, 30181, 
30893, 31600, 32302, 32999, 33692, 34379, 35061, 35738, 
36409, 37075, 37736, 38390, 39039, 39682, 40319, 40950, 
41575, 42194, 42806, 43411, 44011, 44603, 45189, 45768, 
46340, 46905, 47464, 48014, 48558, 49095, 49624, 50145, 
50659, 51166, 51664, 52155, 52638, 53113, 53580, 54039, 
54490, 54933, 55367, 55794, 56211, 56620, 57021, 57413, 
57797, 58171, 58537, 58895, 59243, 59582, 59913, 60234, 
60546, 60850, 61144, 61429, 61704, 61970, 62227, 62475, 
62713, 62942, 63161, 63371, 63571, 63762, 63943, 64114, 
64276, 64428, 64570, 64703, 64826, 64939, 65042, 65136, 
65219, 65293, 65357, 65412, 65456, 65491, 65515, 65530, 
65535, 0
};

float mysin(float x){
    long ix, subix, sign, tval;
    
    ix = (int)(x * (I_PI / PI));   //単位変換
    sign = ix & I_PI;              //第3,第4象限である
    ix &= (I_PI - 1);              //第1,第2象限に限定
    if(ix > I_HPI) ix = I_PI - ix; //第1象限に限定
    
    subix = ix & (SUBINDEX - 1);   //線形補完に用いるサブインデックス
    ix >>= SUBBIT;                 //テーブル番号に変換
    
    //線形補完
    tval = ((long)sin_table[ix]   * (SUBINDEX - subix)
          + (long)sin_table[ix+1] * subix);
    
    return (sign ? -tval : tval) / (SUBINDEX * 65535.f);
}

マイコンでの動作に適した高速・コンパクトな三角関数です。
技術的な背景などはこちらのページが参考になります。

ROM消費量をできるだけ減らし、高速かつ、そこそこの精度を目指して作ってみました。
128個のテーブル間を256分割して線形補完します。要は512角形で近似しています。
ROM節約と高速化のため、テーブルに格納する値を16bit整数としています。
浮動小数点計算は2回、条件分岐も可能な限り減らしました。
コンパイラによる最適化を前提として、定数同士の演算はそのまま残してあります。

STM32で64MHz、GCCで-Osで最適化した時の処理時間は約7us、ROM消費量は約350Byteとなりました。
最大誤差は0.00005ぐらいでした。

テーブルのビット数を上げるか、配列数を増やせばもう少し精度は向上するでしょう。
ROM消費量は増えますが・・・
あと、最初の式の"PI"を"180.f"に置き換えると度数法にできます。

あ、ちなみに整数乗算器を持った32bitマイコン向けですので、あしからず。




 
×

この広告は60日間更新がないwikiに表示されております。

管理人のみ編集できます