在为我的IMU代码创建一个更大的库之前,我一直在做一个库作为测试。当包含库时,我得到以下错误。
> \\uoa.auckland.ac.nz\engdfs\Home\cjay511\Documents\Arduino\sketch_may19a/sketch_may19a.ino:303:
> undefined reference to `I2CRW::writeByte(unsigned char, unsigned char,
> unsigned char)'
每当我从自定义头文件中调用函数时,它就会出现。我看过stackoverflow上的解决方案,比如删除build文件夹和重建没有帮助。
代码(取出#define for the register coz theres heaps)
#include <Wire.h>
#include <i2crw.h>
// Specify sensor full scale
int Gscale = 0;
int Ascale = 0;
float AccelRes, GyroRes; // scale resolutions per LSB for the sensors
int16_t accelCount[3]; // Stores the 16-bit signed accelerometer sensor output
float ax, ay, az; // Stores the real accel value in g's
int16_t gyroCount[3]; // Stores the 16-bit signed gyro sensor output
float gx, gy, gz; // Stores the real gyro value in degrees per seconds
float gyroBias[3] = {0, 0, 0}, accelBias[3] = {0, 0, 0}; // Bias corrections for gyro and accelerometer
float SelfTest[6];
// parameters for 6 DoF sensor fusion calculations
float GyroMeasError = PI * (40.0f / 180.0f); // gyroscope measurement error in rads/s (start at 60 deg/s), then reduce after ~10 s to 3
float beta = sqrt(3.0f / 4.0f) * GyroMeasError; // compute beta
float GyroMeasDrift = PI * (2.0f / 180.0f); // gyroscope measurement drift in rad/s/s (start at 0.0 deg/s/s)
float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift; // compute zeta, the other free parameter in the Madgwick scheme usually set to a small or zero value
float deltat = 0.0f; // integration interval for both filter schemes
uint32_t lastUpdate = 0, firstUpdate = 0; // used to calculate integration interval
uint32_t Now = 0; // used to calculate integration interval
float angle;
uint32_t delt_t = 0; // used to control display output rate
uint32_t count = 0; // used to control display output rate
I2CRW i2crw;
void setup() {
// put your setup code here, to run once:
//Wire.begin();
Serial.begin(38400);
uint8_t c = i2crw.readByte(MPU9150_ADDRESS, WHO_AM_I);
// Get magnetometer calibration from AK8975A ROM
if (c == 0x68) // WHO_AM_I should always be 0x68
{
Serial.println("MPU9150 is online...");
MPU9150SelfTest(SelfTest);
Serial.println("Senpai, My acceleration trim values");
Serial.print("x-axis self test: acceleration trim within : ");
Serial.print(SelfTest[0],1);
Serial.println("% of factory value");
Serial.print("y-axis self test: acceleration trim within : ");
Serial.print(SelfTest[1],1);
Serial.println("% of factory value");
Serial.print("z-axis self test: acceleration trim within : ");
Serial.print(SelfTest[2],1);
Serial.println("% of factory value");
Serial.println("Senpai, My gyration trim values");
Serial.print("x-axis self test: gyration trim within : ");
Serial.print(SelfTest[3],1);
Serial.println("% of factory value");
Serial.print("y-axis self test: gyration trim within : ");
Serial.print(SelfTest[4],1);
Serial.println("% of factory value");
Serial.print("z-axis self test: gyration trim within : ");
Serial.print(SelfTest[5],1);
Serial.println("% of factory value");
if(SelfTest[0] < 1.0f && SelfTest[1] < 1.0f && SelfTest[2] < 1.0f && SelfTest[3] < 1.0f && SelfTest[4] < 1.0f && SelfTest[5] < 1.0f)
{
Serial.println("Senpai I have Passed my Selftest!!");
delay(3000);
calibrateMPU9150(gyroBias, accelBias); // Calibrate gyro and accelerometers, load biases in bias registers
Serial.println("My biases, senpai");
Serial.print("Acceleration bias X: ");
Serial.println((int)(1000*accelBias[0]));
Serial.print("Acceleration bias Y: ");
Serial.println((int)(1000*accelBias[1]));
Serial.print("Acceleration bias Z: ");
Serial.println((int)(1000*accelBias[2]));
Serial.print("Gyration bias X: ");
Serial.println(gyroBias[0],1);
Serial.print("Gyration bias Y: ");
Serial.println(gyroBias[1],1);
Serial.print("Gyration bias Z: ");
Serial.println(gyroBias[2],1);
delay(3000);
initMPU9150();
Serial.println("Awaiting command from Senpai");
}
else
{
Serial.println("Senpai, You are wrong");
}
}
}
void loop()
{
if(i2crw.readByte(MPU9150_ADDRESS, INT_STATUS) & 0x01)
{
Serial.println("Data read byte set");
}
else
{
Serial.println("Data read byte NOT SET");
}
readAccelData(accelCount);
//getAccelRes();
AccelRes = 2.0/32768.0;
readGyroData(gyroCount);
//getGyroRes();
GyroRes = 250.0/32768.0;
ax = (float)accelCount[0]*AccelRes;
ay = (float)accelCount[1]*AccelRes;
az = (float)accelCount[2]*AccelRes;
gx = (float)gyroCount[0]*GyroRes;
gy = (float)gyroCount[1]*GyroRes;
gz = (float)gyroCount[2]*GyroRes;
Now = micros();
deltat = ((Now-lastUpdate)/1000000.0f);
lastUpdate = Now;
angle = gz*deltat;
Serial.print("average rate = "); Serial.print(1.0f/deltat, 2); Serial.println(" Hz");
Serial.println("I bought Senpai the Acceleration and Gyration Values");
Serial.println("");
Serial.print("ax = "); Serial.print((int)1000*ax);
Serial.print(" ay = "); Serial.print((int)1000*ay);
Serial.print(" az = "); Serial.print((int)1000*az); Serial.println(" mg");
Serial.print("gx = "); Serial.print( gx, 1);
Serial.print(" gy = "); Serial.print( gy, 1);
Serial.print(" gz = "); Serial.print( gz, 1); Serial.println(" deg/s");
Serial.println("");
Serial.print("angle = "); Serial.println(angle,1);
delay(1000);
}
void readAccelData(int16_t *acceldata)
{
uint8_t rawdata[6];
i2crw.readBytes(MPU9150_ADDRESS, ACCEL_XOUT_H, 6, &rawdata[0]);
acceldata[0] = (int16_t)((rawdata[0]<<8)|(rawdata[1]));
acceldata[1] = (int16_t)((rawdata[2]<<8)|(rawdata[3]));
acceldata[2] = (int16_t)((rawdata[4]<<8)|(rawdata[5]));
}
void readGyroData(int16_t *gyrodata)
{
uint8_t rawdata[6];
i2crw.readBytes(MPU9150_ADDRESS, GYRO_XOUT_H, 6, &rawdata[0]);
gyrodata[0] = (int16_t)((rawdata[0]<<8)|(rawdata[1]));
gyrodata[1] = (int16_t)((rawdata[2]<<8)|(rawdata[3]));
gyrodata[2] = (int16_t)((rawdata[4]<<8)|(rawdata[5]));
}
void initMPU9150()
{
i2crw.writeByte(MPU9150_ADDRESS, PWR_MGMT_1, 0x01);
i2crw.writeByte(MPU9150_ADDRESS, CONFIG, 0x03);
i2crw.writeByte(MPU9150_ADDRESS, SMPLRT_DIV, 0x04);
uint8_t c = i2crw.readByte(MPU9150_ADDRESS, GYRO_CONFIG);
i2crw.writeByte(MPU9150_ADDRESS, GYRO_CONFIG, c & ~0xE0);
i2crw.writeByte(MPU9150_ADDRESS, GYRO_CONFIG, c & ~0x18);
i2crw.writeByte(MPU9150_ADDRESS, GYRO_CONFIG, c | Gscale << 3);
c = i2crw.readByte(MPU9150_ADDRESS, ACCEL_CONFIG);
i2crw.writeByte(MPU9150_ADDRESS, ACCEL_CONFIG, c & ~0xE0); // Clear self-test bits [7:5]
i2crw.writeByte(MPU9150_ADDRESS, ACCEL_CONFIG, c & ~0x18); // Clear AFS bits [4:3]
i2crw.writeByte(MPU9150_ADDRESS, ACCEL_CONFIG, c | Ascale << 3);
i2crw.writeByte(MPU9150_ADDRESS, INT_PIN_CFG, 0x22);
i2crw.writeByte(MPU9150_ADDRESS, INT_ENABLE, 0x01);
}
void calibrateMPU9150(float * dest1, float * dest2)
{
uint8_t data[12];
uint16_t ii, packet_count, fifo_count;
int32_t gyro_bias[3] = {0,0,0}, accel_bias[3] = {0,0,0};
i2crw.writeByte(MPU9150_ADDRESS, PWR_MGMT_1, 0x80);
delay(100);
i2crw.writeByte(MPU9150_ADDRESS, PWR_MGMT_1, 0x01);
i2crw.writeByte(MPU9150_ADDRESS, PWR_MGMT_2, 0x00);
delay(200);
// Configure device for bias calculation
i2crw.writeByte(MPU9150_ADDRESS, INT_ENABLE, 0x00); // Disable all interrupts
i2crw.writeByte(MPU9150_ADDRESS, FIFO_EN, 0x00); // Disable FIFO
i2crw.writeByte(MPU9150_ADDRESS, PWR_MGMT_1, 0x00); // Turn on internal clock source
i2crw.writeByte(MPU9150_ADDRESS, I2C_MST_CTRL, 0x00); // Disable I2C master
i2crw.writeByte(MPU9150_ADDRESS, USER_CTRL, 0x00); // Disable FIFO and I2C master modes
i2crw.writeByte(MPU9150_ADDRESS, USER_CTRL, 0x0C); // Reset FIFO and DMP
delay(15);
// Configure MPU9150 gyro and accelerometer for bias calculation
i2crw.writeByte(MPU9150_ADDRESS, CONFIG, 0x01); // Set low-pass filter to 188 Hz
i2crw.writeByte(MPU9150_ADDRESS, SMPLRT_DIV, 0x00); // Set sample rate to 1 kHz
i2crw.writeByte(MPU9150_ADDRESS, GYRO_CONFIG, 0x00); // Set gyro full-scale to 250 degrees per second, maximum sensitivity
i2crw.writeByte(MPU9150_ADDRESS, ACCEL_CONFIG, 0x00); // Set accelerometer full-scale to 2 g, maximum sensitivity
uint16_t gyrosensitivity = 131; // = 131 LSB/degrees/sec
uint16_t accelsensitivity = 16384; // = 16384 LSB/g
// Configure FIFO to capture accelerometer and gyro data for bias calculation
i2crw.writeByte(MPU9150_ADDRESS, USER_CTRL, 0x40); // Enable FIFO
i2crw.writeByte(MPU9150_ADDRESS, FIFO_EN, 0x78); // Enable gyro and accelerometer sensors for FIFO (max size 1024 bytes in MPU-9150)
delay(80); // accumulate 80 samples in 80 milliseconds = 960 bytes
// At end of sample accumulation, turn off FIFO sensor read
i2crw.writeByte(MPU9150_ADDRESS, FIFO_EN, 0x00); // Disable gyro and accelerometer sensors for FIFO
i2crw.readBytes(MPU9150_ADDRESS, FIFO_COUNTH, 2, &data[0]); // read FIFO sample count
fifo_count = ((uint16_t)data[0] << 8) | data[1];
packet_count = fifo_count/12;// How many sets of full gyro and accelerometer data for averaging
for (ii = 0; ii < packet_count; ii++) {
int16_t accel_temp[3] = {0, 0, 0}, gyro_temp[3] = {0, 0, 0};
i2crw.readBytes(MPU9150_ADDRESS, FIFO_R_W, 12, &data[0]); // read data for averaging
accel_temp[0] = (int16_t) (((int16_t)data[0] << 8) | data[1] ) ; // Form signed 16-bit integer for each sample in FIFO
accel_temp[1] = (int16_t) (((int16_t)data[2] << 8) | data[3] ) ;
accel_temp[2] = (int16_t) (((int16_t)data[4] << 8) | data[5] ) ;
gyro_temp[0] = (int16_t) (((int16_t)data[6] << 8) | data[7] ) ;
gyro_temp[1] = (int16_t) (((int16_t)data[8] << 8) | data[9] ) ;
gyro_temp[2] = (int16_t) (((int16_t)data[10] << 8) | data[11]) ;
accel_bias[0] += (int32_t) accel_temp[0]; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases
accel_bias[1] += (int32_t) accel_temp[1];
accel_bias[2] += (int32_t) accel_temp[2];
gyro_bias[0] += (int32_t) gyro_temp[0];
gyro_bias[1] += (int32_t) gyro_temp[1];
gyro_bias[2] += (int32_t) gyro_temp[2];
}
accel_bias[0] /= (int32_t) packet_count; // Normalize sums to get average count biases
accel_bias[1] /= (int32_t) packet_count;
accel_bias[2] /= (int32_t) packet_count;
gyro_bias[0] /= (int32_t) packet_count;
gyro_bias[1] /= (int32_t) packet_count;
gyro_bias[2] /= (int32_t) packet_count;
if(accel_bias[2] > 0L) {accel_bias[2] -= (int32_t) accelsensitivity;} // Remove gravity from the z-axis accelerometer bias calculation
else {accel_bias[2] += (int32_t) accelsensitivity;}
// Construct the gyro biases for push to the hardware gyro bias registers, which are reset to zero upon device startup
data[0] = (-gyro_bias[0]/4 >> 8) & 0xFF; // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format
data[1] = (-gyro_bias[0]/4) & 0xFF; // Biases are additive, so change sign on calculated average gyro biases
data[2] = (-gyro_bias[1]/4 >> 8) & 0xFF;
data[3] = (-gyro_bias[1]/4) & 0xFF;
data[4] = (-gyro_bias[2]/4 >> 8) & 0xFF;
data[5] = (-gyro_bias[2]/4) & 0xFF;
// Push gyro biases to hardware registers
i2crw.writeByte(MPU9150_ADDRESS, XG_OFFS_USRH, data[0]);// might not be supported in MPU9150
i2crw.writeByte(MPU9150_ADDRESS, XG_OFFS_USRL, data[1]);
i2crw.writeByte(MPU9150_ADDRESS, YG_OFFS_USRH, data[2]);
i2crw.writeByte(MPU9150_ADDRESS, YG_OFFS_USRL, data[3]);
i2crw.writeByte(MPU9150_ADDRESS, ZG_OFFS_USRH, data[4]);
i2crw.writeByte(MPU9150_ADDRESS, ZG_OFFS_USRL, data[5]);
dest1[0] = (float) gyro_bias[0]/(float) gyrosensitivity; // construct gyro bias in deg/s for later manual subtraction
dest1[1] = (float) gyro_bias[1]/(float) gyrosensitivity;
dest1[2] = (float) gyro_bias[2]/(float) gyrosensitivity;
// Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain
// factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold
// non-zero values. In addition, bit 0 of the lower byte must be preserved since it is used for temperature
// compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that
// the accelerometer biases calculated above must be divided by 8.
int32_t accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases
i2crw.readBytes(MPU9150_ADDRESS, XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values
accel_bias_reg[0] = (int16_t) ((int16_t)data[0] << 8) | data[1];
i2crw.readBytes(MPU9150_ADDRESS, YA_OFFSET_H, 2, &data[0]);
accel_bias_reg[1] = (int16_t) ((int16_t)data[0] << 8) | data[1];
i2crw.readBytes(MPU9150_ADDRESS, ZA_OFFSET_H, 2, &data[0]);
accel_bias_reg[2] = (int16_t) ((int16_t)data[0] << 8) | data[1];
uint32_t mask = 1uL; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers
uint8_t mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis
for(ii = 0; ii < 3; ii++) {
if(accel_bias_reg[ii] & mask) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit
}
// Construct total accelerometer bias, including calculated average accelerometer bias from above
accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale)
accel_bias_reg[1] -= (accel_bias[1]/8);
accel_bias_reg[2] -= (accel_bias[2]/8);
data[0] = (accel_bias_reg[0] >> 8) & 0xFF;
data[1] = (accel_bias_reg[0]) & 0xFF;
data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers
data[2] = (accel_bias_reg[1] >> 8) & 0xFF;
data[3] = (accel_bias_reg[1]) & 0xFF;
data[3] = data[3] | mask_bit[1]; // preserve temperature compensation bit when writing back to accelerometer bias registers
data[4] = (accel_bias_reg[2] >> 8) & 0xFF;
data[5] = (accel_bias_reg[2]) & 0xFF;
data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers
// Push accelerometer biases to hardware registers
i2crw.writeByte(MPU9150_ADDRESS, XA_OFFSET_H, data[0]); // might not be supported in MPU9150
i2crw.writeByte(MPU9150_ADDRESS, XA_OFFSET_L_TC, data[1]);
i2crw.writeByte(MPU9150_ADDRESS, YA_OFFSET_H, data[2]);
i2crw.writeByte(MPU9150_ADDRESS, YA_OFFSET_L_TC, data[3]);
i2crw.writeByte(MPU9150_ADDRESS, ZA_OFFSET_H, data[4]);
i2crw.writeByte(MPU9150_ADDRESS, ZA_OFFSET_L_TC, data[5]);
// Output scaled accelerometer biases for manual subtraction in the main program
dest2[0] = (float)accel_bias[0]/(float)accelsensitivity;
dest2[1] = (float)accel_bias[1]/(float)accelsensitivity;
dest2[2] = (float)accel_bias[2]/(float)accelsensitivity;
}
void MPU9150SelfTest(float * testdata)
{
uint8_t rawData[4];
uint8_t selfTest[6];
float factoryTrim[6];
i2crw.writeByte(MPU9150_ADDRESS, ACCEL_CONFIG, 0xF0);
i2crw.writeByte(MPU9150_ADDRESS, GYRO_CONFIG, 0xE0);
delay(250);
rawData[0] = i2crw.readByte(MPU9150_ADDRESS, SELF_TEST_X);
rawData[1] = i2crw.readByte(MPU9150_ADDRESS, SELF_TEST_Y);
rawData[2] = i2crw.readByte(MPU9150_ADDRESS, SELF_TEST_Z);
rawData[3] = i2crw.readByte(MPU9150_ADDRESS, SELF_TEST_A);
// Extract the acceleration test results first
selfTest[0] = (rawData[0] >> 3) | (rawData[3] & 0x30) >> 4 ; // XA_TEST result is a five-bit unsigned integer
selfTest[1] = (rawData[1] >> 3) | (rawData[3] & 0x0C) >> 2 ; // YA_TEST result is a five-bit unsigned integer
selfTest[2] = (rawData[2] >> 3) | (rawData[3] & 0x03) ; // ZA_TEST result is a five-bit unsigned integer
// Extract the gyration test results first
selfTest[3] = rawData[0] & 0x1F ; // XG_TEST result is a five-bit unsigned integer
selfTest[4] = rawData[1] & 0x1F ; // YG_TEST result is a five-bit unsigned integer
selfTest[5] = rawData[2] & 0x1F ; // ZG_TEST result is a five-bit unsigned integer
// Process results to allow final comparison with factory set values
factoryTrim[0] = (4096.0*0.34)*(pow( (0.92/0.34) , (((float)selfTest[0] - 1.0)/30.0))); // FT[Xa] factory trim calculation
factoryTrim[1] = (4096.0*0.34)*(pow( (0.92/0.34) , (((float)selfTest[1] - 1.0)/30.0))); // FT[Ya] factory trim calculation
factoryTrim[2] = (4096.0*0.34)*(pow( (0.92/0.34) , (((float)selfTest[2] - 1.0)/30.0))); // FT[Za] factory trim calculation
factoryTrim[3] = ( 25.0*131.0)*(pow( 1.046 , ((float)selfTest[3] - 1.0) )); // FT[Xg] factory trim calculation
factoryTrim[4] = (-25.0*131.0)*(pow( 1.046 , ((float)selfTest[4] - 1.0) )); // FT[Yg] factory trim calculation
factoryTrim[5] = ( 25.0*131.0)*(pow( 1.046 , ((float)selfTest[5] - 1.0) )); // FT[Zg] factory trim calculation
for (int i = 0; i < 6; i++) {
testdata[i] = 100.0 + 100.0*((float)selfTest[i] - factoryTrim[i])/factoryTrim[i]; // Report percent differences
}
}
标题(.h)
/* I2C library to read and Write Bytes from MPU 9150*/
#ifndef I2CRW_h
#define I2CRW_h
#include "Arduino.h"
#include <Wire.h>
class I2CRW
{
public:
I2CRW();
void writeByte(uint8_t address, uint8_t subAddress, uint8_t data);
uint8_t readByte(uint8_t address, uint8_t subAddress);
void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest);
private:
};
#endif
的.cpp
#include "Arduino.h"
#include "i2crw.h"
#include <Wire.h>
I2CRW::I2CRW(){
}
void writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
{
Wire.beginTransmission(address); // Initialize the Tx buffer
Wire.write(subAddress); // Put slave register address in Tx buffer
Wire.write(data); // Put data in Tx buffer
Wire.endTransmission(); // Send the Tx buffer
}
uint8_t readByte(uint8_t address, uint8_t subAddress)
{
uint8_t data; // `data` will store the register data
Wire.beginTransmission(address); // Initialize the Tx buffer
Wire.write(subAddress); // Put slave register address in Tx buffer
Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive
Wire.requestFrom(address, (uint8_t) 1); // Read one byte from slave register address
data = Wire.read(); // Fill Rx buffer with result
return data; // Return data read from slave register
}
void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
{
Wire.beginTransmission(address); // Initialize the Tx buffer
Wire.write(subAddress); // Put slave register address in Tx buffer
Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive
uint8_t i = 0;
Wire.requestFrom(address, count); // Read bytes from slave register address
while (Wire.available()) {
dest[i++] = Wire.read(); } // Put read results in the Rx buffer
}
任何帮助将不胜感激。不要以为你需要我的整个草图,但我把它放在以防万一。 谢谢 萨汉
答案 0 :(得分:0)
我想问题是你在“i2crw.h”中声明了一个类writeByte()
,有一些方法(readBytes()
和两个不同的I2CRW::I2CRW()
),但是你还没有他们已经实施了。
如果你看一下cpp文件(我猜想是“i2crw.cpp”),你已经实现了构造函数
I2CRW
和三个与void writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
uint8_t readByte(uint8_t address, uint8_t subAddress)
void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
类
IWCRW
我想您的意图是实现三个I2CRW::
方法,但是您忘记了函数名称前的void IWCRW::writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
uint8_t IWCRW::readByte(uint8_t address, uint8_t subAddress)
void IWCRW::readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
部分。
解决方案:在cpp类文件中更正方法实现中的函数实现
con
p.s:抱歉我的英语不好。