Salve signori
sto cercando un modo per trasformare i valori provenienti da un sensore in gradi.
Brevemente: sto usando un accelerometro per misurare delle inclinazioni sui vari assi di un oggetto, vorrei trasformare in gradi questi valori.
Sono quasi sicuro che se ne è parlato già in questo forum ma non trovo nulla, sicuramente sto usando parole chiavi non corrette, potete darmi una mano??
//Ingressi analogici di Arduino
const int xPin = 0;
const int yPin = 1;
const int zPin = 2;
//Valori massimo e minimo dell'accelerometro
//utilizzato e quindi da modificare se necessario
int minVal = 260;
int maxVal = 397;
//Variabili che contengono il valore attuale
double x;
double y;
double z;
void setup(){
Serial.begin(9600);
}
void loop(){
//Lettura valori di tensione forniti dal sensore
int xRead = analogRead(xPin);
int yRead = analogRead(yPin);
int zRead = analogRead(zPin);
//Conversione dei valori letti in gradi
int xAng = map(xRead, minVal, maxVal, -90, 90);
int yAng = map(yRead, minVal, maxVal, -90, 90);
int zAng = map(zRead, minVal, maxVal, -90, 90);
//Visualizzo i valori
Serial.print("x: ");
Serial.print(xAng);
Serial.print(" | y: ");
Serial.print(yAng);
Serial.print(" | z: ");
Serial.println(zAng);
delay(1000);
}
è un codice molto abbozzato e sicuramente non preciso.
Su una pagina web ho visto che utilizzano anche questa porzione di codice
x = RAD_TO_DEG * ( atan2(-yAng, -zAng) + PI);
y = RAD_TO_DEG * ( atan2(-xAng, -zAng) + PI);
z = RAD_TO_DEG * ( atan2(-yAng, -xAng) + PI);
ovviamente poi vengono printati questi valori, ho provato ma mi escono numeri che non riesco a decifrare.
AMBUSH:
ovviamente poi vengono printati questi valori, ho provato ma mi escono numeri che non riesco a decifrare.
Non sono un matematico ma se hai un vettore che rappresenta la direzione e l'intensità dell'accelerazione, immagino che quelle 3 formule estrapolino la posizione nello spazio della "punta" del vettore stesso.
ok ma non capisco se mi può essere di qualche utilità...
e lo sketch che sto adottando va bene? oppure la base è sbagliata e devo trovare un'altro modo??
Se hai un accelerometro ed hai la lettura dei 3 assi spaziali, puoi avere la direzione del vettore di spinta e l'intensità della stessa. Non chiedermi le formule perché non sono un matematico.. Intendo una cosa come quella dell'immagine, un vettore in uno spazio cartesiano
Però rileggendo la tua domanda, tu vuoi sapere le "inclinazioni sui vari assi di un oggetto". Non è che forse più che di un accelerometro ti serve un giroscopio? L'accelerometro di darà delle letture solo se l'oggetto è sottoposto appunto ad accelerazione ma se l'oggetto è ruotato ma fermo, avrai sempre letture 0,0,0 per i tre assi x,y,z.
Non è zero perchè comunque l'accelerometro è soggetto alla forza di gravità quando è fermo e quindi ricordando la formula F=m*g dove g e l'accelerazione della gravità se ne ricava che l'accelerometro rivela come è ripartita questa forza quando il sensore ruota su uno/due/ tre assi.
quindi integrando questi valori ottengo l'inclinazione degli angoli.
vorrei chiedervi un parere su questa mia idea (sicuramente già sviluppata da qualcun altro)
i valori che leggo dal sensore tramite Arduino li riporto in "g", g è un valore compreso da -1 e +1 (quindi può valere anche 0)
di conseguenza i valori dell'accelerometro variano da -1 g a + 1 g-
ad esempio se il sensore è posizionato in orizzontale x=0, y=0 e z=-1 g
ricavati\convertiti questi valori applico queste formule di trigonometria
oppure
(spero di non aver violato qualche regola con questi link)
è un ragionamento corretto o è completamente no-sense??
Sto usando un accelerometro analogico per misurare l'inclinazione di un oggetto fermo e quindi soggetto alla sola accelerazione di gravità.
vorrei avere il vostro parere su questo sketch
const int xpin = A1;
const int ypin = A2;
const int zpin = A3;
//Array_x
const int numofReadings_x = 100;
int readings_x[numofReadings_x];
int index_x = 0;
float total_x = 0;
int average_x = 0;
//Array_y
const int numofReadings_y = 100;
int readings_y[numofReadings_y];
int index_y = 0;
float total_y = 0;
int average_y = 0;
//Array_z
const int numofReadings_z = 100;
int readings_z[numofReadings_z];
int index_z = 0;
float total_z = 0;
int average_z = 0;
void setup()
{
Serial.begin(9600);
//inizializza array_x delle letture
for (int i_x = 0; i_x < numofReadings_x; i_x++) {
readings_x[i_x] = 0;
}
//inizializza array_y delle letture
for (int i_y = 0; i_y < numofReadings_y; i_y++) {
readings_y[i_y] = 0;
}
//inizializza array_z delle letture
for (int i_z = 0; i_z < numofReadings_z; i_z++) {
readings_z[i_z] = 0;
}
analogReference(EXTERNAL);
pinMode(xpin, INPUT);
pinMode(ypin, INPUT);
pinMode(zpin, INPUT);
}
void loop()
{
float x = analogRead(xpin);
delay(1);
float y = analogRead(ypin);
delay(1);
float z = analogRead(zpin);
delay(1);
float zero_G_x = 501.5;
float zero_G_y = 500.5;
float zero_G_z = 520.5;
float scale_x = 103.5;
float scale_y = 104.5;
float scale_z = 102.5;
x = ((float)x - zero_G_x)/scale_x; //riporto i valori i "g"
y = ((float)y - zero_G_y)/scale_y;
z = ((float)z - zero_G_z)/scale_z;
float rad_x = atan( x / sqrt((sq(y) + sq (z))));
float rad_y = atan( y / sqrt((sq(x) + sq (z))));
float rad_z = atan( z / sqrt((sq(x) + sq (y))));
float grado_x = (rad_x * 57296)/1000;
float grado_y = (rad_y * 57296)/1000;
float grado_z = (rad_z * 57296)/1000;
//Per diminuire l'errore crea un array_x con le letture e calcola la media
total_x -= readings_x[index_x];
readings_x[index_x] = grado_x;
total_x += readings_x[index_x];
index_x = (index_x + 1);
if (index_x >= numofReadings_x)
index_x = 0;
average_x = total_x / numofReadings_x; //Media dei valori delle distanze acquisite
//array_y
total_y -= readings_y[index_y];
readings_y[index_y] = grado_y;
total_y += readings_y[index_y];
index_y = (index_y + 1);
if (index_y >= numofReadings_y)
index_y = 0;
average_y = total_y / numofReadings_y; //Media dei valori delle distanze acquisite
//array_z
total_z -= readings_z[index_z];
readings_z[index_z] = grado_z;
total_z += readings_z[index_z];
index_z = (index_z + 1);
if (index_z >= numofReadings_z)
index_z = 0;
average_z = total_z / numofReadings_z; //Media dei valori delle distanze acquisite
//Serial.print(x);
Serial.print(average_x);
Serial.print("\t");
//Serial.print(y);
Serial.print(average_y);
Serial.print("\t");
//Serial.print(z);
Serial.print(average_z);
Serial.print("\n");
delay(50);
}
secondo voi è corretto?? io ottengo dei valori che mi sembrano abbastanza veritieri tranne in alcune circostanze ma sballa di 1 o 2 gradi nei casi peggiori.
ciao
non mi ci metto a modificare il tuo sketch, non ho tempo :P.
non trovo lo sketch del video, comunque in linea di massima (vado a memoria) è così
float x = analogRead(xpin);
float xx = xx*0.70+ x*0.30; //media valori (la somma deve sempre fare 1)
gradix = map (xx,valoreinclinatoSx,valoreinclinatoDx,-90,90);
edit: codice sopra errato
i valroreinclinato destro e sinistro li si trova con il monitor seriale inclinando l'accelerometro da 0 a 180.
mediavalori 0.90+ x*0.10 piu stabile ma più si va su piu rallenta arduino
camperos:
ciao
non mi ci metto a modificare il tuo sketch, non ho tempo :P.
non trovo lo sketch del video, comunque in linea di massima (vado a memoria) è così
float x = analogRead(xpin);
float xx = xx0.70+ x0.30; //media valori (la somma deve sempre fare 1)
gradix = map (xx,valoreinclinatoSx,valoreinclinatoDx,-90,90);
i valroreinclinato destro e sinistro li si trova con il monitor seriale inclinando l'accelerometro da 0 a 180.
mediavalori 0.90+ x*0.10 piu stabile ma più si va su piu rallenta arduino
uoi spiegarmi perchè moltiplichi per 0.70 e 0.30?? Appena hai tempo ovviamente XD
float x;
float gradix;
---
----
x= 0.70 * x + 0.30 * analogRead (xpin); //media valori (la somma deve sempre fare 1)
gradix = map (x,valoreinclinatoSx,valoreinclinatoDx,-90,90);
x -> è il valore letto nel giro precedentemente
prendo il 70 % di x
aggiungo la lettura successiva del 30 %
se la lettura precedente è di 100, e la lettura seguente è di 110 e poi 90 (in pochi millisecondi)
il risultato sarà
primo giro 70 + 32 =102 (anzichè 110)
secondo giro (70 % di 102) ciirca 71 + (30% di 90) circa 27 = 98 (anzichè 90)
la media è sempre 100, ma dopo il calcolo la lettura è ...fluida