Gimbal con MPU6050

Salve a tutti ragazzi,
Avevo intenzione di realizzare un gimbal elettronico utilizzando un modulo MPU6050 e due stepper 28BYJ-48 (con relativi moduli L298N).
Volevo chiedervi quindi alcune cose.
Dato che vorrei realizzare qualcosa di abbastanza compatto avevo pensato di utilizzare un Arduino mini ma volevo chiedervi se è abbastanza “potente” per sopportare questi 2 motorini.
Allego una guida dove spiega anche i collegamenti necessari per illustrarvi anche il numero di pin necessari:

Grazie mille ragazzi!!!!

Ciao, so che sei un vecchio utente, ma ... NON riesco a trovare il tuo post di presentazione :confused: ... quindi, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO (che, dal tmpo della tua iscrizione, ha subito varie modifiche) ... Grazie. :slight_smile:

Guglielmo

gpb01:
Ciao, so che sei un vecchio utente, ma ... NON riesco a trovare il tuo post di presentazione :confused: ... quindi, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO (che, dal tmpo della tua iscrizione, ha subito varie modifiche) ... Grazie. :slight_smile:

Guglielmo

ok, mi sono "ripresentato" :slight_smile:

Bernardo-96:
... Dato che vorrei realizzare qualcosa di abbastanza compatto avevo pensato di utilizzare un Arduino mini ma volevo chiedervi se è abbastanza “potente” per sopportare questi 2 motorini ...

Cosa intendi per "abbastanza potente" ?

La MCU (ATmega328P) della MINI è la stessa di un Arduino UNO e, a parte il numero di alcune risorse (memoria, pin, timer, ecc) ha le stesse capacità elaborative (in termini di velocità e set di isrtuzioni) della MEGA ...

Guglielmo

okok perfetto!
volevo chiedervi se è possibile limitare la rotazione del motore a un certo angolo stabilito da me attraverso questo sketch perché comunque il gimbal oltre un certo "grado" non deve ruotare altrimenti potrebbe rompersi.

/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
 This software may be distributed and modified under the terms of the GNU
 General Public License version 2 (GPL2) as published by the Free Software
 Foundation and appearing in the file GPL2.TXT included in the packaging of
 this file. Please note that GPL2 Section 2[b] requires that all works based
 on this software must also be made publicly available under the terms of
 the GPL2 ("Copyleft").
 Contact information
 -------------------
 Kristian Lauszus, TKJ Electronics
 Web      :  http://www.tkjelectronics.com
 e-mail   :  kristianl@tkjelectronics.com
 */

#include <Stepper.h>
#include <Wire.h>
#include "Kalman.h" // Source: https://github.com/TKJElectronics/KalmanFilter

#define RESTRICT_PITCH // Comment out to restrict roll to ±90deg instead - please read: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf

Kalman kalmanX; // Create the Kalman instances
Kalman kalmanY;

/* IMU Data */
double accX, accY, accZ;
double gyroX, gyroY, gyroZ;
int16_t tempRaw;

double gyroXangle, gyroYangle; // Angle calculate using the gyro only
double compAngleX, compAngleY; // Calculated angle using a complementary filter
double kalAngleX, kalAngleY; // Calculated angle using a Kalman filter

uint32_t timer;
uint8_t i2cData[14]; // Buffer for I2C data

Stepper stepper2(100, 8,9,10,11);
Stepper stepper1(100, 7,6,5,4);

int cantidad = 1;

int previousx = 0;
int previousy = 0;

