armray 发表于 2015-4-29 21:42:40

思考了一晚上不知道为什么,求助论坛大神,关于Arduino中的wire

首先我写了五个文件放在同一目录下:MPU6050.h 、MPU6050.CPP 、PASSOMETER.INO、DATABUFFER.H、DATABUFFER.H
功能实现放在passometer.ino里面,其他的 当类库使用,编译通过,可以运行。
在MPU6050.CPP中有这样两个函数:MPU6050_read和readFromsensor,前一个函数在第二中得到调用。
int MPU6050::MPU6050_read(int start, uint8_t *buffer, int size)
{
        int i, n;
        Wire.begin();
        Wire.beginTransmission(MPU6050_I2C_ADDRESS);
        n = Wire.write(start);
        if (n != 1)
                return (-10);
        n = Wire.endTransmission(false);
        if (n != 0)
                return (n);
        Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
        i = 0;
        while(Wire.available() && i<size)
        {
          buffer=Wire.read();
        }               
        if ( i != size)
                return (-11);
        return (0); // return : no error
}

void MPU6050::readFromSensor(DataBuffer * db) {
       
        int error;
      error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
   ........
}

然后loop中申明了一个mpu6050的对象,循环调用了readFromsensor,是这样调用的:
mpu6050.readFromSensor(&databuffer);
按照预期,,Wire.read应该返回动态的一组数据,,可实际上wire.read每次读取到的都是同样的。

为了找到错误,我做了这样的尝试:
1、以为是buffer中存储时出错,,所以有直接让wire.read的内容输出的串口,,发现结果仍然是每次返回同样的数据。
2、用while(wire.available())wire.read();
      来清空缓存,,结果失败。

新手遇到这样的问题好心塞,百度都百度不到,求好心人指点。

tsaiwn 发表于 2015-4-29 22:09:12


可能是你程序自己写错了
把以下这完整贴上来:
void MPU6050::readFromSensor(DataBuffer * db) {
      
      int error;
      error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
   ........
}

armray 发表于 2015-4-29 22:19:32

感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的一些处理。现在的问题是在MPU6050里读到的数据就是不对的。我又尝试了将MPU6050_read直接合并到readFromSensor里面,失败了。。等下只能试试将函数弄到loop里面去会不会成功了。因为我是初学者,整个代码我只是把一个单文件改成了多文件的形式,,原来能运行的文件应该是对的,,所以一步步减小多文件与单文件的差异希望能找到错误。

