Bonjour,
j'ai repris un programme de : // Aritro Mukherjee , April 2016
// For more information Aritro Mukherjee - Hackster.io
( DIY Flight Instruments for Horizon and Compass)
pour faire un horizon artificiel. j'ai rajouter un capteur de pression (BMP280) pour l'alti et vario,
le sérial comme sur le cite est envoyer vers une raspberry pour l'affichage.
Ce programme bug et bloque au bout de 10 a 15 secondes, après raz ou relance du programme c'est idem avec ou sans la raspberry.
je ne trouve pas le problème.
un petit coup de main me ferais bien plaisir.
voici le code:
// Aritro Mukherjee , April 2016
// For more information https://www.hackster.io/Aritro
/********************************** encodeur rotatif ******************************/
#include <ClickEncoder.h>
#include <TimerOne.h>
ClickEncoder *encoder;
float last, value;
int adj;
void timerIsr() {
encoder->service();
}
/////////////////// BMP /////////////////////////
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // I2C
float pressure;
long int ancien_millis;
float Alti;
float Vario;
float vario;
float ancienne_altitude;
/////////////////////////////////////////////////
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
#define OUTPUT_READABLE_YAWPITCHROLL
#define LED_PIN 13
bool blinkState = false;
// Variables de contrôle/état du MPU
bool dmpReady = false; // définir vrai si l'initialisation DMP a réussi
uint8_t mpuIntStatus; // détient l'octet d'état d'interruption réel du MPU
uint8_t devStatus; // renvoie l'état après chaque opération de l'appareil (0 = succès, !0 = erreur)
uint16_t packetSize; // taille de paquet DMP attendue (la valeur par défaut est de 42 octets)
uint16_t fifoCount; // nombre de tous les octets actuellement dans FIFO
uint8_t fifoBuffer[64]; // Tampon de stockage FIFO
// vars d'orientation/mouvement
Quaternion q; // [w, x, y, z] conteneur de quaternion
VectorInt16 aa; // [x, y, z] mesures du capteur d'accélération
VectorInt16 aaReal; // [x, y, z] mesures du capteur d'accélération sans gravité
VectorInt16 aaWorld; // [x, y, z] mesures du capteur d'accélération à l'échelle mondiale
VectorFloat gravity; // [x, y, z] vecteur de gravité
float euler[3]; // 3 // [psi, theta, phi] Conteneur d'angle d'Euler
float ypr[3]; // [yaw, pitch, roll] pres lacet/tangage/rouleau conteneur et vecteur de gravité
// structure de paquet pour la démonstration de teapot InvenSense
uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; //[14]
// ================================================================
// === ROUTINE DE DETECTION D'INTERRUPTION ===
// ================================================================
volatile bool mpuInterrupt = false; // indique si la broche d'interruption MPU est passée au niveau haut
void dmpDataReady() {
mpuInterrupt = true;
}
// ================================================================
// === CONFIGURATION INITIALE ===
// ================================================================
void setup() {
/********************************** encodeur rotatif ********************************/
encoder = new ClickEncoder(A1, A0, A2);
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);
////////// Connexion au capteur BMP /////////
if (!bmp.begin()) {
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
while (1);
}
Serial.println(F("Reading BMP280 : "));
//////////////////////////////////////////////
// rejoindre le bus I2C (la bibliothèque I2Cdev ne le fait pas automatiquement)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // Horloge I2C 400 kHz (200 kHz si le processeur est à 8 MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// initialiser la communication série
// (115200 choisi car il est requis pour la sortie Teapot Demo, mais c'est
Serial.begin(115200);
while (!Serial); //attendre le dénombrement arduino, les autres continuent immédiatement
mpu.initialize();
devStatus = mpu.dmpInitialize();
// décalages de gyroscope, mis à l'échelle pour une sensibilité minimale
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788);
//assurez-vous que cela a fonctionné (renvoie 0 si oui)
if (devStatus == 0) {
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
//Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// activer la détection d'interruption Arduino
//Serial.println(F("Activation de la détection d'interruption (interruption externe Arduino 0)..."));
dmpReady = true;
// obtenir la taille de paquet DMP attendue pour une comparaison ultérieure
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(devStatus);
Serial.println(F(")"));
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
// ================================================================
// === MAIN PROGRAM LOOP ===
// ================================================================
void loop() {
/********************************** encodeur rotatif ********************************/
ClickEncoder::Button b = encoder->getButton();
if (b != ClickEncoder::Open) {
encodeur();
}
/*************************************************************************************/
// si la programmation a échoué, n'essayez pas de faire quoi que ce soit
if (!dmpReady) return;
// attend l'interruption du MPU ou des paquets supplémentaires disponibles
while (!mpuInterrupt && fifoCount < packetSize) {
}
// réinitialiser l'indicateur d'interruption et obtenir l'octet INT_STATUS
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// obtenir le nombre FIFO actuel
fifoCount = mpu.getFIFOCount();
// vérifie le débordement (cela ne devrait jamais arriver à moins que notre code ne soit trop inefficace)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// réinitialiser pour que nous puissions continuer proprement
mpu.resetFIFO();
//Serial.println(F("FIFO overflow!"));
// sinon, vérifiez l'interruption de la disponibilité des données DMP (cela devrait se produire fréquemment)
} else if (mpuIntStatus & 0x02) {
// attend la longueur correcte des données disponibles, devrait être une attente TRÈS courte
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// lit un paquet depuis FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// suivre le nombre de FIFO ici au cas où il y aurait > 1 paquet disponible
// (cela nous permet d'en lire plus immédiatement sans attendre une interruption)
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_QUATERNION
// affiche les valeurs des quaternions sous forme de matrice simple : w x y z
mpu.dmpGetQuaternion(&q, fifoBuffer);
Serial.print("quat\t");
Serial.print(q.w);
Serial.print("\t");
Serial.print(q.x);
Serial.print("\t");
Serial.print(q.y);
Serial.print("\t");
Serial.println(q.z);
#endif
#ifdef OUTPUT_READABLE_EULER
// affiche les angles d'Euler en degrés
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180 / M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180 / M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180 / M_PI);
#endif
#ifdef OUTPUT_READABLE_YAWPITCHROLL
// affiche les angles d'Euler en degrés
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
//Serial.print("Phi: ");
Serial.print(ypr[2] * 18 / M_PI);
//Serial.print("\t theta: ");
Serial.print(" ");
Serial.print(ypr[1] * 180 / M_PI);
//Serial.print("\t Psi: ");
Serial.print(" ");
Serial.print(ypr[0] * 180 / M_PI);
/******************************************/
// envoie Alti et Vario a la Raspberry //
/******************************************/
////////// lecture du capteur BMP //////////
Alti = bmp.readAltitude (1013+value);
Serial.print(" ");
Serial.print(Alti);
calcule_vario();
Serial.print(" ");
Serial.print(vario);
Serial.print(" ");
Serial.println(value);
#endif
#ifdef OUTPUT_READABLE_REALACCEL
// affiche l'accélération réelle, ajustée pour éliminer la gravité
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
Serial.print("areal\t");
Serial.print(aaReal.x);
Serial.print("\t");
Serial.print(aaReal.y);
Serial.print("\t");
Serial.println(aaReal.z);
#endif
#ifdef OUTPUT_READABLE_WORLDACCEL
// affiche l'accélération initiale du cadre mondial, ajustée pour supprimer la gravité
// et pivoté en fonction de l'orientation connue du quaternion
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
Serial.print("aworld\t");
Serial.print(aaWorld.x);
Serial.print("\t");
Serial.print(aaWorld.y);
Serial.print("\t");
Serial.println(aaWorld.z);
#endif
#ifdef OUTPUT_TEAPOT
// afficher les valeurs de quaternion dans le format de démonstration InvenSense Teapot :
teapotPacket[2] = fifoBuffer[0];
teapotPacket[3] = fifoBuffer[1];
teapotPacket[4] = fifoBuffer[4];
teapotPacket[5] = fifoBuffer[5];
teapotPacket[6] = fifoBuffer[8];
teapotPacket[7] = fifoBuffer[9];
teapotPacket[8] = fifoBuffer[12];
teapotPacket[9] = fifoBuffer[13];
//teapotPacket[10] = 1013.12; // test
Serial.write(teapotPacket, 14); //Serial.write(teapotPacket, 14);
teapotPacket[11]++; // packetCount, boucle à 0xFF exprès //test teapotPacket[11]++;
#endif
// LED clignotante pour indiquer l'activité
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
}
/************************************ Void Vario *******************************/
void calcule_vario() {
if ((millis() - ancien_millis) >= 1000) {
ancien_millis = millis();
float moyenne = 0;
for (int i = 0; i <= 20; i++) {
moyenne += bmp.readAltitude();
delay(1);
}
moyenne /= 20;
vario = (moyenne - ancienne_altitude);
ancienne_altitude = moyenne;
}
}
/************************************ Void Encodeur *******************************/
void encodeur () {
encoder->setAccelerationEnabled(true);
value += encoder->getValue();
if (value != last) {
last = value;
}
}