I have the following very basic program that reads MPU6050(accelerometer and gyroscope) sensor using the I2C library, and prints the sensor information. This program works as expected.
#include <Arduino.h>
#include <MPU6050_6Axis_MotionApps20.h>
inline void printToSerial(bool, bool) __attribute__((always_inline));
MPU6050 imu;
int16_t ax, ay, az, gx, gy, gz;
void setup() {
imu.initialize();
imu.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
imu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
imu.setXAccelOffset(-1451);
imu.setYAccelOffset(-682);
imu.setZAccelOffset(1448);
imu.setXGyroOffset(69);
imu.setYGyroOffset(-16);
imu.setZGyroOffset(29);
Serial.begin(9600);
}
void loop() {
imu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
printToSerial(false, true);
delay(50);
}
void printToSerial(bool a, bool g){
if(a){
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.println(az);
}
if(g){
Serial.print(gx); Serial.print("\t");
Serial.print(gy); Serial.print("\t");
Serial.println(gz);
}
}
But as I want to add more functionality to the main program - I want to move MPU6050 specific code to separate file.
So, I created Sensor.h
with the following content,
#ifndef SENSOR_H
#define SENSOR_H
#include <MPU6050_6Axis_MotionApps20.h>
extern MPU6050 imu;
extern int16_t ax, ay, az, gx, gy, gz;
void sensorInit();
void sensorUpdate();
#endif
And placed the implementation in the Sensor.cpp
file.
# include "Sensor.h"
void sensorInit(){
imu.initialize();
imu.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
imu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
imu.setXAccelOffset(-1451);
imu.setYAccelOffset(-682);
imu.setZAccelOffset(1448);
imu.setXGyroOffset(69);
imu.setYGyroOffset(-16);
imu.setZGyroOffset(29);
}
void sensorUpdate(){
imu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
}
And finally, modified the main.cpp
file in the following way,
#include "Sensor.h"
#include <Arduino.h>
inline void printToSerial(bool, bool) __attribute__((always_inline));
void setup() {
sensorInit(); // replaced few lines of codes
Serial.begin(9600);
}
void loop() {
sensorUpdate(); // replaced few lines of codes
printToSerial(false, true);
delay(50);
}
void printToSerial(bool a, bool g){
if(a){
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.println(az);
}
if(g){
Serial.print(gx); Serial.print("\t");
Serial.print(gy); Serial.print("\t");
Serial.println(gz);
}
}
But when I try to build the code, I get the following error in the linking step,
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpInitialize()'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpPacketAvailable()'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetAccel(long*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetAccel(int*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetAccel(VectorInt16*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetQuaternion(long*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetQuaternion(int*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetQuaternion(Quaternion*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetGyro(long*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetGyro(int*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetGyro(VectorInt16*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetLinearAccel(VectorInt16*, VectorInt16*, VectorFloat*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetLinearAccelInWorld(VectorInt16*, VectorInt16*, Quaternion*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetGravity(int*, unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetGravity(VectorFloat*, Quaternion*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetEuler(float*, Quaternion*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetYawPitchRoll(float*, Quaternion*, VectorFloat*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpProcessFIFOPacket(unsigned char const*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpReadAndProcessFIFOPacket(unsigned char, unsigned char*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetFIFOPacketSize()'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `MPU6050::dmpInitialize()':
(.text+0x0): multiple definition of `MPU6050::dmpGetCurrentFIFOPacket(unsigned char*)'
.pio\build\uno\src\Sensor.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\libdeps\uno\I2Cdevlib-MPU6050/MPU6050.h:436:7: warning: type 'struct MPU6050' violates one definition rule [-Wodr]
class MPU6050 {
^
.pio\libdeps\uno\I2Cdevlib-MPU6050\MPU6050.h:436:7: note: a different type is defined in another translation unit
class MPU6050 {
^
.pio\libdeps\uno\I2Cdevlib-MPU6050/MPU6050.h:1036:18: note: the first difference of corresponding definitions is field 'dmpPacketBuffer'
uint8_t *dmpPacketBuffer;
^
.pio\libdeps\uno\I2Cdevlib-MPU6050\MPU6050.h:436:7: note: a type with different number of fields is defined in another translation unit
class MPU6050 {
^
C:\Users\iamcr\AppData\Local\Temp\cc1jV0kL.ltrans0.ltrans.o: In function `MPU6050::getDeviceID() [clone .constprop.29]':
<artificial>:(.text+0xbba): undefined reference to `imu'
<artificial>:(.text+0xbd0): undefined reference to `imu'
<artificial>:(.text+0xbd4): undefined reference to `imu'
C:\Users\iamcr\AppData\Local\Temp\cc1jV0kL.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x10c): undefined reference to `imu'
<artificial>:(.text.startup+0x11c): undefined reference to `imu'
C:\Users\iamcr\AppData\Local\Temp\cc1jV0kL.ltrans0.ltrans.o:<artificial>:(.text.startup+0x12a): more undefined references to `imu' follow
C:\Users\iamcr\AppData\Local\Temp\cc1jV0kL.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x282): undefined reference to `ax'
<artificial>:(.text.startup+0x286): undefined reference to `ax'
<artificial>:(.text.startup+0x28a): undefined reference to `imu'
<artificial>:(.text.startup+0x28e): undefined reference to `imu'
<artificial>:(.text.startup+0x298): undefined reference to `ay'
<artificial>:(.text.startup+0x29c): undefined reference to `ay'
<artificial>:(.text.startup+0x2a0): undefined reference to `imu'
<artificial>:(.text.startup+0x2a4): undefined reference to `imu'
<artificial>:(.text.startup+0x2ae): undefined reference to `az'
<artificial>:(.text.startup+0x2b2): undefined reference to `az'
<artificial>:(.text.startup+0x2b6): undefined reference to `imu'
<artificial>:(.text.startup+0x2ba): undefined reference to `imu'
<artificial>:(.text.startup+0x2c4): undefined reference to `gx'
<artificial>:(.text.startup+0x2c8): undefined reference to `gx'
<artificial>:(.text.startup+0x2cc): undefined reference to `imu'
<artificial>:(.text.startup+0x2d0): undefined reference to `imu'
<artificial>:(.text.startup+0x2da): undefined reference to `gy'
<artificial>:(.text.startup+0x2de): undefined reference to `gy'
<artificial>:(.text.startup+0x2e2): undefined reference to `imu'
<artificial>:(.text.startup+0x2e6): undefined reference to `imu'
<artificial>:(.text.startup+0x2f0): undefined reference to `gz'
<artificial>:(.text.startup+0x2f4): undefined reference to `gz'
<artificial>:(.text.startup+0x30c): undefined reference to `gy'
<artificial>:(.text.startup+0x310): undefined reference to `gy'
<artificial>:(.text.startup+0x328): undefined reference to `gz'
<artificial>:(.text.startup+0x32c): undefined reference to `gz'
Main.cpp, Sensor.cpp and Sensor.h files are in the same directory. I am using PlatformIO to build and deploy the code on an Arduino Uno and the platformio.ini file content is the following,
[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps = jrowberg/[email protected]+sha.fbde122cc5
I am wondering what is causing the linking errors.