Salve,
Ho creato un piccolo progetto dove il servo è comandato dal giroscopio quando quest'ultimo si muove su asse Yaw, e fin qui sono riuscito a realizzare il tutto con varie ricerche sia sul Vs sito che sul web, quindi ho realizzato sia hardware ed anche il codice che desideravo, tutto funziona.
Adesso vi chiedo aiuto poiché ho bisogno della seguente modifica:
vorrei che il servo iniziasse a muoversi dopo che il giroscopio abbia effettua esempio 45° quindi diciamo che se muovessi il giroscopio da 0 a 45° il servo non risponde, non appena abbia superato il 45° inizia a muoversi
vorrei che il servo una volta che ha compiuto i suoi 180° tornasse indietro nella posizione di partenza (0°).
Spero di aver esposto con chiarezza la problematica e se potete aiutarmi nella modifica/aggiunta del codice.
Grazie in anticipo
#include <Wire.h>
#include <MPU6050.h>
#include <Servo.h>
MPU6050 mpu;
Servo ServoZ;
// Timers
unsigned long timer = 0;
float timeStep = 0.01;
// Pitch, Roll and Yaw values
float pitch = 0;
float roll = 0;
float yaw = 0;
void setup()
{
Serial.begin(115200);
ServoZ.attach(9);
// Initialize MPU6050
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
// Calibrate gyroscope. The calibration must be at rest.
// If you don't want calibrate, comment this line.
mpu.calibrateGyro();
// Set threshold sensivty. Default 3.
// If you don't want use threshold, comment this line or set 0.
mpu.setThreshold(3);
}
void loop()
{
timer = millis();
// Read normalized values
Vector norm = mpu.readNormalizeGyro();
// Calculate Pitch, Roll and Yaw
pitch = pitch + norm.YAxis * timeStep;
roll = roll + norm.XAxis * timeStep;
yaw = yaw + norm.ZAxis * timeStep;
ServoZ.write(yaw);
// Output raw
Serial.print(" Pitch = ");
Serial.print(pitch);
Serial.print(" Roll = ");
Serial.print(roll);
Serial.print(" Yaw = ");
Serial.println(yaw);
// Wait to full timeStep period
delay((timeStep*5000) - (millis() - timer));
}
Ciao ti ringrazio per la risposta, ho provato e va abbastanza bene, però il servo dopo che ha compiuto i 180° non ritorna a zero in automatico ma solo se riporto il giroscopio al di sotto dei 45°, a me piacerebbe che ritorna a zero in automatico, è fattibile? ho provato io ma non ne ho le capacità facendo vari tentativi
if (yaw > 45) {
ServoZ.write(180);
}
// il resto del codice di prima a seguire l'ultima parte
// Wait to full timeStep period
delay((timeStep*5000) - (millis() - timer));
ServoZ.write(0);
}
Credo proprio non possa funzionare. Dopo essere tornato a zero cosa accade se yaw è ancora > di 45, perché al momento torna a 180 e dopo circa 50ms (o meno) va a zero.
Purtroppo non va ma ti ringrazio ugualmente, secondo me perché probabilmente è tutto legato al giroscopio...
Da ignorante secondo me dovrebbe essere tradotto in codice:
Se Yaw è maggiore di 45° porta il Servo a 180° (come già mi ha scritto tu il codice)
Quando il Servo ha raggiunto i 180° portalo al punto di partenza cioè a zero.
Mi piacerebbe che Quando il servo ritorna a zero e da questo punto ricalibra il giroscopio cosi da riportare Yaw a 0° cosi da iniziare di nuovo il ciclo.
Cmq è il giroscopio che muove il servo.
Quindi riepilogando:
Se Yaw è maggiore di 45° porta il Servo a 180° (come già mi ha scritto tu il codice)
Quando il Servo ha raggiunto i 180° portarlo al punto di partenza cioè a zero.
Ricalibra il giroscopio in modo che Yaw è di nuovo su 0°
Non so se è accettabile. dopo il comando servo(0) la cpu si ferma per 100ms, quando trascorsi, chiama: mpu.calibrateGyro();, che dovrebbe ricalibrare il giroscopio.
void loop()
{
timer = millis();
// Read normalized values
Vector norm = mpu.readNormalizeGyro();
// Calculate Pitch, Roll and Yaw
pitch = pitch + norm.YAxis * timeStep;
roll = roll + norm.XAxis * timeStep;
yaw = yaw + norm.ZAxis * timeStep;
if (yaw > 45) {
ServoZ.write(180);
delay(100); // 100ms nella speranza che il servo non ci impieghi più tempo.
ServoZ.write(0);
delay(100);
mpu.calibrateGyro();
}
// Output raw
Serial.print(" Pitch = ");
Serial.print(pitch);
Serial.print(" Roll = ");
Serial.print(roll);
Serial.print(" Yaw = ");
Serial.println(yaw);
// Wait to full timeStep period
delay((timeStep*5000) - (millis() - timer));
}
PS: non l'avevi detto che volevi calibrare il gyro?
Ho fatto qualche piccola modifica "Servo.write (yaw < 45" perché altrimenti il servo si muoveva già da prima, adesso risolto, però non mi fa ripartire il giroscopio, si impalla dopo aver fatto il suo lavoro normalmente.
Non si muove prima, invece stampa 600ms dopo avere ruotato il gyro a poco più di 45°.
ServoZ.write(yaw < 45) viene valutato così:
Se yaw è minore di 45 il risultato della espressione è vera (true):
ServoZ.write(1)
Se yaw è => (uguale o maggiore di)i 45 viene valutata falsa (false).
ServoZ.write(0)
true equivale a 1.
false equivale a 0.
Forse è dovuto a:mpu.calibrateGyro();
Non mi intendo tanto di giroscopi.
bool enable = false;
void loop()
{
timer = millis();
// Read normalized values
Vector norm = mpu.readNormalizeGyro();
// Calculate Pitch, Roll and Yaw
pitch = pitch + norm.YAxis * timeStep;
roll = roll + norm.XAxis * timeStep;
yaw = yaw + norm.ZAxis * timeStep;
if (enable == true && yaw > 45) {
ServoZ.write(180);
delay(100); // 100ms nella speranza che il servo non ci impieghi più tempo.
ServoZ.write(0);
delay(100);
enable = false; // da questo momento enable == false.
} else if (yaw < 1) {
// altrimenti se yaw < 1 enable = true.
enable = true;
}
// Output raw
Serial.print(" Pitch = ");
Serial.print(pitch);
Serial.print(" Roll = ");
Serial.print(roll);
Serial.print(" Yaw = ");
Serial.println(yaw);
// Wait to full timeStep period
delay((timeStep*5000) - (millis() - timer));
}
Bene....magari per risolvere il problema di ricominciare il ciclo ho pensato ad un pulsante di reset, faccio prima una ricerca prima di scocciare qui.... Grazie ancora vi aggiorno
leggevo un pò in giro del "do while", potrebbe fare al mio caso?
" la condizione di ripetizione viene verificata solo DOPO aver eseguito il corpo del ciclo"
sembra adatto per la mia esigenza...
Escludo che il do while possa cambiare le cose.
Ma scusa cosa non va nell'ultimo skech che ho allegato.
Il servo va a 180, dopo 100ms torna a 0.
Da questo momento per avere lo stesso comportamento devi girare il gyro in modo che il valore di yaw sia minore di 1.
Adesso se muovi il gyro e superi 45 accade la stessa cosa e così all'infinito.
Nella modifica che mi hai scritto succede che il servo si posiziona a 45° e non da 0° e quando con il giroscopio raggiungo i 45° al monitor seriale, il servo fa solo un cenno di muoversi e basta, poi l'asse Yaw si blocca a zero sul monitor e non cambia valore.
Invece quello dello screenshot che ti ho allegato precedentemente fa il suo lavoro benissimo anche se probabilmente è scritto piu rudimentale.
Il problema resta come ripartire da zero lo sketch da codice prima di arrivare al tasto reset esterno
Provato, mi piace come lavora.... solo la sensibilità del giroscopio è troppo elevata, appena lo tocco subito attiva il servo. Su quali parametri posso agire? Grazie ancora