void setup() {
 
  stepper2.setSpeed(200);
    stepper1.setSpeed(200);
  
  Serial.begin(115200);
  Wire.begin();
  TWBR = ((F_CPU /400000L) - 16) / 2; // Set I2C frequency to 400kHz

  i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
  i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
  i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
  i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
  while (i2cWrite(0x19, i2cData, 4, false)); // Write to all four registers at once
  while (i2cWrite(0x6B, 0x01, true)); // PLL with X axis gyroscope reference and disable sleep mode

  while (i2cRead(0x75, i2cData, 1));
  if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register
    Serial.print(F("Error reading sensor"));
    while (1);
  }

  delay(100); // Wait for sensor to stabilize

  /* Set kalman and gyro starting angle */
  while (i2cRead(0x3B, i2cData, 6));
  accX = (i2cData[0] << 8) | i2cData[1];
  accY = (i2cData[2] << 8) | i2cData[3];
  accZ = (i2cData[4] << 8) | i2cData[5];

  // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
  // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
  // It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
  double roll  = atan2(accY, accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  kalmanX.setAngle(roll); // Set starting angle
  kalmanY.setAngle(pitch);
  gyroXangle = roll;
  gyroYangle = pitch;
  compAngleX = roll;
  compAngleY = pitch;

  timer = micros();
}

void loop() {
  /* Update all the values */
  while (i2cRead(0x3B, i2cData, 14));
  accX = ((i2cData[0] << 8) | i2cData[1]);
  accY = ((i2cData[2] << 8) | i2cData[3]);
  accZ = ((i2cData[4] << 8) | i2cData[5]);
  tempRaw = (i2cData[6] << 8) | i2cData[7];
  gyroX = (i2cData[8] << 8) | i2cData[9];
  gyroY = (i2cData[10] << 8) | i2cData[11];
  gyroZ = (i2cData[12] << 8) | i2cData[13];

  double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
  timer = micros();

  // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
  // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
  // It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
  double roll  = atan2(accY, accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  double gyroXrate = gyroX / 131.0; // Convert to deg/s
  double gyroYrate = gyroY / 131.0; // Convert to deg/s

#ifdef RESTRICT_PITCH
  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
  if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {
    kalmanX.setAngle(roll);
    compAngleX = roll;
    kalAngleX = roll;
    gyroXangle = roll;
  } else
    kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleX) > 90)
    gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);
#else
  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
  if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {
    kalmanY.setAngle(pitch);
    compAngleY = pitch;
    kalAngleY = pitch;
    gyroYangle = pitch;
  } else
    kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleY) > 90)
    gyroXrate = -gyroXrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
#endif

  gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter
  gyroYangle += gyroYrate * dt;
  //gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate
  //gyroYangle += kalmanY.getRate() * dt;

  compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter
  compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;

  // Reset the gyro angle when it has drifted too much
  if (gyroXangle < -180 || gyroXangle > 180)
    gyroXangle = kalAngleX;
  if (gyroYangle < -180 || gyroYangle > 180)
    gyroYangle = kalAngleY;

  /* Print Data */
#if 0//et to 1 to activate
Serial.print(accX); Serial.print("\t");
Serial.print(accY); Serial.print("\t");
//Serial.print(accZ); Serial.print("\t");
//rial.print(gyroX); Serial.print("\t");
 //erial.print(gyroY); Serial.print("\t");
//Serial.print(gyroZ); Serial.print("\t");
  Serial.print("\t");
#endif

//Serial.print(roll); Serial.print("\t");
  //Serial.print(gyroXangle); Serial.print("\t");
  //Serial.print(compAngleX); Serial.print("\t");
  Serial.print(kalAngleX); Serial.print("\t");

  Serial.print("\t");

  //Serial.print(pitch); Serial.print("\t");
  //Serial.print(gyroYangle); Serial.print("\t");
  //Serial.print(compAngleY); Serial.print("\t");
  Serial.print(kalAngleY); Serial.print("\t");

#if 0 // Set to 1 to print the temperature
  Serial.print("\t");
  double temperature = (double)tempRaw / 340.0 + 36.53;
  Serial.print(temperature); Serial.print("\t");
#endif

  Serial.print("\r\n");
  //delay(2);

int valuex = kalAngleX;  
stepper2.step(valuex - previousx);
  previousx = valuex;
  
int valuey = kalAngleY;
stepper1.step(valuey - previousy);
  previousy = valuey;



}

grazie ancora!

