MPU6050 Acceleration meter range

[SOLVED]
Jeff was totally right. I need to use the "mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);" after the initialization of the MPU6050 to set the range to +-16g.
It works! Thanks Jeff!

Hi All,

I need help setting the range from 2g to 16g on the MPU6050.
I'm trying to do it with the "mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);". Also tried it with writing to the 0x1c address of the MPU6050. No luck.
I'm trying it on an Arduino Mega.
Also tried with "mpu.setFullScaleAccelRange(3)" but no luck.
Any idea?

#include "MPU6050_6Axis_MotionApps20.h"

void setup() {
    Serial.begin(115200);
    Serial.print(" Eredeti:");
    Serial.print(mpu.getFullScaleAccelRange());
    Serial.println();
//  Wire.begin(MPU6050_ADDRESS);
//  Wire.beginTransmission(MPU6050_ADDRESS);
//  Wire.write(0x1c),Wire.write(0x02);
//  Wire.endTransmission();
//  Wire.requestFrom(MPU6050_ADDRESS, 1);
  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
  delay(1000);
  Serial.print(" Jelenlegi:");
  Serial.print(mpu.getFullScaleAccelRange());
  Serial.println();
  mpu.initialize();
  }
void loop()
{
}

With the following code I got back the '3' when I check the register, but still can't measure more than 2 G.

Any help would be great!

Kindest Regards,

Brucez

#include <I2C.h>

/*
  mpuAccelerometerDemo
  Based on the MPU6050_DMP6 "teapot demo" code
*/


/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 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.
===============================================
*/

// 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" // replaces and enhances the "MPU6050.h"
//#include "MPU6050.h"
#define MPU6050_ADDRESS 0x68
#define MPU6050_ACCEL_CONFIG       0x1C   // R/W
#define MPU6050_AFS_SEL0   MPU6050_D3
#define MPU6050_AFS_SEL1   MPU6050_D4
#define MPU6050_D0 0
#define MPU6050_D1 1
#define MPU6050_D2 2
#define MPU6050_D3 3
#define MPU6050_D4 4
#define MPU6050_D5 5
#define MPU6050_D6 6
#define MPU6050_D7 7
uint8_t range=3;
MPU6050 mpu;

//define OUTPUT_TEAPOT

#define ACCELERATION_FROM_FIFO
#define LED_PIN 13 // Using the LED to light up on any error (critical or non critical)


// 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 (not all are needed in this demo)
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

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '

, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

// packet structure for the AccelerometerDemo
uint8_t accelerometerPacket[10] = { 'A', 0,0, ';', 0,0, ';', 0,0, '\n' };

// ================================================================
// ===              INTERRUPT DETECTION ROUTINE                ===
// ================================================================

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

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

void setup() {
    Serial.begin(115200);
    Serial.print(" Eredeti:");
    Serial.print(mpu.getFullScaleAccelRange());
    Serial.println();
  Wire.begin(MPU6050_ADDRESS);
//  Wire.beginTransmission(MPU6050_ADDRESS);
//  Wire.write(0x1c),Wire.write(0x03);
//  Wire.endTransmission();
//  Wire.requestFrom(MPU6050_ADDRESS, 1);
  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
  delay(1000);
  Serial.print(" Jelenlegi:");
  Serial.print(mpu.getFullScaleAccelRange());
  Serial.println();
  mpu.initialize();
 
//while(Wire.available())    // slave may send less than requested
//  {
//    char c = Wire.read();    // receive a byte as character
//    Serial.print(c,HEX);        // print the character
//  }
//  Serial.print("ennyi?");
  delay(5000);

//MPU6050_write_reg (MPU6050_AFS_SEL0,3);
//  LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_CONFIG, 0x03);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

Wire.begin();
  Serial.begin(115200);
  while (!Serial); // wait for Leonardo enumeration, others continue immediately

// initialize device

// verify connection
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

// DEAD: 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
  devStatus = mpu.dmpInitialize();
   
  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
    // turn on the DMP, now that it's ready
    mpu.setDMPEnabled(true);

// enable Arduino interrupt detection
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows it's okay to use it
    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)
    digitalWrite(LED_PIN, HIGH);
    //Serial.print(F("DMP Initialization failed (code "));
    //Serial.print(devStatus);
    //Serial.println(F(")"));
  }

}

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

void loop() {
/*    // 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) {
*/
//          TEST
  Serial.print("X: ");
  Serial.print((mpu.getAccelerationX()/8092));
  Serial.print("  Y: ");
  Serial.print((mpu.getAccelerationY()/8092));
  Serial.print("  Z: ");
  Serial.println((mpu.getAccelerationZ()/8092));
delay(100);

}

