
#141
Posté 02 mars 2018 - 08:52
Par contre il tremble beaucoup, il nest pas stable. Je vais essayé de recommencer le process plus sérieusement pour voir si ca réduit les vibrations.
Je peux aussi jouer sur le temps de computation, ca a lair de beaucoup jouer sur ce problème
#142
Posté 06 mars 2018 - 09:43
Bonjour à tous,
Je pense avoir atteint le mieux que je puisse faire pour la partie "Balancement". BurnBot tient vraiment bien à l'équilibre, j'ai amélioré sa stabilité, il ne tremble presque plus
Grâce au traceur j'ai pu me rendre plus fidèlement compte du comportement de mon PID et j'ai trouvé les bons paramètre que je vous partage ici :
Temps de computation : 5 ms
OutputLimits : -3000, 3000 (quasiment les valeurs max de mes moteurs pas à pas)
SetPoint : 0.2
Kp : 500
Ki : 15000
Kd : 0.8
Voici une petite vidéo encore pour illustrer tout ça :
Maintenant je me concentre sur comment le déplacer et comme je vous l'ai dit j'ai quelques difficultés sur ce point la. Pour le faire tourner à droite ou a gauche c'est facile, il me suffit de créer une différence entre la vitesse des deux moteurs. Comme vous pouvez le voir dans la vidéo ça marche plutôt bien, je vais juste créer un décalage plus important pour qu'il tourne plus vite.
Pour avancé et reculé c'est vraiment plus compliqué ! J'ai essayé en mettant +500 (par exemple) aux vitesses des deux moteurs, sauf que le robot compense tout seul en baissant la vitesse pour maintenir sa consigne d'équilibre (bah oui je l'ai trop bien conçu ).
Du coup l'idée que j'ai depuis le début c'est de jouer sur la consigne (setpoint). Là elle est à 0.2° (consigne d'équilibre) et pour moi si je la met à 10° le robot devrait se déplacer vers l'avant car il serait constamment entrain de tomber. Et pourtant comme vous pouvez le voir dans la vidéo, je l'incline à +10° et -10° et la seule chose qu'il fait s'est de se pencher sans reculer n'y avancer....
Est-ce les câbles qui l’empêche de bouger ou mon idée qui n'est carrément pas la bonne ? Pas facile en tout cas
#143
Posté 06 mars 2018 - 02:14
Ce sont les mêmes moteurs qui font avancer le robot et qui le maintiennent en équilibre.
C'est peut-être stupide ce que je vais dire, mais pour moi, il faut d'abord avancer puis rétablir l'équilibre.
Quand je dis avancer, je pense à 5° ou 10°.
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#144
Posté 07 mars 2018 - 04:13
Bonjour à tous,
C'est bon, j'arrive en fin à faire déplacer BurnBot ! Mon idée de jouer sur le SetPoint de mon PID était bonne, il fallait juste qu'au lieu de passer radicalement d'une valeur à une autre (de 0 à 10° d'un coup par exemple), que j'incrémente/décrémente le Setpoint progressivement pour avoir un comportement souple (et non brusque).
Du coup ça marche plutôt bien comme vous pouvez le voir dans cette vidéo :
Bon pour le coup les cables gènes un peu et empêche d'avoir quelque chose de parfaitement fluide, et il faudrait que je peaufine un peu tout ça mais je suis satisfait du résultat.
J'ai encore travaillé/amélioré la stabilité du robot et j'ai vraiment un très bon comportement aux perturbations :
C'est ainsi que je pense clore mon expérience avec BrunBot J'ai atteins tous les objectifs que je mettais fixé, je suis super satisfait du résultat et je ne souhaite pas pousser le robot plus loin pour l'instant. J'ai commandé de quoi faire un futur robot de type "Self balancing" que je détaillerais dans un autre post. Les objectifs seront de miniaturiser au maximum le robot, de le munir d'une batterie (plus aucun cable) et de le commander à distance grâce à une télécommande home made.
Voilà, BurnBot m'a permit de me familiariser avec les PID, les moteurs pas à pas, l'impression 3D et arduino en générale, je le retravaillerais surement un jour mais je préfère tourner mes futurs objectifs vers un robot encore plus efficaces, qui aura de plus une réelle fonction (autre que de rouler et tenir à l'équilibre) mais ça je vous en parlerez plus tard
PS : Je ferais surement une dernière vidéo ou je jouerais avec des parois inclinées, ou il franchira des obstacles etc...
#145
Posté 07 mars 2018 - 05:49
Super projet, mené à son terme !
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#147
Posté 07 mars 2018 - 07:15
Moi, j'aimerais bien jeter un petit coup d'œil au code, complet...
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#150
Posté 08 mars 2018 - 09:35
Pour ceux que ça intéresse
//Ce programme permet de régler le premier PID de BurnBot, je me suis rendu compte qu'il fonctionnait très bien avec seulement un PID pour le moment donc j'ai abandonné l'idée d'en combiner deux #include "I2Cdev.h" #include<Wire.h> // librairie pour le gyroscope #include <PID_v1.h> // librairie pour le PID #include "MPU6050_6Axis_MotionApps20.h" // librairie pour le gyroscope #include <AccelStepper.h> // librairie pour les moteurs pas à pas #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif // class default I2C address is 0x68 // specific I2C addresses may be passed as a parameter here // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) // AD0 high = 0x69 MPU6050 mpu; //MPU6050 mpu(0x69); // <-- use for AD0 high float vitesse; //Vitesse des moteurs int incomingByte = 0; //Byte utilisé dans le serial.read char CharByte; int Controle = 0; //Variable contenant l'instruction de direction double i = 0; //Coefficient pour le controle du robot int vit1 = 0; //Différence de vitesse pour faire tourner le robot int vit2 = 0; unsigned long temps = 0; //Variable utilisée dans certains calcul sur excel AccelStepper roueD(1, 9, 6); //9 sortie digital avec laquelle on contrôle la vitesse, le 6 la même pour le sens de rotation. AccelStepper roueG(1, 8, 5); double Setpoint, Input, Output; //Variales du PID double Kp=300, Ki=15000, Kd=1; //Coefficients du PID //500 600 2.85 //500 750 5 //450, 15000, 0.8 (valeur très correct) float Pas3 = 0.1; //Variables permettant de régler le PID float Pas2 = 5; float Pas1 = 5; PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); //Définition du PID #define OUTPUT_READABLE_YAWPITCHROLL #define ARDUINO_BOARD #define LED_PIN 13 // (Galileo/Arduino is 13) 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 VectorFloat gravity; // [x, y, z] gravity vector Quaternion q; // [w, x, y, z] quaternion container float euler[3]; // [psi, theta, phi] Euler angle container float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector // ================================================================ // === INTERRUPT DETECTION ROUTINE === // ================================================================ // This function is not required when using the Galileo volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { mpuInterrupt = true; } // ================================================================ // === INITIAL SETUP === // ================================================================ void setup() { // join I2C bus (I2Cdev library doesn't do this automatically) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); int TWBR; // 400kHz I2C clock (200kHz if CPU is 8MHz) TWBR = 24; #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif Serial.begin(115200); while (!Serial); // initialize device Serial.println(F("Initializing I2C devices...")); mpu.initialize(); // verify connection Serial.println(F("Testing device connections...")); Serial.println(F("MPU6050 connection ")); Serial.print(mpu.testConnection() ? F("successful") : F("failed")); // wait for ready Serial.println(F("\nSend any character to begin DMP programming and demo: ")); //while (Serial.available() && Serial.read()); // empty buffer // while (!Serial.available()); // wait for data // while (Serial.available() && Serial.read()); // empty buffer again // 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(45); //A qualibrer avec l'autre programme pour l'offset du MPU mpu.setYGyroOffset(38); mpu.setZGyroOffset(29); mpu.setZAccelOffset(1758); // 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 { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); } // configure LED for output pinMode(LED_PIN, OUTPUT); roueD.setMaxSpeed(3500); // Vitesse max du moteur en nombre de pas par seconde //roueD.setAcceleration(1000); //en step par seconde roueG.setMaxSpeed(3500); // Vitesse max du moteur en nombre de pas par seconde //roueG.setAcceleration(1000); //en step par seconde vitesse = 0; //Initialisation de la vitesse à 0 Setpoint = 0.2; //Point d'équilibre parfait myPID.SetMode(AUTOMATIC); //Initialisation du PID en mode automatique myPID.SetOutputLimits(-3500, 3500); //définition des limites du PID myPID.SetTunings(Kp, Ki, Kd); //Application des coefficients myPID.SetSampleTime(5); //La computation est executé toutes les 5ms delay(5000); //Delai de 5 seconde pour attendre que le MPU se calibre } // ================================================================ // === MAIN PROGRAM LOOP === // ================================================================ void loop() { roueD.runSpeed(); roueG.runSpeed(); if (Serial.available() > 0) { //Changement Manuel des coefficients du PID + ordre de déplacement incomingByte = Serial.read(); CharByte = incomingByte; if (CharByte == 49) { Kp = Kp + Pas1; } if (CharByte == 50) { Kp = Kp - Pas1; } if (CharByte == 52) { Ki = Ki + Pas2; } if (CharByte == 53) { Ki = Ki - Pas2; } if (CharByte == 55) { Kd = Kd + Pas3; } if (CharByte == 56) { Kd = Kd - Pas3; } if (CharByte == 122) { Controle = 1; //avant } if (CharByte == 115) { Controle = 2; //arrière } if (CharByte == 113) { Controle = 4; //droite } if (CharByte == 100) { Controle = 3; //gauche } if (CharByte == 97) { Controle = 0; //rien faire } //Serial.println(incomingByte); myPID.SetTunings(Kp, Ki, Kd); //On applique les nouveau coefficients roueD.runSpeed(); roueG.runSpeed(); } // if programming failed, don't try to do anything if (!dmpReady) return; roueD.runSpeed(); roueG.runSpeed(); // wait for MPU interrupt or extra packet(s) available #ifdef ARDUINO_BOARD while (!mpuInterrupt && fifoCount < packetSize) { roueD.runSpeed(); roueG.runSpeed(); } #endif // 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) { roueD.runSpeed(); roueG.runSpeed(); // reset so we can continue cleanly mpu.resetFIFO(); //Serial.println(F("FIFO overflow!")); //C'est moi qui l'ai mis en commentaire // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { roueD.runSpeed(); roueG.runSpeed(); // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); roueD.runSpeed(); roueG.runSpeed(); // 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); roueD.runSpeed(); roueG.runSpeed(); #endif if (Controle == 2) { //Toute cette partie avec les if sert au contrôle du robot i = 0; Setpoint = Setpoint + 0.05; if (Setpoint >= 6)Setpoint = 6; } if (Controle == 1) { i = 0; Setpoint = Setpoint - 0.05; if (Setpoint <= -6)Setpoint = -6; } if (Controle == 3) { vit1 = 700; vit2 = -700; } if (Controle == 4) { vit1 = -700; vit2 = 700; } if (Controle == 0) { vit1 = 0; vit2 = 0; Setpoint = Setpoint-i*Setpoint; i = i + 0.01; if(i >= 1)i = 1; } //Serial.print(Controle); Serial.print(" "); Serial.println(Setpoint); // blink LED to indicate activity blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); Input = (ypr[1] * 180/M_PI); //On change l'input myPID.Compute(); //On compute le pid vitesse = Output; // On applique l'output à la vitesse roueD.setSpeed(vitesse+vit1); roueD.runSpeed(); roueG.setSpeed(-1*(vitesse+vit2)); //On inverse la vitesse du deuxième moteur roueG.runSpeed(); Serial.print(roueD.currentPosition()); Serial.print("\t"); Serial.print(roueG.currentPosition()); Serial.print("\t"); Serial.print(Input); Serial.print("\t"); Serial.print(vitesse); Serial.print("\t"); Serial.print(Kp); Serial.print("\t"); Serial.print(Ki); Serial.print("\t"); Serial.println(Kd); temps = millis(); //Serial.print(temps); Serial.print("\t"); // Serial.print(Setpoint); Serial.print(", "); // Serial.print(Input-Setpoint); // Serial.println(); } }
#151
Posté 08 mars 2018 - 09:46
- Budet aime ceci
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#153
Posté 14 janvier 2019 - 09:55
Hola je déterre un peu le sujet, j'ai ressorti le robot dernièrement pour jouer avec, je vous avez promis en testant son équilibre dans des pentes et il s'en sort plutôt bien !
Je travaille sur un nouveau projet vraiment complexe j'aimerai vous en parler plus mais je vais attendre qu'il soit un peu plus aboutie
#154
Posté 14 janvier 2019 - 10:00
Je travaille sur un nouveau projet vraiment complexe j'aimerai vous en parler plus mais je vais attendre qu'il soit un peu plus aboutie
Nous tease pas plus ! Vas y balance tout ce que tu sais déjà pas besoin d'attendre que ça soit plus abouti ! ^^
Hola je déterre un peu le sujet, j'ai ressorti le robot dernièrement pour jouer avec, je vous avez promis en testant son équilibre dans des pentes et il s'en sort plutôt bien !
Je kiffe ce genre de détérage Par contre il faudrait modifier un chouilla le comportement pour qu'il soit " asservi en position " et que si il se déplace il cherche ensuite à se remettre là où il était =)
Si mon commentaire vous a plus laissez nous un avis !
Nouveau sur Robot Maker ?
Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope aux articles, à la boutique et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être !
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!
#155
Posté 14 janvier 2019 - 10:17
Oui en effet un asservissement en position serait type top, il faudrait que je me replonge dans le code de Burnbot, un dimanche quand je saurais pas quoi faire

Répondre à ce sujet

Aussi étiqueté avec au moins un de ces mots-clés : balancing, equilibre, pas à pas
1 utilisateur(s) li(sen)t ce sujet
0 members, 1 guests, 0 anonymous users