dello stepper conosci le caratteristiche e quindi conosci quanti step per una rotazione completa quindi
step : 360° = xStep: gradiDaControllare

Ok però il punto è: dove inserisco questo valore?(in base al codice che ho postato)
Ad esempio 180 gradi.

qui devi controllare che valuex - previousx e valuey-previousy rimangano come valori assoluti entro il range che desideri

int valuex = kalAngleX; 
stepper2.step(valuex - previousx);
  previousx = valuex;
 
int valuey = kalAngleY;
stepper1.step(valuey - previousy);
  previousy = valuey;

Ok, appena mi arriverà il modulo farò le prime prove.
Come ultime cose vorrei chiedervi:

1)questi motori sono abbastanza potenti da sostenere il peso della action cam?(110grammi)

2)è possibile aumentare la velocità di rotazione dei motori?(sempre nel mio sketch)

3)mi conviene alimentare a 5v o 12v i motori?

Vi ringrazio!

Solo un'appunto, essendo gli stepper dei motori "liberi" (cioe' che non hanno un finecorsa o un feedback, a meno che non prendi degli stepper con un'encoder assoluto integrato), ti servira' per forza metterci un paio di micro (o meglio ancora di sensori IR a forcella) con cui al momento dell'accensione andrai a cercare lo "zero", cioe' la posizione di partenza ... altrimenti ogni volta che li accendi, partiranno da una posizione "a caso" che potrebbe anche non essere quella centrale che vuoi ... :wink:

Ok,suppongo che questo procedimento dovrei implementarlo nel void setup giusto?
Il punto è che non so farlo...potreste aiutarmi?

I passi che dovrei fare sono:
1)Far girare il motore in senso antiorario fino a quando non tocca il finecorsa.

2)fermare il motore (anche per risparmiare energia)

3)salvare la posizione e da quella posizione “contare” 180gradi

Il punto è che non so scrivere il codice per effettuare queste operazioni..

>Bernardo-96: ... emmm, non vorrei sembrare scortese, ma .. hai presente il punto 16.1 del REGOLAMENTO ? Dovresti leggerlo con attenzione ...

Qui sul forum nessuno scrive software per conto terzi o realizza schemi su ordinazione, ma si aiuta chi viene qui a correggere/ottimizzare il software che lui scrive o gli schemi che lui realizza. ::slight_smile:

Quindi ... prova a seguire i link riportati, prova a studiare qualche buon libro di programmazione e poi ... butta giù il tuo programma ! Noi saremo qui ad aiutarti a correggerlo ed a risolvere eventuali problemi :wink:

Guglielmo

P.S.: ... personalmente, inoltre, io consiglio sempre QUESTO libro :slight_smile:

Non ho chiesto a nessuno di scrivermi un intero codice per costruire un gimbal, ho semplicemente chiesto come realizzare quel ciclo, che per voi credo che non sia molto difficile.
Tutto qui.

Bernardo-96:
...
1)Far girare il motore in senso antiorario fino a quando non tocca il finecorsa.
...

Aspetta, perche' anche se tecnicamente e' una procedura corretta, in questo specifico caso gia qui con l'applicazione che vuoi realizzare, potresti avere dei problemi a livello "meccanico" ... intendo dire che, essendo un gimbal, il progetto deve essere studiato prendendo in considerazione prima di tutto le caratteristiche fisiche dell'apparato, e solo in seguito adattandogli il resto.

Un passo alla volta, se mi consenti ... stiamo parlando di un "gimbal", cioe' di un supporto stabilizzato il cui scopo e' mantenere orizzontale un'oggetto (poco importa in questo momento il numero di assi, ma solo lo scopo della macchina) ... per cui non ha molto senso far fare mezzo giro al tutto solo per trovare un finecorsa, specie se l'oggetto in questione rischia di danneggiarsi se viene a trovarsi in verticale (magari no, ma e' l'approccio iniziale quello di cui sto parlando ;))

