Arduino Zero Code Problems

I bought an Arduino Zero recently to put in my quadcopter, but when I compiled my code, nothing showed up on the Serial Monitor. It only showed "Initializing I2C devices..." and that is it. However when ran on my Arduino Uno, it goes past that, and then displays the values of the gyro.

There were lots of wires plugged into the board (Zero), so I decided to run a sample program for the MPU6050. I had the MPU6050 wired up to the Zero like so, and compiled and uploaded the following program with no problems.

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
// 10/7/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//      2013-05-08 - added multiple output formats
//                 - added seamless Fastwire support
//      2011-10-07 - initial release

/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/

// 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.h"

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#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 InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high

int16_t ax, ay, az;
int16_t gx, gy, gz;



// uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated
// list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read,
// not so easy to parse, and slow(er) over UART.
#define OUTPUT_READABLE_ACCELGYRO

// uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit
// binary, one right after the other. This is very fast (as fast as possible
// without compression or data loss), and easy to parse, but impossible to read
// for a human.
//#define OUTPUT_BINARY_ACCELGYRO


#define LED_PIN 13
bool blinkState = false;

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(115200);

    // initialize device
    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

    // use the code below to change accel/gyro offset values
    /*
    Serial.println("Updating internal sensor offsets...");
    // -76	-2359	1688	0	0	0
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    accelgyro.setXGyroOffset(220);
    accelgyro.setYGyroOffset(76);
    accelgyro.setZGyroOffset(-85);
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    */

    // configure Arduino LED for
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    // these methods (and a few others) are also available
    //accelgyro.getAcceleration(&ax, &ay, &az);
    //accelgyro.getRotation(&gx, &gy, &gz);

    #ifdef OUTPUT_READABLE_ACCELGYRO
        // display tab-separated accel/gyro x/y/z values
        Serial.print("a/g:\t");
        Serial.print(ax); Serial.print("\t");
        Serial.print(ay); Serial.print("\t");
        Serial.print(az); Serial.print("\t");
        Serial.print(gx); Serial.print("\t");
        Serial.print(gy); Serial.print("\t");
        Serial.println(gz);
    #endif

    #ifdef OUTPUT_BINARY_ACCELGYRO
        Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
        Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
        Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
        Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
        Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
        Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
    #endif

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

When ran how ever it only shows "Initializing I2C devices..."

I then swapped the Zero with an Uno and re uploaded the sketch, and ran it.

It ran perfectly displaying the raw values of the accel and gyro sensors.

To make sure something wasn't broken, I ran the following little program on the Zero.

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  Serial.println("HIGH");   // send the state to the serial monitor
  delay(2000);              // wait for two second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  Serial.println("LOW");
  delay(500);
  
}

That run fine, as it displayed the high and low values.

Is there something different about the Zero on how it runs serial commands, or is something else the problem?

I am using the programming port on the Zero.

I have included a photo of my set up on the Arduino IDE

Here's the thing: the Zero is a 3V3 model, while the uno is 5V. If you have a multimeter (analog or digital) handy, check the SDA, SCL, and INT pins of the IMU. If they're more than 3V3, you have a fried board, unless you are really lucky. In that case, buy another one, and use something like this. Also, instead of using analog 4 and 5, hook up the IMU's SDA to the Zero's SDA and the IMU's SCL to the Zero's SCL (positioned near digital pin 13). On the Zero, 4 & 5 are just analog pins.

I checked the SCL and SDA pins on the MPU, and they were at 3.0V (3.4V when the MPU was supplied with 5V). So I didn't fry the board.

My program seems to stop when it encounters anything to do with the MPU. It will stop on line 111 of QuadMain. That is what is seems like, as it doesn't output the other line on the serial monitor. It looks like its getting stuck in MPU library, but I am going to have to do I little more debugging to confirm.

It could be a problem with the SCL and SDA pins plugged into ports A4 and A5 (like you said), but the Zero should have the same pinout as the Uno. Do they?

I also tried the program with the SCL and SDA pins plugged into the SCL and SDA pins of the Zero, but with no luck.

I would modify the MPU6050 and I2Cdev libraries to work with the Zero, but I wasn't the one who wrote the libraries, so modifying it would be a little difficult. Plus the library code is a little above my coding knowledge.