void MPU6050::readFromSensor(DataBuffer * db) {
       
        int error;
      error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
      if(error != 0) {
                Serial.print(F("Read accel, temp and gyro, error = "));
                Serial.println(error,DEC);
        }
        uint8_t swap;
        #define SWAP(x,y) swap = x; x = y; y = swap
        SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
        SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
        SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
        SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
        SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
        SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
        SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);

        Serial.print(F("accel x,y,z: "));
        Serial.print(accel_t_gyro.value.x_accel, DEC);
        Serial.print(F(", "));
        Serial.print(accel_t_gyro.value.y_accel, DEC);
        Serial.print(F(", "));
        Serial.print(accel_t_gyro.value.z_accel, DEC);
        Serial.print(F(", at "));
        Serial.print(db->Index);
        Serial.println(F(""));

    if((db->Index) < (db->BUFFER_SIZE) && (db->Index) > 1) {
                int tempX = accel_t_gyro.value.x_accel;
                int tempY = accel_t_gyro.value.y_accel;
                int tempZ = accel_t_gyro.value.z_accel;

                char temp = (char)(tempX >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer = temp;
                db->Index++;
                temp = (char)(tempX);
                if(temp == 0x00)
                        temp = 0x01;
                db->aAccelBuffer = temp;
                db->Index++;
   
                temp = (char)(tempY >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer = temp;
                db->Index++;
                temp = (char)(tempY);
                if(temp == 0x00)
                temp = 0x01;
                db->aAccelBuffer = temp;
                db->Index++;
   
                temp = (char)(tempZ >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer = temp;
                db->Index++;
                temp = (char)(tempZ);
                if(temp == 0x00)
                        temp = 0x01;
                db->aAccelBuffer = temp;
                db->Index++;
    }
}

tsaiwn 发表于 2015-4-29 22:53:54

armray 发表于 2015-4-29 22:19 static/image/common/back.gif
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的 ...

(1)你的以下这句写在何处 ?
   accel_t_gyro_union accel_t_gyro;

(2)你的这句写在何处?
   MPU6050mpu6050;

(3)麻烦把 MPU6050.h也贴上来

tsaiwn 发表于 2015-4-29 23:00:06

armray 发表于 2015-4-29 22:19 static/image/common/back.gif
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的 ...

还有还有

你说在 loop ( ) 内用:
   mpu6050.readFromSensor(&databuffer);
那请问这里的 databuffer 是写在何处, 以及如何写?

tsaiwn 发表于 2015-4-29 23:35:07

armray 发表于 2015-4-29 22:19 static/image/common/back.gif
感觉没有必要贴,,因为在readFromsensor一开始就调用了,MPU6050_read函数,,没有贴的部分都是读取后做的 ...

你的问题应该跟 Wire 没关系
应该是使用类库创建 "对象" 使用上的问题
例如 DataBuffer databuffer; 使用错误或写在错误的地方
还有
你说 "然后loop中申明了一个mpu6050的对象"
其实这也不应该,
如果你真的是 "在loop中申明一个mpu6050的对象"
则等于每次进入 loop 都重新创建新的 mpu6050的对象
因为, 每次离开 loop( ) { } 时在 loop( ) 中所有的变量与对象都会不见
意思是该些在 loop( ) 申明的变量与对象所占用内存都会被移除 !

armray 发表于 2015-4-30 10:35:34

tsaiwn 发表于 2015-4-29 23:35 static/image/common/back.gif
你的问题应该跟 Wire 没关系
应该是使用类库创建 "对象" 使用上的问题
例如 DataBuffer databuffer; 使 ...

哦哦,终于从wire的话题上打住了,看了下逻辑,也用你说的方法清理了缓存,应该不是wire的问题。问题应该还是在单文件到多文件的转换,就是引用对象时产生了差异,,整体的代码也不长,300行吧,我整理一下贴出来吧。
昨晚回去就睡了,才看到,既然大神都已经入局了,就麻烦再多看一下,帮我解决了问题吧,小弟不胜感激:lol

armray 发表于 2015-4-30 10:54:21

//DataBuffer.h
#ifndef DataBuffer_H
#define DataBuffer_H

#if defined(ARDUINO) && ARDUINO >= 100
        #include "Arduino.h"
#else
        #include "WProgram.h"
#endif

class DataBuffer{
        public:
                int BUFFER_SIZE;//buffer大小
                int Index;//buffer已存数据位
                byte aAccelBuffer;//存储单元
                DataBuffer();//构造函数
                void InitBuffer();//清空buffer
};
#endif
//DataBuffer.cpp
#include"DataBuffer.h"
DataBuffer::DataBuffer(){
    BUFFER_SIZE=125;
    Index=2;       
}
void DataBuffer::InitBuffer(){
          Index = 2;
      for(int i=Index; i<BUFFER_SIZE; i++) {
                aAccelBuffer = 0x00;
      }
       aAccelBuffer = 0xfe;
       aAccelBuffer = 0xfd;
       aAccelBuffer = 0xfd;
       aAccelBuffer = 0xfe;
       aAccelBuffer = 0x00;
}
//MPU6050.h
#ifndef MPU6050_H
#define MPU6050_H

#if defined(ARDUINO) && ARDUINO >= 100
        #include "Arduino.h"
#else
        #include "WProgram.h"
#endif
#include"DataBuffer.h"

#define MPU6050_ACCEL_XOUT_H 0x3B
#define MPU6050_PWR_MGMT_1 0x6B
#define MPU6050_PWR_MGMT_2 0x6C
#define MPU6050_WHO_AM_I 0x75
#define MPU6050_I2C_ADDRESS 0x68

class MPU6050{
        public:
                MPU6050();
                void readFromSensor(DataBuffer * db);
                int MPU6050_read(int start, uint8_t *buffer, int size);
                int MPU6050_write_reg(int reg, uint8_t *data);
                typedef union accel_t_gyro_union {
                        struct {
                        uint8_t x_accel_h;
                        uint8_t x_accel_l;
                        uint8_t y_accel_h;
                        uint8_t y_accel_l;
                        uint8_t z_accel_h;
                        uint8_t z_accel_l;
                        uint8_t t_h;
                        uint8_t t_l;
                        uint8_t x_gyro_h;
                        uint8_t x_gyro_l;
                        uint8_t y_gyro_h;
                        uint8_t y_gyro_l;
                        uint8_t z_gyro_h;
                        uint8_t z_gyro_l;
                        } reg;

                        struct {
                        int x_accel;
                        int y_accel;
                        int z_accel;
                        int temperature;
                        int x_gyro;
                        int y_gyro;
                        int z_gyro;
                        } value;
                };
      accel_t_gyro_union accel_t_gyro;

};
#endif
//MPU6050.cpp
#include"MPU6050.h"
#include"DataBuffer.h"
#include <math.h>
#include <Wire.h>
#include <SoftwareSerial.h>
MPU6050::MPU6050(){
       
};
int MPU6050::MPU6050_read(int start, uint8_t *buffer, int size)
{
        int i, n;
        Wire.begin();
        Wire.beginTransmission(MPU6050_I2C_ADDRESS);

        n = Wire.write(start);
        if (n != 1)
                return (-10);
       
        n = Wire.endTransmission(false);
        if (n != 0)
                return (n);
       
        // Third parameter is true: relase I2C-bus after data is read.
        Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
        i = 0;
        while(Wire.available() && i<size)
        {
          buffer=Wire.read();
        }               
        if ( i != size)
                return (-11);
        return (0);
}
void MPU6050::readFromSensor(DataBuffer * db) {
       
        int error;
      error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
      if(error != 0) {
                Serial.print(F("Read accel, temp and gyro, error = "));
                Serial.println(error,DEC);
        }
        uint8_t swap;
        #define SWAP(x,y) swap = x; x = y; y = swap//这一大段其实并没有用到,,也没有传给蓝牙
        SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
        SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
        SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
        SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
        SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
        SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
        SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);

        Serial.print(F("accel x,y,z: "));
        Serial.print(accel_t_gyro.value.x_accel, DEC);
        Serial.print(F(", "));
        Serial.print(accel_t_gyro.value.y_accel, DEC);
        Serial.print(F(", "));
        Serial.print(accel_t_gyro.value.z_accel, DEC);
        Serial.print(F(", at "));
        Serial.print(db->Index);
        Serial.println(F(""));

    if((db->Index) < (db->BUFFER_SIZE) && (db->Index) > 1) {
                int tempX = accel_t_gyro.value.x_accel;
                int tempY = accel_t_gyro.value.y_accel;
                int tempZ = accel_t_gyro.value.z_accel;

                char temp = (char)(tempX >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer = temp;
                db->Index++;
                temp = (char)(tempX);
                if(temp == 0x00)
                        temp = 0x01;
                db->aAccelBuffer = temp;
                db->Index++;
   
                temp = (char)(tempY >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer = temp;
                db->Index++;
                temp = (char)(tempY);
                if(temp == 0x00)
                temp = 0x01;
                db->aAccelBuffer = temp;
                db->Index++;
   
                temp = (char)(tempZ >> 8);
                if(temp == 0x00)
                        temp = 0x7f;
                db->aAccelBuffer = temp;
                db->Index++;
                temp = (char)(tempZ);
                if(temp == 0x00)
                        temp = 0x01;
                db->aAccelBuffer = temp;
                db->Index++;
    }
}
int MPU6050::MPU6050_write_reg(int reg, uint8_t *data)
{
        int error,n;
        Wire.beginTransmission(MPU6050_I2C_ADDRESS);
       
        n = Wire.write(reg);
        if (n != 1)
                {error=-20;return (error);}
       
        n = Wire.write(data, 1);
        if (n != 1)
                {error=-21;return (error);}
       
        error = Wire.endTransmission(true);
        if (error != 0)
                return (error);
        return (error);
}

//main file
#include <math.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include"DataBuffer.h"
#include"MPU6050.h"

#define SENSOR_READ_INTERVAL 50 //��ȡMPU�ļ��ʱ��
unsigned long prevSensoredTime = 0;//�ϴζ�ȡʱ��
unsigned long curSensoredTime = 0;//��ǰʱ��

SoftwareSerial BTSerial(2, 3);
MPU6050mpu6050=MPU6050();
DataBuffer databuffer=DataBuffer();

void setup() {
        Serial.begin(9600);
        BTSerial.begin(9600);
        Wire.begin();
      int error;
        uint8_t c;
        error = mpu6050.MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
        Serial.print(F("WHO_AM_I : "));
        Serial.print(c,HEX);
        Serial.print(F(", error = "));
        Serial.println(error,DEC);

        error = mpu6050.MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
        Serial.print(F("PWR_MGMT_2 : "));
        Serial.print(c,HEX);
        Serial.print(F(", error = "));
        Serial.println(error,DEC);
        mpu6050.MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
        databuffer.InitBuffer();
}
void loop() {
curSensoredTime = millis();
while(Wire.available())
      {Wire.read( );}
if(curSensoredTime - prevSensoredTime > SENSOR_READ_INTERVAL) {
    mpu6050.readFromSensor(&databuffer);
    prevSensoredTime = curSensoredTime;

    if(databuffer.Index >= databuffer.BUFFER_SIZE - 3) {
      sendToRemote(&databuffer);
      databuffer.InitBuffer();
      Serial.println("------------- Send 20 accel data to remote");
    }
}
}
void sendToRemote(DataBuffer * db) {
BTSerial.write( "accel" );
BTSerial.write( (char*)(db->aAccelBuffer) );
}

armray 发表于 2015-4-30 10:57:06

tsaiwn 发表于 2015-4-29 22:53 static/image/common/back.gif
(1)你的以下这句写在何处 ?
   accel_t_gyro_union accel_t_gyro;



1、accel_t_gyro_union accel_t_gyro;写在头文件里面了
2、MPU6050 mpu6050写在主文件中,但不是loop和setup中

armray 发表于 2015-4-30 11:00:20

tsaiwn 发表于 2015-4-29 23:35 static/image/common/back.gif
你的问题应该跟 Wire 没关系
应该是使用类库创建 "对象" 使用上的问题
例如 DataBuffer databuffer; 使 ...

因为在loop中要用到,对象在setup中申明的话会报“未定义对象”的错误,所以我在函数外申明了

tsaiwn 发表于 2015-4-30 11:35:28

armray 发表于 2015-4-30 10:54 static/image/common/back.gif
//DataBuffer.h
#ifndef DataBuffer_H
#define DataBuffer_H



Line 224 那句不对
    MPU6050mpu6050=MPU6050();

请注意 C++ 不是 Java, 对于 class/Object 的概念与用法略有不同.
该句必须改为:
    MPU6050mpu6050;   // 如果是 Java 则必须写 MPU6050mpu6050 = new MPU6050( );
/// 在 C++, 这样 mpu6050 就是个可以用的 Object (对象) 了 !

另外, 以下Line 225 也不对

   DataBuffer databuffer=DataBuffer();

虽然编译会过, 但是意义不同 !
必须改为

   DataBuffer databuffer;

或这样也可以:

   DataBuffer databuffer( );

你先改这两个看看是否问题就解决了 !?

armray 发表于 2015-4-30 12:16:38

tsaiwn 发表于 2015-4-30 11:35 static/image/common/back.gif
Line 224 那句不对
    MPU6050mpu6050=MPU6050();



按照你刚才说的改了,可以运行,但输出还是一直是这样

armray 发表于 2015-4-30 12:29:56

tsaiwn 发表于 2015-4-30 11:35 static/image/common/back.gif
Line 224 那句不对
    MPU6050mpu6050=MPU6050();



还有DataBuffer databuffer();这样的表达编译时通不过的哈

passometer.ino: In function 'void setup()':
passometer.ino:34:13: error: request for member 'InitBuffer' in 'databuffer', which is of non-class type 'DataBuffer()'
passometer.ino: In function 'void loop()':
passometer.ino:42:39: error: no matching function for call to 'MPU6050::readFromSensor(DataBuffer (*)())'
passometer.ino:42:39: note: candidate is:
In file included from passometer.ino:6:0:
C:\Users\rayray\AppData\Local\Temp\build1820798255905393185.tmp\MPU6050.h:21:8: note: void MPU6050::readFromSensor(DataBuffer*)
   void readFromSensor(DataBuffer * db);
      ^
C:\Users\rayray\AppData\Local\Temp\build1820798255905393185.tmp\MPU6050.h:21:8: note:   no known conversion for argument 1 from 'DataBuffer (*)()' to 'DataBuffer*'
passometer.ino:45:19: error: request for member 'Index' in 'databuffer', which is of non-class type 'DataBuffer()'
passometer.ino:45:39: error: request for member 'BUFFER_SIZE' in 'databuffer', which is of non-class type 'DataBuffer()'
passometer.ino:46:31: error: cannot convert 'DataBuffer (*)()' to 'DataBuffer*' for argument '1' to 'void sendToRemote(DataBuffer*)'
passometer.ino:47:18: error: request for member 'InitBuffer' in 'databuffer', which is of non-class type 'DataBuffer()'
编译有误。

tsaiwn 发表于 2015-4-30 13:01:33

armray 发表于 2015-4-30 12:16 static/image/common/back.gif
按照你刚才说的改了,可以运行,但输出还是一直是这样

(1) Classname objname( );这样会有问题喔?
   奇怪, 难道 Arduino 的 C++ 解读 class / object 不同
(2)还是 0 ? 那我晚上再看看

armray 发表于 2015-4-30 13:02:55

tsaiwn 发表于 2015-4-30 11:35 static/image/common/back.gif
Line 224 那句不对
    MPU6050mpu6050=MPU6050();



从com口传回的结果来看,用MPU6050_read在setup中执行这样的操作是正确的:
error = mpu6050.MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
也就是说MPU605_read 函数本身是没有错误的;

但在readFromsensor中调用,在loop中执行就是错误的;为了消除差异,

我有试过将readFromsensor放到setup中执行,,失败;
试过将readFromsensor中的MPU6050read的调用注释掉,直接填入相关代码,,失败。

感觉最后问题的解决不是及其简单就是及其高深
页: [1] 2
查看完整版本: 思考了一晚上不知道为什么,求助论坛大神,关于Arduino中的wire