Mettere a "zero" un giroscopio RISOLTO

Salve,

Sono nuovissimo del forum anche se vi leggo, sto cercando di fare un dispositivo che mi avverta quando la mia carrozzina supera una certa inclinazione avvisandomi tramite un suono che aumenta all'aumetare dell'inclinazione. Fino quì sono riuscito con un giroscopio (mpu 5060). Ora, poichè, non so ancora dove andrà posizionato sulla carrozzina, volevo avere un modo per "mettere a zero" il dispositivo una volta installato, tipo installo il dispositivo premo un tasto per 3 secondi e il dispositivo è tarato a zero.... come potrei fare? grazie

ivano1960:
Fino quì sono riuscito con un giroscopio (mpu 5060). Ora, poichè, non so ancora dove andrà posizionato sulla carrozzina, volevo avere un modo per "mettere a zero" il dispositivo una volta installato, tipo installo il dispositivo premo un tasto per 3 secondi e il dispositivo è tarato a zero.... come potrei fare? grazie

Semplicemente devi prendere i valori all'accensione, dopo aver installato il sensore e con la carrozzina perfettamente in piano, e memorizzarli come zero, preferibilmente in EEPROM, poi non fai altro che verificare lo scostamento da questi valori e in base alla soglia prefissata, che è un delta rispetto allo zero e non un valore assoluto, decidi cosa fare.

grazie della risposta, ci ho provato... non mi riesce....avevo pensato di prendere il valore che mi compare sul "monitor" metterlo su una variabile ma non mi riesce, ho preso un programmino che pigiando un pulsante mi accende un led e poi ho aggiunto un riga che mettesse il valore che compare nel monitor in una variabile...ma non va, la variabile è sempre "0".... il concetto l'ho chiaro...ma non riesco a metterlo in pratica

ivano1960:
grazie della risposta, ci ho provato... non mi riesce...

Cominciamo per gradi, prima di tutto come stai utilizzando l'MPU6050 ?
Usi i valori raw dell'accelerometro e/o giroscopio oppure usi i quaternioni forniti dal DMP ?

Senti, io non ci capisco nulla di programmazione, ho preso un codice trovato in internet e sto cercando i adattarlo alle mie esigenze, ti posto il codice e poi vediamo, ovviamente sarà "sporchissimo" e ci saranno righe inutili.... credevo fosse molto semplice... quello che ho aggiunto io è alla fine del codice... il programma prevede anche che, con un sensore di luminosità, accenda le luci posteriori e poi con il progredire dell'oscurità quelle anteriori... GRAZIE

int led = 7;
int led1 = 8;
int led2 = 9;
int val=0;
int val1=0;
int val2=0;
int analogInPin = A0;
int sensorValue1 = 0;
int setvalueP = 0;
int setvalueR = 0;
int buttonpin=11; //
int ledstatus=0;
#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}

void setup() {

pinMode(led, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode( analogInPin, INPUT);

pinMode(buttonpin , INPUT);
digitalWrite(led, ledstatus);
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif

Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately

// initialize device
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();

// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

// load and configure the DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();

// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);

// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;

// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
//
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}

// configure LED for output
pinMode(LED_PIN, OUTPUT);
}

void loop() {

// if programming failed, don't try to do anything
if (!dmpReady) return;

// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize) {
// other program behavior stuff here

}

// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();

// get current FIFO count
fifoCount = mpu.getFIFOCount();

// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));

// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);

// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;

#ifdef OUTPUT_READABLE_YAWPITCHROLL
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[2] * 180/M_PI);
Serial.print("\t");
Serial.println(setvalueP);

//val = (ypr[1] * 180/M_PI); // legge il valore dell'input e lo conserva
val1 = (ypr[2] * 180/M_PI); // legge il valore dell'input e lo conserva 2
val= setvalueP+(ypr[1] * 180/M_PI);

#endif

if (val > 20 || val < -20 || (val1 > 20 || val1 < -20))
{
digitalWrite(led, HIGH); //accende il led
}
else {
digitalWrite(led, LOW); //spegne il led
}
if (sensorValue1 < 200)
{
digitalWrite(led1, HIGH); //accende il led
}
else {
digitalWrite(led1, LOW); //spegne il led
}
if (sensorValue1 < 100)
{
digitalWrite(led2, HIGH); //accende il led
}
else {
digitalWrite(led2, LOW); //spegne il led
}

ledstatus = digitalRead(buttonpin); // lettura dell'ingresso
if (ledstatus == HIGH) { // controlla se il pulsante è premuto
digitalWrite(led, HIGH) ; // accedn il LED
setvalueP == (ypr[1] * 180/M_PI);
}
else if (ledstatus == LOW) { // controlla se il pulsante viene rilasciato
digitalWrite(led, LOW); // spegne il LED
}
}
sensorValue1 = analogRead(analogInPin);
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);

}

ivano1960:
Senti, io non ci capisco nulla di programmazione,

Prima di tutto il codice va messo con i relativi tag altrimenti non si capisce nulla, secondo questa non è una cosa semplice da implementare, oltre a richiedere un pochino di esperienza di programmazione con Arduino occorre sapere cosa sia una IMU e come usarla.
Hai copiato un esempio per l'MPU6050 a cui hai aggiunto qualche riga di codice tuo, non potrà mai funzionare come vuoi, occorre scrivere il necessario codice tenendo presente quello che deve fare la IMU, e non è una cosa semplice da fare.

Grazie delle risposte e dello sforzo che stai facendo per me,sicuramente è come dici tu, ma vorrei capire, sono riuscito a far accendere un LED prendendo

" (ypr[1] * 180/M_PI);" e

" (ypr[2] * 180/M_PI);" che sono il "beccheggio" ed il "rollio" che appaiono nel serial monitor

mettendoli nella variabili "val" e "val1" così' " val= (ypr[1] * 180/M_PI);" e val1= (ypr[2] * 180/M_PI);

e con questa riga "if (val > 20 || val < -20 || (val1 > 20 || val1 < -20))" far accendere il Led ad una certa inclinazione di "rollio" e beccheggio"

non dovrebbe essere difficile mettere le variabili "val" e "val1" in altre due variabili ad esempio "setvalueP" e "setvalueR" alla pressione di un pulsante per poi fare quello che dici tu descritto nel primo tuo post...

o sbaglio.....

Vi ho messo in difficoltà... o mi state facendo capire che non si può fare con le mie conoscenze? sempre per capire!!!!

era semplice.... in questa istruzione " setvalueP == (ypr[1] * 180/M_PI);" ho messo "==" invece di "=" che mi avrebbe salvato il valore rilevato dall'accellerometro nella variabile "setvalueP"...

facile dire... "non se po fà"....

ivano1960:
facile dire... "non se po fà"....

... il tempo ti dimostrerà chi aveva ragione ... :smiling_imp: :smiling_imp: :smiling_imp:

Guglielmo