Any suggestions?

You have to use the SCL and SDA pins on the Zero. Pins A4 and A5 are not an I2C port.

I tried it plugged into the SCL and SDA pins on the Zero, and it does the same thing it did when it was plugged into A4 & A5.

Is your problem solved ?

HailStorm:
Is there something different about the Zero on how it runs serial commands, or is something else the problem?

Yes.
Serial.print() shows the print through the programming port.
SerialUSB.print() shows the print through the native port.

Where you have connected the serial monitor?

totolens:
Is your problem solved ?

No it is not solved. Unfortunately :slightly_frowning_face:

PaoloP:
Yes.
Serial.print() shows the print through the programming port.
SerialUSB.print() shows the print through the native port.

Where you have connected the serial monitor?

I have it connected to the programming port. Plus my program only uses Serial.print(), so don't think it is the problem.

UPDATE:

When the program encounters anything to do with the gyro library it seems to get "stuck" (for lack of a better work).

For example, in the QuadMain program, it will seem to stop at line 111, but will execute everything before that. If I comment out line 111, it will continue on, and then get stuck again at line 115.

I have gone through with a debugger, and stepped through my code, but when I get to a gyro related piece of code (i.e. line 111), I can step into it fine and it seems to be executing things properly. Note that I haven't followed it until it comes back out at line 114, because it seems to go on forever.

The code compiles fine, and it worked fine on my Uno, so I am not sure what the problem is.

Here are the the libraries I am using: MPU6050 & I2Cdev
Any help?

see this thread on what I had to do to get I2C working on ZERO

Hi Hailstorm,

I connected my Zero up to my MPU6050:

Zero -> MPU6050
3.3v -> VCC
GND -> GND
SCL -> SCL
SDA -> SDA

Note that my MPU6050 breakout has on-board pull-up resistors on SCL and SDA.

The following sketch outputs the raw 3-axis gyro and accelerometer values:

#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>

MPU6050 accelGyro;                                        // Instansiate the MPU6050 object
int16_t ax, ay, az, gx, gy, gz;                           // Create the 3 axis gyro/accel variables

void setup() {
  Serial.begin(115200);                                   // Initialise the serial port
  Wire.begin();                                           // Initialise the wire library
  accelGyro.initialize();                                 // Initialise the gyro and accelerometer
  //accelGyro.setRate(0x00);                              // Set sampling rate, not used here  
  accelGyro.setDLPFMode(0x04);                            // Set digital low pass filter to 20Hz  
  accelGyro.setFullScaleGyroRange(0x01);                  // Set gyro full scale range to +/-500 degrees/s
  accelGyro.setFullScaleAccelRange(0x01);                 // Set accelerometer full scale range to +/-4g     
  accelGyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);     // Discard the first set of results as they are incorrect
}

void loop() {
  accelGyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);     // Read the gyro and acceleromter
  Serial.print(ax);                                       // Output the results to the console
  Serial.print(F("   "));
  Serial.print(ay);
  Serial.print(F("   "));
  Serial.print(az);
  Serial.print(F("   "));
  Serial.print(gx);
  Serial.print(F("   "));
  Serial.print(gy);
  Serial.print(F("   "));
  Serial.println(gz);
  delay(1000);
}

This sketch worked on my Zero.

I downloaded the latest nightly build, and uploaded the program that @MartinL posted, and his program works fine.

I then uploaded my program and it still seems to stop at line 111. :sob:

I am REALLY at a loss right now as I have no idea what is causing this. What gets me really confused is that it works fine on my Uno, but not on my Zero. What is so different about the Uno and the Zero that would make the code not work?

Any help?

Hi HailStorm,

When you say that my program worked, was that on the Uno or Zero?

I just ran your program on my Zero, it works perfectly and outputs the following:

a/g: -696 12 17076 -154 21 -111
a/g: -720 -12 16932 -170 -28 -127
a/g: -668 112 16920 -151 -12 -148
a/g: -624 4 17080 -153 6 -115
a/g: -756 20 16912 -153 -13 -127
a/g: -640 88 16964 -154 -26 -125
a/g: -688 172 16964 -163 8 -123
a/g: -720 72 16916 -162 -2 -116
a/g: -740 40 16972 -158 -19 -138

