Ардуино и арктангенс - время счета
Jan. 17th, 2021 06:06 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Я хочу использовать ардуино как основу для безконтактного джойстика на магнитометрах, а 3Д вычисления повесить на него же. Перед этим надо убедиться, что оно потянет вычисление несколько корней и арктангенсов за разумное время.
Для этого пишем примерный код -
#include "math.h";
byte b=0;
void setup() {
Serial.begin(9600);
}
void loop() {
double a;
unsigned long t=micros();
a=atan2(b,1)+atan2(1,b)+atan2(b,b)+atan2(1+b,1-b);
a=sqrt(a*a+1);
a=sqrt(a*a+2);
t=micros()-t;
Serial.print(t);
Serial.print('/');
Serial.println(a);
b=b+1;
delay(200);
}
Результат -
500/2.92
748/4.29
856/4.59
852/4.72
860/4.79
860/4.84
864/4.87
860/4.89
856/4.90
852/4.92
844/4.93
Т.е. не более миллисекунды, что более чем достаточно.
Теперь о точности - насколько приближенно 8-ми битный проц вычисляет аркангенс? Для этого с помощью дельфи создадим примерные массивы синусов и косинусов, чтобы скормить их ардуино и посмотреть, насколько точно оно восстановит значения -
procedure TForm1.Button1Click(Sender: TObject);
var a:integer;
ss,sc:string;
begin
ss:='';
sc:='';
for a:=0 to 9 do begin
ss:=ss+floattostr(sin(a*10/180*pi))+',';
sc:=sc+floattostr(cos(a*10/180*pi))+',';
end;
form1.Memo1.Lines.Add('double ss[]={'+ss+'};');
form1.Memo1.Lines.Add('double sc[]={'+sc+'};');
end;
С помощью полученных строк с массивами пишем примерный код для ардуино -
#include "math.h";
double ss[]={0,0.17364817766693,
0.342020143325669,0.5,
0.642787609686539,0.766044443118978,
0.866025403784439,0.939692620785908,
0.984807753012208,1};
double sc[]={1,0.984807753012208,
0.939692620785908,0.866025403784439,
0.766044443118978,0.642787609686539,
0.5,0.342020143325669,
0.17364817766693,0};
byte b=0;
void setup() {
Serial.begin(9600);
}
void loop() {
if (b==0) {
unsigned long t=micros();
for (int i=0; i<=9; i++) {
Serial.println(atan2(ss[i],sc[i])*180/3.1415926535);
}
t=micros()-t;
Serial.print(t);
b=1;
}
}
Результат -
0.00
10.00
20.00
30.00
40.00
50.00
60.00
70.00
80.00
90.00
5072
Очень даже неплохо.
Для этого пишем примерный код -
#include "math.h";
byte b=0;
void setup() {
Serial.begin(9600);
}
void loop() {
double a;
unsigned long t=micros();
a=atan2(b,1)+atan2(1,b)+atan2(b,b)+atan2(1+b,1-b);
a=sqrt(a*a+1);
a=sqrt(a*a+2);
t=micros()-t;
Serial.print(t);
Serial.print('/');
Serial.println(a);
b=b+1;
delay(200);
}
Результат -
500/2.92
748/4.29
856/4.59
852/4.72
860/4.79
860/4.84
864/4.87
860/4.89
856/4.90
852/4.92
844/4.93
Т.е. не более миллисекунды, что более чем достаточно.
Теперь о точности - насколько приближенно 8-ми битный проц вычисляет аркангенс? Для этого с помощью дельфи создадим примерные массивы синусов и косинусов, чтобы скормить их ардуино и посмотреть, насколько точно оно восстановит значения -
procedure TForm1.Button1Click(Sender: TObject);
var a:integer;
ss,sc:string;
begin
ss:='';
sc:='';
for a:=0 to 9 do begin
ss:=ss+floattostr(sin(a*10/180*pi))+',';
sc:=sc+floattostr(cos(a*10/180*pi))+',';
end;
form1.Memo1.Lines.Add('double ss[]={'+ss+'};');
form1.Memo1.Lines.Add('double sc[]={'+sc+'};');
end;
С помощью полученных строк с массивами пишем примерный код для ардуино -
#include "math.h";
double ss[]={0,0.17364817766693,
0.342020143325669,0.5,
0.642787609686539,0.766044443118978,
0.866025403784439,0.939692620785908,
0.984807753012208,1};
double sc[]={1,0.984807753012208,
0.939692620785908,0.866025403784439,
0.766044443118978,0.642787609686539,
0.5,0.342020143325669,
0.17364817766693,0};
byte b=0;
void setup() {
Serial.begin(9600);
}
void loop() {
if (b==0) {
unsigned long t=micros();
for (int i=0; i<=9; i++) {
Serial.println(atan2(ss[i],sc[i])*180/3.1415926535);
}
t=micros()-t;
Serial.print(t);
b=1;
}
}
Результат -
0.00
10.00
20.00
30.00
40.00
50.00
60.00
70.00
80.00
90.00
5072
Очень даже неплохо.