MPU6050 и Arduino, управление светодиодами

WinterBreeze
Offline
Зарегистрирован: 25.08.2019
Всем привет!
Прошу помощи с кодом.
Нашёл на сайте код для управления светодиодами при помощи GY-521.
Вычленил из полного кода кусок для управления только четырьмя диодами (у автора реализована возможность переключения на управление большей группой диодов).
 
Получилось так:
 
const int frontLed = 3;
const int bottomLed = 5;
const int rightLed = 6;
const int leftLed = 9;
long int lastPrintTime;

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif

MPU6050 mpu;

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
volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high

void setup()
{
    #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(9600);
    while (!Serial); // wait for Leonardo enumeration, others continue immediately
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();
    mpu.setXGyroOffset(220);
    mpu.setYGyroOffset(76);
    mpu.setZGyroOffset(-85);
    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
    if (devStatus == 0) {
        // turn on the DMP, now that it's ready
        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);
        Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
        attachInterrupt(0, dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();
        Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
    }
    initializeLEDsSimple();
    lastPrintTime = millis();  
}

void loop()
{
    if (!dmpReady) return;
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    fifoCount = mpu.getFIFOCount();
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));
    } else if (mpuIntStatus & 0x02) {
        while (fifoCount < packetSize) {
          fifoCount = mpu.getFIFOCount();
        }
        mpu.getFIFOBytes(fifoBuffer, packetSize);      
        fifoCount -= packetSize;
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        int x = ypr[0] * 180/M_PI;
        int y = ypr[1] * 180/M_PI;
        int z = ypr[2] * 180/M_PI;
        Serial.print(y);Serial.print("\t");Serial.println(z); 
        flashLEDsSimple(x, y, z);
        }
}

void initializeLEDsSimple()
{
    pinMode(frontLed, OUTPUT);
    pinMode(bottomLed, OUTPUT);  
    pinMode(rightLed, OUTPUT);
    pinMode(leftLed, OUTPUT);
}

void flashLEDsSimple(int x, int y, int z)
{
    if (y > 0) {
        analogWrite(rightLed, y*4);
        analogWrite(leftLed, 0);         
    } else {
        analogWrite(leftLed, y*4*-1);    
        analogWrite(rightLed, 0);    
    }
    if (z > 0) {
        analogWrite(bottomLed, z*4);
        analogWrite(frontLed, 0);        
    } else {
        analogWrite(frontLed, z*4*-1);    
        analogWrite(bottomLed, 0);    
    }   
}

void dmpDataReady()
{
    mpuInterrupt = true;
}

 

 
Всё работает (но если осталось ещё что-то лишнее, подскажите - вырежу).
 
Моя же задача сводится к тому, чтобы датчик управлял диодами относительно положения, в котором он находился при включении, а не относительно горизонта. Ну и направлять на светодиоды не аналоговый сигнал, а цифровой.
 
Попробовал собрать такой вариант:
 
const int frontLed = 3;
const int bottomLed = 5;
const int rightLed = 6;
const int leftLed = 9;
int x1;
int y1;
int z1;
long int lastPrintTime;

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif

MPU6050 mpu;

bool dmpReady = false;
uint8_t mpuIntStatus;
uint8_t devStatus;
uint16_t packetSize;
uint16_t fifoCount;
uint8_t fifoBuffer[64];

// orientation/motion vars
Quaternion q;
VectorInt16 aa;
VectorInt16 aaReal;
VectorInt16 aaWorld;
VectorFloat gravity;
float euler[3];
float ypr[3];
volatile bool mpuInterrupt = false;

void setup()
{
    #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(9600);
    while (!Serial);
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();
    mpu.setXGyroOffset(220);
    mpu.setYGyroOffset(76);
    mpu.setZGyroOffset(-85);
    mpu.setZAccelOffset(1788);
    if (devStatus == 0) {
        // turn on the DMP, now that it's ready
        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);
        Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
        attachInterrupt(0, dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();
        Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
    }
    initializeLEDsSimple();
    lastPrintTime = millis();


    if (!dmpReady) return;
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    fifoCount = mpu.getFIFOCount();
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));
    } else if (mpuIntStatus & 0x02) {
        while (fifoCount < packetSize) {
          fifoCount = mpu.getFIFOCount();
        }
        mpu.getFIFOBytes(fifoBuffer, packetSize);      
        fifoCount -= packetSize;
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        x1 = ypr[0] * 180/M_PI;
        y1 = ypr[1] * 180/M_PI;
        z1 = ypr[2] * 180/M_PI;
        Serial.print(y1);Serial.print("\t");Serial.println(z1);
        }
}

void loop()
{
    if (!dmpReady) return;
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    fifoCount = mpu.getFIFOCount();
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));
    } else if (mpuIntStatus & 0x02) {
        while (fifoCount < packetSize) {
          fifoCount = mpu.getFIFOCount();
        }
        mpu.getFIFOBytes(fifoBuffer, packetSize);      
        fifoCount -= packetSize;
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        int x = ypr[0] * 180/M_PI;
        int y = ypr[1] * 180/M_PI;
        int z = ypr[2] * 180/M_PI;
        Serial.print(y);Serial.print("\t");Serial.println(z); 
        flashLEDsSimple(x, y, z, x1, y1, z1);
        }
}

void initializeLEDsSimple()
{
    pinMode(frontLed, OUTPUT);
    pinMode(bottomLed, OUTPUT);  
    pinMode(rightLed, OUTPUT);
    pinMode(leftLed, OUTPUT);
}

void flashLEDsSimple(int x, int y, int z, int x1, int y1, int z1)
{
    if (y1 > y) {
        digitalWrite(rightLed, 1);
        digitalWrite(leftLed, 0);         
    } else {
        digitalWrite(leftLed, 1);    
        digitalWrite(rightLed, 0);    
    }
    if (z1 > z) {
        digitalWrite(bottomLed, 1);
        digitalWrite(frontLed, 0);        
    } else {
        digitalWrite(frontLed, 1);    
        digitalWrite(bottomLed, 0);    
    }   
}

void dmpDataReady()
{
    mpuInterrupt = true;
}

 

Помогите, пожалуйста.
Заранее спасибо!
andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

WinterBreeze пишет:

Моя же задача сводится к тому, чтобы датчик управлял диодами относительно положения, в котором он находился при включении, а не относительно горизонта.

Ну так запоминайте положение при включении и вычисляйте текущее положение относительно  него.