You can see the gravity acting on the accelerometer's z-axis.

It's now just a process of elimination. If the code works on the UNO then this suggests that the MPU6050 is OK and you're addressing it correctly, (I2C address 0x68). As the Wire, I2CDev and MPU6050 libraries work on both Uno and Zero, it must be something to do with your Zero's I2C. Do you have another I2C device that you can test on your Zero?

MartinL:
When you say that my program worked, was that on the Uno or Zero?

Yes it worked on the Zero.

MartinL:
I just ran your program on my Zero, it works perfectly and outputs the following:

If you ran my quad code it should have looked like this:

Initializing I2C devices...
Testing device connections...
MPU6050 connection successful
Initializing DMP...
Enabling DMP...
Enabling interrupt detection (Arduino external interrupt 0)...
DMP ready! Waiting for first interrupt...
FIFO overflow!
-87.92, 79.73, 5.95
Calibrating Gyro....
-77, -97, 89
, 69, 15, -5
FIFO overflow!
115.15, 84.60, -1.61
115.15, 84.60, -1.61
115.15, 84.60, -1.61

At least that's what it looks like when ran on an Uno.

Running it on a Zero (for me) just show this:

Initializing I2C devices...

And it just stays like that, even if I reset the board.

MartinL:
Do you have another I2C device that you can test on your Zero?

I unfortunately do not.

Should I contact support and tell them I have a defective board?

@HailStorm it looks like there are several breakout boards for the MPU-6050. Which are you using?

mantoui:
@HailStorm it looks like there are several breakout boards for the MPU-6050. Which are you using?

It has been a little over a year since I purchased it, so I don't know where I bought it from, but this is the one I have (they look identical).

Also you mentioned in this post that you were able to fix the problem by adding a 4.7k ohm pull up resistor on SCL and SDA. Would doing the same on my board fix anything? If so, would I pull up using 3.3v or 5v, and would 4.5k ohms work instead? I don't have any 4.7k's laying around, so I would have to put some 1k's and 330's in series.

I think the issue here might be due to the different ways the MPU6050 can be accessed.

You can either call on the device to give you the raw gyro and accelerometer values, say every loop{} using the getMotion6(), getRotation() and getAcceration() functions, or use its in-build Digital Motion Processor (DMP) to process the results for you. The DMP loads the Euler angles, quaternions, etc... into the MPU6050's FIFO buffer and flags that the contents are ready with the it's DRDY (data ready) interrupt.

The raw values are just the digitized gyro and accelerometer outputs, these need to be converted to degrees/s for the gyro and degrees for the accelerometer in your own Arduino sketch.

An excellent source of information for understanding the MPU6050 is the Geek Mom Projects website, (geekmomprojects.com).

Jeff Rowberg who wrote the MPU6050 library also produced two really useful sketch examples, MPU6050_raw and MPU6050_DMP6.

If your flight control firmware is using the DMP, it may be expecting a DRDY interrupt on one of its pins?

HailStorm:
It has been a little over a year since I purchased it, so I don't know where I bought it from, but this is the one I have (they look identical).

Also you mentioned in this post that you were able to fix the problem by adding a 4.7k ohm pull up resistor on SCL and SDA. Would doing the same on my board fix anything? If so, would I pull up using 3.3v or 5v, and would 4.5k ohms work instead? I don't have any 4.7k's laying around, so I would have to put some 1k's and 330's in series.

There is some discussion of GY-521 here
The discussion suggests that breakout board might best be fed with 5v (it has a regulator to convert to 3.3). The schematic provided there indicates it has pullups.
Earlier in this thread, you said you were measuring 3.3+v on SCL/SDA with everything connected and powered up, that would suggest there are pullups. board must be connected to SCL/SDA (NOT A4/A5)

So I was looking through the MPU6050_DMP6 example sketch to see if I missed any code from it (I took some of the code from there, and used it in my quad code), and found that I had commented out some (apparently important) lines of code.

// join I2C bus (I2Cdev library doesn't do this automatically)
    #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

So I uncommented that, and added a variable (it was complaining about "TWBR") and now it works. :smiley:

Wish I would have checked that earlier. :-[

Thanks to everyone who helped me, it helped a lot. :slight_smile:

Glad to hear you got it working. Good luck with your flight controller project.