It looks like you're calling mpu.initialize() after you set the full-scale accel range, which will reset it back to 2g.

Additionally, I am not sure you can count on using any particular range if you then go on to use the DMP, which is a finely tuned algorithm which probably depends on a specific range value. The mpu.dmpInitialize() method does a whole lot with the MPU, including some sensitivity settings. Changing the sensitivity probably only matters if you are using raw readings.

Ah I see!
Ok, I'll do some tests and I'll post what I've found. Thanks Jeff for the fast reply! :slight_smile:

Brucez:
Ah I see!
Ok, I'll do some tests and I'll post what I've found. Thanks Jeff for the fast reply! :slight_smile:

Can you tell me your findings? Did it influence something?

Also, I'm wondering about the sensitivity range. While experimenting with it I get the impression that the range which is written like +/-2g is actually -1g and +1g so that it becomes 2g total sensitivity range.
Do I see this right or is it -2g and +2g?

edit
I just found a very related link

Here is a quick and dirty fix for setting sensitivity of MPU6050 using just Wire library.

#include<Wire.h>

const int MPU_addr=0x68; // I2C address of the MPU-6050

void setup(){
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);

//start serial
Serial.begin(9600);

//set sensitivity @ address 1C
Wire.beginTransmission(MPU_addr);
Wire.write(0x1C);
Wire.write(B00010000); //here is the byte for sensitivity (8g here) check datasheet for the one u want
Wire.endTransmission(true);

//sanity check sensitivity register
Wire.beginTransmission(MPU_addr);
Wire.write(0x1C);
Wire.endTransmission(true);

Wire.requestFrom(MPU_addr, 1);
if(Wire.available()){
accelSet = Wire.read();

//very poor code that bitshifts and reads each bit in the sensitivity register :smiley:
for(int y = 0; y<8; y++){
if((accelSet & 0x80) == 128)
{
Serial.print(1);
}
else Serial.print(0);
accelSet = accelSet << 1;
}
Serial.println();
}

}

Hi,

I ask to the experts (because I'm a newbie and don't know this) where should I put the string:

mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);

In the .ino file? In the mpu6050.h file? I cannot change accel/gyro range yet.. If you can share sketch, that will be helpfull.

Thanks for your time.

Dario

Example : MPU6050_raw.ino by Jeff Rowberg jeff@rowberg.net

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

Serial.begin(38400);

// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_8);
// accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
}

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

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

Testing device connections...
MPU6050 connection successful
a/g: 0.004 -0.019 0.951 -450 -45 207
a/g: 0.005 -0.013 0.943 -444 -77 211

Hi all, this code will change the accelerometer range to 16G and the Gyro range to 2000 degrees per sec.

The only thing that needs to be changed in this code is the offsets for the accelerometer and the GYRO for your sensor using the IMU_Zero code provided by Jeff. Using this I get 1 g in Z axis, and 0, 0, 0 for the gyro. Cheers !

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

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(38400);

// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
Serial.print("Initial Range= ");
Serial.println(accelgyro.getFullScaleAccelRange());
Serial.println(accelgyro.getFullScaleGyroRange());

//These lines sets the scale of the Accelerometer to 16g and Gyro to 2000 rads per second
//These lines are to be put after the accelgyro.initialize method.
accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
//
Serial.print("New Range= ");
Serial.println(accelgyro.getFullScaleAccelRange());// Print the current range
Serial.println(accelgyro.getFullScaleGyroRange());
// 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
//This part prints the current offsets
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");

// This part updates the offsets.
accelgyro.setXGyroOffset(110);
accelgyro.setYGyroOffset(200);
accelgyro.setZGyroOffset(1411);
accelgyro.setXAccelOffset(2923);
accelgyro.setYAccelOffset(555);
accelgyro.setZAccelOffset(1479);

//Verify that the offsets are updated
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");

}

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

Serial.print(ax/2048.0); Serial.print("\t");//For FS_16 the divider is 2048.0
Serial.print(ay/2048.0); Serial.print("\t");
Serial.print(az/2048.0); Serial.print("\t");

Serial.print(gx/16.40); Serial.print("\t");// For Gyro range = 2000, divider is 16.4
Serial.print(gy/16.40); Serial.print("\t");
Serial.println(gz/16.40);

}

I am attaching images of readings for upright and upside down position of the accelerometer

Try this code. It's a simple code I have written using wire.h library which lets the developer choose the sensitivity for both accelerometer and gyroscope.

All the best.