Accelerometro MMA7455L e valori inprecisi

Salve a tutti ragazzi,

sto cercando di costruire un piccolo stabilizzatore elettronico con arduino uno, un accelerometro MMA7455L e un servomotore.

Prendendo in lettura i valori letti dall'asse x, prendo la media dei valori letti per una maggiore precisione:

char average(int num, char axis){
  long tot=0;
  char val;
  for (int i=1; i<=num; i++){
    val=mySensor.readAxis(axis);
    tot += val;
   //Serial.print( val,DEC );Serial.print( " " );
   delay(2);
  }
  val=tot/num;
  //Serial.println( val );
  return(val);

Per il mio utilizzo, quando muovo l'accelerometro leggo valori da -0.13 a -2.05.
Calcolando l'equazione della retta ho ricavato questa ecquazione:

y = 591.667-833.333 x

dove y sarebbe il valore per il servo (che varia tra 300 e 2300) mentre x e' il valore letto dall'accelerometro (che varia da -0.13 a -2.05)

Mettendo nel loop il seguente codice:

valore = 591.667- (833.333 * averange(10,'x')),
myservo.writeMicroseconds(valore);

il motore fa a scattini anche se e' fermo.

Nonostante ci sia la funzione averange che calcola la media dei 10 valori letti, le posizioni che manda al servo mentre l'accelerometro e' il posizione ferma sul tavolo sono i seguenti:

start:
1578.33
1565.00
1578.33
1578.33
1578.33
1578.33
1578.33
1578.33
1578.33
1565.00
1565.00
1578.33
1578.33
1565.00
1565.00
1565.00

e cosi via.....

come vedete nonostante la media, c'e sempre un erroe di 18.33 movimenti che e' grave.

Avete qualche consiglio per ovviare questo problema?

Grazie in anticipo.

Tony

Ragazzi e' un limite dell'acceelrometro oppure sbaglio qualcosa?

tonyhhkx:
il motore fa a scattini anche se e' fermo.

E' normale, sopratutto con i servo economici, mentre con dei servo digitali di fascia alta è normale sentire un fischio ad alta frequenza con il servo fermo.

astrobeed:
E' normale, sopratutto con i servo economici, mentre con dei servo digitali di fascia alta è normale sentire un fischio ad alta frequenza con il servo fermo.

pero' sembrerebbe un problema di valori. Nel senso, se i valori fossero piu stabili/vicini tra loro, il servo starebbe piu o meno fermo.

Invece si muove come i pazzi su e giu nonostante l'accelerometro sia fermo sul tavolo.

tonyhhkx:
Invece si muove come i pazzi su e giu nonostante l'accelerometro sia fermo sul tavolo.

Prima cosa quale servo stai usando ?
Secondo si muove leggermente a piccoli scatti, che può essere normale, oppure si sposta di molto. ?

astrobeed:
Prima cosa quale servo stai usando ?
Secondo si muove leggermente a piccoli scatti, che può essere normale, oppure si sposta di molto. ?

MG945.

Si muove molto direi.
Nel caso pratico se in un loop metti questo servo e dai questi comandi (che sarebbero i valori che si alternano in modo casuale con l'accelerometro fermo) balla molto:

myServo.digitalWrite(1578.33);
myServo.digitalWrite(1565.00);

Quindi visto che da fermo l'accelerometro passa questi due valori in modo casuale, il fatto che si muova molto e' perche i valori sono molto distanti giusto? Con valori tra 700 e 2300, quello scostamento di circa 13.33 forse e' molto. Oppure e' il prezzo da pagare per il mio servo?

In alcuni video ho visto steady cam con servo simili e non ballano/tremano

Credo che il problema sia un altro.

Lo scostamento di 13 credo che non si dovrebbe notare.
Ma non e' quello che legge effettivamente!

Mi spiego.

Avviando il loop senza il pin del servo, l'output e' il seguente:
servo: 1554
servo: 1554
servo: 1541
servo: 1541
servo: 1554
servo: 1541
servo: 1541
servo: 1554
servo: 1541
servo: 1554
servo: 1554
servo: 1568
servo: 1554
servo: 1568

Se invece collego il servo loutput invece cambia drasticamente!

servo: 2224
servo: 2158
servo: 2290
servo: 2093
servo: 1948
servo: 1843
servo: 2250
servo: 2198
servo: 2211
servo: 1935
servo: 1870
servo: 2303
servo: 2093
servo: 2250
servo: 2171

Come e' possibile?
Perche cambia?

In esecuzione, se levo il pin diventa stabile (13 di errore) se lo collego diventa instabile (200 circa di errore).

Cosa sto sbagliando?

Posto il codice semplificato completo:

#include <Servo.h>
#include <Wire.h> //Include the Wire library
#include <MMA_7455.h> //Include the MMA_7455 library
 
const int vcc =  A0;
const int gnd =  A1; 
 Servo myservo;
 long a;
MMA_7455 mySensor = MMA_7455(); //Make an instance of MMA_7455
 
char xVal, yVal, zVal; //Variables for the values from the sensor
float x, y, z;
 
void setup()
{
  pinMode(gnd, OUTPUT);
  pinMode(vcc, OUTPUT);
  digitalWrite(gnd, LOW);
  digitalWrite(vcc, HIGH);
  delay (1000);
 
  Serial.begin(9600);
  Serial.println("start");
 
  mySensor.initSensitivity(8);
  mySensor.calibrateOffset(0, 0, 0);
  myservo.attach(9);
 
}
 
void loop()
{
   //y = 820.513 x+2382.05 EQUAZIONE DELLA RETTA
   a =820.513*(average(10,'x')*0.016)+2382.05;
   Serial.print("servo: "); Serial.println(a);
  
   myservo.writeMicroseconds(a);

}
 
char average(int num, char axis){
  long tot=0;
  char val;
  for (int i=1; i<=num; i++){
    val=mySensor.readAxis(axis);
    tot += val;
   //Serial.print( val,DEC );Serial.print( " " );
   delay(2);
  }
  val=tot/num;
  //Serial.println( val );
  return(val);
 
}

Credo che sia problem di alimentazione.
Se metto il servo su 3v invece di 5v i valori sembrano essere stabili

tonyhhkx:
Credo che sia problem di alimentazione.
Se metto il servo su 3v invece di 5v i valori sembrano essere stabili

Il servo va alimentato a 5-6V, però devi usare una sorgente dedicata separata da quella che alimenta Arduino, sia perché rischi reset continui, sia perché i picchi di assorbimento causano non pochi problemi ai device di natura analogica.
Anche se l'accelerometro esce in digitale dentro è analogico con un suo ADC, è di vitale importanza che la sua alimentazione sia pulitissima.

astrobeed:
Il servo va alimentato a 5-6V, però devi usare una sorgente dedicata separata da quella che alimenta Arduino, sia perché rischi reset continui, sia perché i picchi di assorbimento causano non pochi problemi ai device di natura analogica.
Anche se l'accelerometro esce in digitale dentro è analogico con un suo ADC, è di vitale importanza che la sua alimentazione sia pulitissima.

infatti notavo che ogni tanto s iresettava.

Grazie mille per l'aiuto e per i consigli.

Finalmente abbiamo incastrato il problema di natura tecnica :slight_smile:

astrobeed:
E' normale, sopratutto con i servo economici, mentre con dei servo digitali di fascia alta è normale sentire un fischio ad alta frequenza con il servo fermo.

scusami astrobeed, ritornando al discorso dei servo, ora che tutto va meglio il mioo servo da fermo fa solo piccoli scattini molto trasculabili quindi mi potrebbe andare bene.

Quando muovo l'accelerometro pero' il movimento non e' istantaneo.

Se volessi creare qualcosa di piu performante e istantaneo cosa dovrei cambiare? Il servo oppure arduino non va bene come tempi di risposta?

tonyhhkx:
Quando muovo l'accelerometro pero' il movimento non e' istantaneo.
Se volessi creare qualcosa di piu performante e istantaneo cosa dovrei cambiare?

Cosa intendi per non istantaneo ?
Tutti i servo lavorano ad almeno 50 Hz di banda, ovvero il massimo lag prima che comincia a muoversi è 20 ms che è un tempo non percepibile da un essere umano.
Ovviamente devi fare i conti anche con la velocità massima del servo, nel tuo caso è ~0.20s per 60°, ovvero partendo dalla condizione di moto ci mette 200 ms per girare di 60 gradi, se parte da fermo il tempo si allunga di un buon 15-20%.

astrobeed:
Cosa intendi per non istantaneo ?
Tutti i servo lavorano ad almeno 50 Hz di banda, ovvero il massimo lag prima che comincia a muoversi è 20 ms che è un tempo non percepibile da un essere umano.
Ovviamente devi fare i conti anche con la velocità massima del servo, nel tuo caso è ~0.20s per 60°, ovvero partendo dalla condizione di moto ci mette 200 ms per girare di 60 gradi, se parte da fermo il tempo si allunga di un buon 15-20%.

nel senso che ho provato ad attaccare un bicchiere con un po d'acqua al servo.
Muovendo il servo il bicchiere rimane diciamo in equilibro, ma se faccio veloce noto che il bicchiere si piega, prima di mettersi in asse.

Per faral breve, la velocita' del mio polso e' molto maggiore della velocita' del servo.

Edito: sono sicurissmo che il servo e] piu veloce del mio polso, ma forse il modo in qui legge i valori e li manda sono lenti?
Se faccio un write da 0 e poi 180 schizza velocissimo, ma leggendo i valori dall accelerometro e stampandoli non sembra invece

questo video di esempio puo aiutare a far capire la lentezza della risposta:

a cosa puo' essere dovuto?