Arduino Uno + MPU6050 + Adafruit nRF8001

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
FredCH
 
Posts: 3
Joined: Sun Jul 27, 2014 7:03 pm

Arduino Uno + MPU6050 + Adafruit nRF8001

Post by FredCH »

Hi,
I have a project running smoothly Arduino Uno + MPU6050 (GY-521) + Sparkfun "normal" bluetooth as a RX TX pipe. This week I tried to update it to a more convenient BLE, and your nRF8001 Breakout looked perfect for the job :)
I had no problem testing the breakout with the examples provided on Adafruit's website.
However, I cannot adapt the sketch to write the MPU6050 info via BLE. It was probably a step too far, so... can you help me?
The first problem happens already in the setup() in the line BTLEserial.begin(), Arduino says that "BTLEserial was not declared in this scope". Do you think it could be a conflict between the libraries Wire.h, I2Cdev.h, SPI.h and Adafruit_BLE_UART.h?
I can post the full sketch if it helps.
Thanks in advance!
Fred

User avatar
Franklin97355
 
Posts: 23938
Joined: Mon Apr 21, 2008 2:33 pm

Re: Arduino Uno + MPU6050 + Adafruit nRF8001

Post by Franklin97355 »

Could you post your code and a description or drawing of your connections between it all?
Please use the code button "</>" as shown below.
Code Button.jpg
Code Button.jpg (4.49 KiB) Viewed 1590 times

FredCH
 
Posts: 3
Joined: Sun Jul 27, 2014 7:03 pm

Re: Arduino Uno + MPU6050 + Adafruit nRF8001

Post by FredCH »

I think things look better now, hopefully it's a small mistake. I can compile and upload the code below. I start the MPU6050 in the Arduino Serial Monitor, which also kicks-off the nRF UART iOS app. The only problem is that I cannot get proper results from the MPU6050, only zeros (both on the Serial Monitor and on my iPhone). I guess the problem is on my poor handling of data over SPI, between bytes and values. Any ideas how to fix the sketch? THANKS in advance for your support.

Code: Select all

/*
MPU6050 – Arduino Uno
VCC – 5V
GND – GND
SDA – A4
SCL – A5
XDA – none
XCL – none
ADO – none
INT – D2

Adafruit nRF8001 - Arduino Uno
SCK – D13
MISO – D12
MOSI – D11
REQ – D10
RDY – D3
ACT – none
RST – D9
3Vo – none
GNC – GND
VIN – 3.3V

Source:
MPU-6050 data based on I2Cdev device library code by Jeff Rowberg
nRF8001 data based on library code by Kevin Townsend/KTOWN  for Adafruit Industries
*/

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include <Wire.h>

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include <I2Cdev.h>

#include <MPU6050_6Axis_MotionApps20.h>
// #include <MPU6050.h> // not necessary if using MotionApps include file

// 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;

// yaw/pitch/roll angles (in degrees) calculated from the quaternions coming
// from the FIFO. Note this also requires gravity vector calculations.
// Also note that yaw/pitch/roll angles suffer from gimbal lock
#define OUTPUT_READABLE_YAWPITCHROLL

// 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
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

// ================================================================
// ===           MPU-6050 INTERRUPT DETECTION ROUTINE           ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

// ================================================================
// ===                 Adafruit nRF8001 SETUP                   ===
// ================================================================

// This version uses the internal data queing so you can treat it like Serial (kinda)!

#include <SPI.h>
#include "Adafruit_BLE_UART.h"

// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 3
#define ADAFRUITBLE_RST 9

Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {

  // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();

    // initialize serial communication
    Serial.begin(115200);
    while (!Serial);

    // initialize nRF8001
    BTLEserial.begin();
    SPI.begin();
  
    // initialize device
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();

    // verify connection
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection 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();
    
    // 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! Welcome back :) \t 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);
}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {
    // Tell the nRF8001 to do whatever it should be working on.
    BTLEserial.pollACI();

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // 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) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        // transfer information to nRF8001
        Serial.println("FIFO overflow!");

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {

        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // 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;

        // get Euler angles in degrees and real acceleration
        // FW: 1g = 4096 in default +/- 2g setting
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetAccel(&aa, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        
        // transfer information to nRF8001
        BTLEserial.write(ypr[0] * 180/M_PI);
        BTLEserial.write(ypr[1] * 180/M_PI);
        BTLEserial.write(ypr[2] * 180/M_PI);
        BTLEserial.write(aaReal.x);
        BTLEserial.write(aaReal.y);
        BTLEserial.write(aaReal.z);
      } 
    }

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: Arduino Uno + MPU6050 + Adafruit nRF8001

Post by adafruit_support_mike »

The BTLE 'write()' function takes a string length as its second parameter. Try changing these lines to 'print()':

Code: Select all

        // transfer information to nRF8001
        BTLEserial.write(ypr[0] * 180/M_PI);
        BTLEserial.write(ypr[1] * 180/M_PI);
        BTLEserial.write(ypr[2] * 180/M_PI);
        BTLEserial.write(aaReal.x);
        BTLEserial.write(aaReal.y);
        BTLEserial.write(aaReal.z);

FredCH
 
Posts: 3
Joined: Sun Jul 27, 2014 7:03 pm

Re: Arduino Uno + MPU6050 + Adafruit nRF8001

Post by FredCH »

Thanks a lot! Problem solved. Well, sort of.
I found on GitHub that Marco Schwartz created the function BTLEserial.print() only 2 weeks ago, so I didn't have it in my previous library (I'm assuming this is the right terminology).
Now I'll work on the processing and communication speed limits: I keep on getting "FIFO Overflow" on the MPU6050 and 0x83 (asynchronous hardware error event) / 0x91 (not connected?) error messages on the nRF8001. I guess the MPU6050 is working much faster than the nRF8001 can publish its data to my iPhone...
Hopefully soon I'll be able to make the nRF UART work in sync with the Arduino Serial Monitor.
Kind regards,
Fred

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: Arduino Uno + MPU6050 + Adafruit nRF8001

Post by adafruit_support_mike »

You can also use the write() method if you add the length of the string as a second parameter. Your previous version was basically telling write() you wanted to send zero bytes per call.

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”