Per cui, il sistema dei finecorsa dovrebbe essere pensato per minimizzare il rischio che questo accada, ed allo stesso tempo ridurre al massimo il lavoro ed il tempo necessario ad iniziare i cicli ... quindi il sistema piu efficente sarebbe uno che ti consenta di sapere la posizione di partenza della macchina all'accensione (piu perfezionato, ma piu complesso, realizzabile o con encoder assoluti o con potenziometro), oppure al limite un sistema che ti consenta di sapere "almeno" in quale posizione "rispetto allo zero centrale" (cioe' al punto in cui l'oggetto e' orizzontale con il supporto orizzontale) si trova al momento dell'accensione, e questo e' realizzabile, volendo, con due forcelline ottiche invece che una (spesa minima, poca complicazione).

Serve usare un disco di plastica o metallo o quello che vuoi, con due asole semicircolari (ma potrebbe anche essere un dischetto di plastica rigida trasparente con dei settori verniciati sopra, per ulteriore semplicita'), con le forcelle affiancate ma "scalate" in altezza, e due settori opachi realizzati sul disco in modo che entrambe le forcelle siano illuminate (oppure oscurate, e' lo stesso) solo nel momento in cui il supporto e' a 90 gradi ... in questo modo all'accensione, se non e' gia a 90 gradi, sai gia in quale direzione e' spostato, e puoi muoverlo nella direzione opposta finche' entrambe le forcelle sono attive, a quel punto sai che sei a 90 gradi e "conti" in piu o in meno secondo dove devi muoverti ...

Questo sistema ti consente anche di evitare di ribaltare l'oggetto muovendo il motore nella direzione sbagliata mentre cerchi lo zero ... oltre a velocizzare il tutto :wink:

Bernardo-96:
... ho semplicemente chiesto come realizzare quel ciclo, che per voi credo che non sia molto difficile.

... che, t'assicuro senza alcuna polemica, ma solo facendo una constatazione ... è sempre chiedere a noi di scrivere un intero pezzo di programma per te non trovi ? ? ? :slight_smile: :slight_smile: :slight_smile:

Sforzati, studia, butta giù quello che pensi debba essere il programma e poi noi sicuramente ti aiutiamo a sistemarlo :wink:

Guglielmo

Ti ringrazio per le informazioni. :slight_smile:
Comunque mi sono documentato un po’ in giro e sono arrivato alla conclusione che pur utilizzando questi stepper e facendo tutto come si deve avrò una marea di problemi quindi ho deciso di passare ai servo, ho visto questa guida e devo dire che funziona abbastanza bene.
L’unica pecca di questo tipo di gimbal è che i servo fanno un rumore pazzesco quindi non ha molto senso stabilizzare per poi avere problemi a livello audio durante il video.
Esiste qualche servo silenzioso o magari è possibile ridurre il rumore?
(In particolare nell’articolo vengono utilizzati i servo sg90)

Link all’articolo:

Grazie ancora!

Domanda: vuoi usare il gimbal in condizioni reali o solo per sperimentare un po? Perchè il progetto con i servo è carino ma dubito sia utilizzabile in condizioni reali (vedi ultimo video).

Per i motori, i gimbal usano i brushless, prova a guardare questi

Infatti anch'io avevo dei dubbi che fosse solo uno studio di fattibilita' (gli stepper darebbero ancora piu problemi dei servo, essendo appunto "stepper", cioe' viaggiando "a salti" (a meno di non usare un driver microstep) ...

Il gimbal che ho massacrato ehm, "riparato" (:P) tempo fa della gopro di un drone usava addirittura degli attuatori "galvo", neppure i brushless ... in pratica, un sistema con doppia bobina ed anello magnetico esterno che si comportava come i "galvo scanner" dei proiettori laser (funzionano in pratica come i motori delle testine degli hard-disk), due soli poli con feedback, risposta fluida e velocissima senza salti, ma necessita di elettronica specializzata e drivers di tipo "voice-coil", non proprio facili da realizzare a livello hobbystico ...