MPU6050 Interfacing with NodeMCU
Introduction
MPU6050 Module
MPU6050 sensor module is an integrated 6-axis Motion tracking device.
- It has a 3-axis Gyroscope, 3-axis Accelerometer, Digital Motion Processor and a Temperature sensor, all in a single IC.
- It can accept inputs from other sensors like 3-axis magnetometer or pressure sensor using its Auxiliary I2C bus.
- If external 3-axis magnetometer is connected, it can provide complete 9-axis Motion Fusion output.
Gyroscope and accelerometer reading along X, Y and Z axes are available in 2’s complement form.
Temperature reading is available in signed integer form (not in 2’s complement form).
Gyroscope readings are in degrees per second (dps) unit; Accelerometer readings are in g unit; and Temperature reading is in degrees Celsius.
For more information about MPU6050 Sensor Module and how to use it, refer the topic MPU6050 Sensor Module in the sensors and modules section.
A NodeMCU can communicate with this module using I2C communication protocol. To know more about I2C functions in NodeMCU refer NodeMCU I2C with ESPlorer IDE or NodeMCU I2C with Arduino IDE
Interfacing Diagram
NodeMCU Interface with MPU6050
Example
Reading Accelerometer, Gyroscope and Temperature parameters from the MPU6050 module and displaying them on Serial Monitor.
First, do the connections as shown in above interfacing diagram.
Now let’s write program for reading accelero, gyro and temperature values from MPU6050.
We can write codes for NodeMCU DevKit in either Lua Script or C/C++ language. We are using ESPlorer IDE for writing code in Lua scripts and Arduino IDE for writing code in C/C++. To know more refer Getting started with NodeMCU using ESPlorer IDE (which uses Lua scripting for NodeMCU) and Getting started with NodeMCU using Arduino IDE (which uses C/C++ language based Arduino sketches for NodeMCU).
Lua Script for NodeMCU
id = 0 -- always 0
scl = 6 -- set pin 6 as scl
sda = 7 -- set pin 7 as sda
MPU6050SlaveAddress = 0x68
AccelScaleFactor = 16384; -- sensitivity scale factor respective to full scale setting provided in datasheet
GyroScaleFactor = 131;
MPU6050_REGISTER_SMPLRT_DIV = 0x19
MPU6050_REGISTER_USER_CTRL = 0x6A
MPU6050_REGISTER_PWR_MGMT_1 = 0x6B
MPU6050_REGISTER_PWR_MGMT_2 = 0x6C
MPU6050_REGISTER_CONFIG = 0x1A
MPU6050_REGISTER_GYRO_CONFIG = 0x1B
MPU6050_REGISTER_ACCEL_CONFIG = 0x1C
MPU6050_REGISTER_FIFO_EN = 0x23
MPU6050_REGISTER_INT_ENABLE = 0x38
MPU6050_REGISTER_ACCEL_XOUT_H = 0x3B
MPU6050_REGISTER_SIGNAL_PATH_RESET = 0x68
function I2C_Write(deviceAddress, regAddress, data)
i2c.start(id) -- send start condition
if (i2c.address(id, deviceAddress, i2c.TRANSMITTER))-- set slave address and transmit direction
then
i2c.write(id, regAddress) -- write address to slave
i2c.write(id, data) -- write data to slave
i2c.stop(id) -- send stop condition
else
print("I2C_Write fails")
end
end
function I2C_Read(deviceAddress, regAddress, SizeOfDataToRead)
response = 0;
i2c.start(id) -- send start condition
if (i2c.address(id, deviceAddress, i2c.TRANSMITTER))-- set slave address and transmit direction
then
i2c.write(id, regAddress) -- write address to slave
i2c.stop(id) -- send stop condition
i2c.start(id) -- send start condition
i2c.address(id, deviceAddress, i2c.RECEIVER)-- set slave address and receive direction
response = i2c.read(id, SizeOfDataToRead) -- read defined length response from slave
i2c.stop(id) -- send stop condition
return response
else
print("I2C_Read fails")
end
return response
end
function unsignTosigned16bit(num) -- convert unsigned 16-bit no. to signed 16-bit no.
if num > 32768 then
num = num - 65536
end
return num
end
function MPU6050_Init() --configure MPU6050
tmr.delay(150000)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SMPLRT_DIV, 0x07)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_1, 0x01)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_2, 0x00)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_CONFIG, 0x00)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_GYRO_CONFIG, 0x00)-- set +/-250 degree/second full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_CONFIG, 0x00)-- set +/- 2g full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_FIFO_EN, 0x00)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_INT_ENABLE, 0x01)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SIGNAL_PATH_RESET, 0x00)
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_USER_CTRL, 0x00)
end
i2c.setup(id, sda, scl, i2c.SLOW) -- initialize i2c
MPU6050_Init()
while true do --read and print accelero, gyro and temperature value
data = I2C_Read(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_XOUT_H, 14)
AccelX = unsignTosigned16bit((bit.bor(bit.lshift(string.byte(data, 1), 8), string.byte(data, 2))))
AccelY = unsignTosigned16bit((bit.bor(bit.lshift(string.byte(data, 3), 8), string.byte(data, 4))))
AccelZ = unsignTosigned16bit((bit.bor(bit.lshift(string.byte(data, 5), 8), string.byte(data, 6))))
Temperature = unsignTosigned16bit(bit.bor(bit.lshift(string.byte(data,7), 8), string.byte(data,8)))
GyroX = unsignTosigned16bit((bit.bor(bit.lshift(string.byte(data, 9), 8), string.byte(data, 10))))
GyroY = unsignTosigned16bit((bit.bor(bit.lshift(string.byte(data, 11), 8), string.byte(data, 12))))
GyroZ = unsignTosigned16bit((bit.bor(bit.lshift(string.byte(data, 13), 8), string.byte(data, 14))))
AccelX = AccelX/AccelScaleFactor -- divide each with their sensitivity scale factor
AccelY = AccelY/AccelScaleFactor
AccelZ = AccelZ/AccelScaleFactor
Temperature = Temperature/340+36.53-- temperature formula
GyroX = GyroX/GyroScaleFactor
GyroY = GyroY/GyroScaleFactor
GyroZ = GyroZ/GyroScaleFactor
print(string.format("Ax:%.3g Ay:%.3g Az:%.3g T:%.3g Gx:%.3g Gy:%.3g Gz:%.3g",
AccelX, AccelY, AccelZ, Temperature, GyroX, GyroY, GyroZ))
tmr.delay(100000) -- 100ms timer delay
end
ESPlorer Serial Output Window
Output window of ESPlorer IDE serial window for above lua script is shown below
Ax = Accelerometer x axis data in g unit
Ay = Accelerometer y axis data in g unit
Az = Accelerometer z axis data in g unit
T = temperature in degree/celcius
Gx = Gyro x axis data in degree/seconds unit
Gy = Gyro y axis data in degree/seconds unit
Gz = Gyro z axis data in degree/seconds unit
Arduino Sketch for NodeMCU
#include <Wire.h>
// MPU6050 Slave Device Address
const uint8_t MPU6050SlaveAddress = 0x68;
// Select SDA and SCL pins for I2C communication
const uint8_t scl = D6;
const uint8_t sda = D7;
// sensitivity scale factor respective to full scale setting provided in datasheet
const uint16_t AccelScaleFactor = 16384;
const uint16_t GyroScaleFactor = 131;
// MPU6050 few configuration register addresses
const uint8_t MPU6050_REGISTER_SMPLRT_DIV = 0x19;
const uint8_t MPU6050_REGISTER_USER_CTRL = 0x6A;
const uint8_t MPU6050_REGISTER_PWR_MGMT_1 = 0x6B;
const uint8_t MPU6050_REGISTER_PWR_MGMT_2 = 0x6C;
const uint8_t MPU6050_REGISTER_CONFIG = 0x1A;
const uint8_t MPU6050_REGISTER_GYRO_CONFIG = 0x1B;
const uint8_t MPU6050_REGISTER_ACCEL_CONFIG = 0x1C;
const uint8_t MPU6050_REGISTER_FIFO_EN = 0x23;
const uint8_t MPU6050_REGISTER_INT_ENABLE = 0x38;
const uint8_t MPU6050_REGISTER_ACCEL_XOUT_H = 0x3B;
const uint8_t MPU6050_REGISTER_SIGNAL_PATH_RESET = 0x68;
int16_t AccelX, AccelY, AccelZ, Temperature, GyroX, GyroY, GyroZ;
void setup() {
Serial.begin(9600);
Wire.begin(sda, scl);
MPU6050_Init();
}
void loop() {
double Ax, Ay, Az, T, Gx, Gy, Gz;
Read_RawValue(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_XOUT_H);
//divide each with their sensitivity scale factor
Ax = (double)AccelX/AccelScaleFactor;
Ay = (double)AccelY/AccelScaleFactor;
Az = (double)AccelZ/AccelScaleFactor;
T = (double)Temperature/340+36.53; //temperature formula
Gx = (double)GyroX/GyroScaleFactor;
Gy = (double)GyroY/GyroScaleFactor;
Gz = (double)GyroZ/GyroScaleFactor;
Serial.print("Ax: "); Serial.print(Ax);
Serial.print(" Ay: "); Serial.print(Ay);
Serial.print(" Az: "); Serial.print(Az);
Serial.print(" T: "); Serial.print(T);
Serial.print(" Gx: "); Serial.print(Gx);
Serial.print(" Gy: "); Serial.print(Gy);
Serial.print(" Gz: "); Serial.println(Gz);
delay(100);
}
void I2C_Write(uint8_t deviceAddress, uint8_t regAddress, uint8_t data){
Wire.beginTransmission(deviceAddress);
Wire.write(regAddress);
Wire.write(data);
Wire.endTransmission();
}
// read all 14 register
void Read_RawValue(uint8_t deviceAddress, uint8_t regAddress){
Wire.beginTransmission(deviceAddress);
Wire.write(regAddress);
Wire.endTransmission();
Wire.requestFrom(deviceAddress, (uint8_t)14);
AccelX = (((int16_t)Wire.read()<<8) | Wire.read());
AccelY = (((int16_t)Wire.read()<<8) | Wire.read());
AccelZ = (((int16_t)Wire.read()<<8) | Wire.read());
Temperature = (((int16_t)Wire.read()<<8) | Wire.read());
GyroX = (((int16_t)Wire.read()<<8) | Wire.read());
GyroY = (((int16_t)Wire.read()<<8) | Wire.read());
GyroZ = (((int16_t)Wire.read()<<8) | Wire.read());
}
//configure MPU6050
void MPU6050_Init(){
delay(150);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SMPLRT_DIV, 0x07);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_1, 0x01);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_2, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_CONFIG, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_GYRO_CONFIG, 0x00);//set +/-250 degree/second full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_CONFIG, 0x00);// set +/- 2g full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_FIFO_EN, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_INT_ENABLE, 0x01);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SIGNAL_PATH_RESET, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_USER_CTRL, 0x00);
}
Arduino Serial Output Window
Output window of Arduino IDE serial window for above Arduino sketch is shown below
Ax = Accelerometer x axis data in g unit
Ay = Accelerometer y axis data in g unit
Az = Accelerometer z axis data in g unit
T = temperature in degree/celcius
Gx = Gyro x axis data in degree/seconds unit
Gy = Gyro y axis data in degree/seconds unit
Gz = Gyro z axis data in degree/seconds unit
Supporting Files
Source Code
- NodeMCU MPU6050 Source files Download 849
Attached File
- MPU6050 Datasheet Download 624
- MPU6050 Register manual Download 535
No comments:
Post a Comment