极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

12
返回列表 发新帖
楼主: armray

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

[复制链接]
 楼主| 发表于 2015-4-30 13:29:35 | 显示全部楼层
tsaiwn 发表于 2015-4-30 13:01
(1) Classname objname( );  这样会有问题喔  ?
   奇怪, 难道 Arduino 的 C++ 解读 class / object 不 ...

好吧,没有耽误你正事就好。编程菜鸟,没有区分过object和class,,几个语言都学混了,都不精。
回复 支持 反对

使用道具 举报

发表于 2015-5-1 00:13:15 | 显示全部楼层
armray 发表于 2015-4-30 13:29
好吧,没有耽误你正事就好。编程菜鸟,没有区分过object和class,,几个语言都学混了,都不精。

看起来应该是以下
  error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
没有取得正确的  address  of  accel_t_gyro, 就是 &accel_t_gyro 啦
但是
这样有点奇怪
怎会拿错呢?
回复 支持 反对

使用道具 举报

发表于 2015-5-1 00:33:04 | 显示全部楼层
armray 发表于 2015-4-30 13:29
好吧,没有耽误你正事就好。编程菜鸟,没有区分过object和class,,几个语言都学混了,都不精。

把 MPU6050.h 和 MPU6050.cpp 改为如下看看
  1. //MPU6050.h
  2. #ifndef MPU6050_H
  3. #define MPU6050_H

  4. #if defined(ARDUINO) && ARDUINO >= 100
  5.         #include "Arduino.h"
  6. #else
  7.         #include "WProgram.h"
  8. #endif
  9. #include"DataBuffer.h"

  10. #define MPU6050_ACCEL_XOUT_H 0x3B
  11. #define MPU6050_PWR_MGMT_1 0x6B
  12. #define MPU6050_PWR_MGMT_2 0x6C
  13. #define MPU6050_WHO_AM_I 0x75
  14. #define MPU6050_I2C_ADDRESS 0x68

  15. class MPU6050{
  16.         public:
  17.                 MPU6050();
  18.                 void readFromSensor(DataBuffer * db);
  19.                 int MPU6050_read(int start);
  20.                 int MPU6050_write_reg(int reg, uint8_t *data);
  21.                 typedef union accel_t_gyro_union {
  22.                         struct {
  23.                         uint8_t x_accel_h;
  24.                         uint8_t x_accel_l;
  25.                         uint8_t y_accel_h;
  26.                         uint8_t y_accel_l;
  27.                         uint8_t z_accel_h;
  28.                         uint8_t z_accel_l;
  29.                         uint8_t t_h;
  30.                         uint8_t t_l;
  31.                         uint8_t x_gyro_h;
  32.                         uint8_t x_gyro_l;
  33.                         uint8_t y_gyro_h;
  34.                         uint8_t y_gyro_l;
  35.                         uint8_t z_gyro_h;
  36.                         uint8_t z_gyro_l;
  37.                         } reg;
  38.                         uint8_t buffer[14];
  39.                         struct {
  40.                         int x_accel;
  41.                         int y_accel;
  42.                         int z_accel;
  43.                         int temperature;
  44.                         int x_gyro;
  45.                         int y_gyro;
  46.                         int z_gyro;
  47.                         } value;
  48.                 };
  49.         accel_t_gyro_union accel_t_gyro;

  50. };
  51. #endif
复制代码
  1. //MPU6050.cpp
  2. #include"MPU6050.h"
  3. #include"DataBuffer.h"
  4. #include <math.h>
  5. #include <Wire.h>
  6. #include <SoftwareSerial.h>
  7. MPU6050::MPU6050(){

  8. };
  9. int MPU6050::MPU6050_read(int start)
  10. {b
  11.         int i, n;
  12.         int size = sizeof(accel_t_gyro);
  13.         Wire.begin();
  14.         Wire.beginTransmission(MPU6050_I2C_ADDRESS);

  15.         n = Wire.write(start);
  16.         if (n != 1)
  17.                 return (-10);

  18.         n = Wire.endTransmission(false);
  19.         if (n != 0)
  20.                 return (n);

  21.         // Third parameter is true: relase I2C-bus after data is read.
  22.         Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  23.         i = 0;
  24.         while(Wire.available() && i<size)
  25.         {
  26.           accel_t_gyro.buffer[i++]=Wire.read();
  27.         }               
  28.         if ( i != size)
  29.                 return (-11);
  30.         return (0);
  31. }
  32. void MPU6050::readFromSensor(DataBuffer * db) {

  33.         int error;
  34.         error = MPU6050_read (MPU6050_ACCEL_XOUT_H);
  35.         if(error != 0) {
  36.                 Serial.print(F("Read accel, temp and gyro, error = "));
  37.                 Serial.println(error,DEC);
  38.         }
  39.         uint8_t swap;
  40.         #define SWAP(x,y) swap = x; x = y; y = swap//这一大段其实并没有用到,,也没有传给蓝牙
  41.         SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
  42.         SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
  43.         SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
  44.         SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
  45.         SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
  46.         SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
  47.         SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);

  48.         Serial.print(F("accel x,y,z: "));
  49.         Serial.print(accel_t_gyro.value.x_accel, DEC);
  50.         Serial.print(F(", "));
  51.         Serial.print(accel_t_gyro.value.y_accel, DEC);
  52.         Serial.print(F(", "));
  53.         Serial.print(accel_t_gyro.value.z_accel, DEC);
  54.         Serial.print(F(", at "));
  55.         Serial.print(db->Index);
  56.         Serial.println(F(""));

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

  61.                 char temp = (char)(tempX >> 8);
  62.                 if(temp == 0x00)
  63.                         temp = 0x7f;
  64.                 db->aAccelBuffer[db->Index] = temp;
  65.                 db->Index++;
  66.                 temp = (char)(tempX);
  67.                 if(temp == 0x00)
  68.                         temp = 0x01;
  69.                 db->aAccelBuffer[db->Index] = temp;
  70.                 db->Index++;

  71.                 temp = (char)(tempY >> 8);
  72.                 if(temp == 0x00)
  73.                         temp = 0x7f;
  74.                 db->aAccelBuffer[db->Index] = temp;
  75.                 db->Index++;
  76.                 temp = (char)(tempY);
  77.                 if(temp == 0x00)
  78.                 temp = 0x01;
  79.                 db->aAccelBuffer[db->Index] = temp;
  80.                 db->Index++;

  81.                 temp = (char)(tempZ >> 8);
  82.                 if(temp == 0x00)
  83.                         temp = 0x7f;
  84.                 db->aAccelBuffer[db->Index] = temp;
  85.                 db->Index++;
  86.                 temp = (char)(tempZ);
  87.                 if(temp == 0x00)
  88.                         temp = 0x01;
  89.                 db->aAccelBuffer[db->Index] = temp;
  90.                 db->Index++;
  91.     }
  92. }
  93. int MPU6050::MPU6050_write_reg(int reg, uint8_t *data)
  94. {
  95.         int error,n;
  96.         Wire.beginTransmission(MPU6050_I2C_ADDRESS);

  97.         n = Wire.write(reg);
  98.         if (n != 1)
  99.                 {error=-20;return (error);}

  100.         n = Wire.write(data, 1);
  101.         if (n != 1)
  102.                 {error=-21;return (error);}

  103.         error = Wire.endTransmission(true);
  104.         if (error != 0)
  105.                 return (error);
  106.         return (error);
  107. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-1 10:18:35 | 显示全部楼层
tsaiwn 发表于 2015-5-1 00:13
看起来应该是以下
  error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof( ...

先不说存储的问题,我用serial.println(wire.read());都是错的呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-1 10:47:44 | 显示全部楼层
tsaiwn 发表于 2015-5-1 00:33
把 MPU6050.h 和 MPU6050.cpp 改为如下看看

果然是不行的。先抛开存储不谈吧,因为我用Serial.print(Wire.read())发现Wire.read()读取的信息一直都是错的。
MPU6050_read()在setup中读取MPU6050_PWR_MGMT_1这些信息是对的,说明MPU6050_read()函数又没有错。
这说明是调用问题,而我将readFromsensor()放在setup中调用,只运行一次,这样读取的数据也是错的。
我将MPU6050_read()合并到readFromsensor中,还是不对。

由此,在setup中调用是对的,所以我消除了第二次调用和在setup中调用差异问题,仍然有错。就是两次几乎一样的操作,第二次调用就是错的。真是无计可施。
回复 支持 反对

使用道具 举报

发表于 2015-5-1 14:43:33 | 显示全部楼层
armray 发表于 2015-5-1 10:47
果然是不行的。先抛开存储不谈吧,因为我用Serial.print(Wire.read())发现Wire.read()读取的信息一直都 ...

那请你在 void loop( ) { 内的一开始加入这句看看:
void loop( ) {
   static MPU6050  mpu6050;
   //...

其他都不要改, 测试看看
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-1 14:55:57 | 显示全部楼层
tsaiwn 发表于 2015-5-1 00:33
把 MPU6050.h 和 MPU6050.cpp 改为如下看看

问题解决了,第一时间就赶来告诉你,是一个很白痴的问题,不是wire、对象调用这些问题。
单文件中申明这个函数唤醒传感器:int MPU6050_write_reg(int reg, uint8_t data)
                       调用它时是这样的:MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);

我的多文件中唤醒传感器也是这样的:int MPU6050::MPU6050_write_reg(int reg, uint8_t *data)
                      调用它时也是这样的:MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);

我把0值传给指针data,编译并没有出错,但却没有将0值写入寄存器,也就是传感器还在休眠状态,当然全是0值了。

传感器中的寄存器参数应该没有多少人记得住,都是用的时候才去查看产品手册的,你应该也忘了。
打扰你多次却得到一个不是问题的问题,不过从你改动的代码中也让我学到不少Arduino编程方法。

最后问一下,在MPU6050.h中申明的联合体中有两个结构体,其中两个结构体大小都是14字节,用sizeof(accel_t_gyro_union)得到的也是14(根据对齐原则,我知道14是正确的),这样我每次用wire.read读取14个值存入时怎么把这个联合体存得满呢(这个联合体要28个字节才能存满吧)?既然存不满,,最后读取value结构体中怎么会有值呢?
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;
                };
回复 支持 反对

使用道具 举报

发表于 2015-5-1 17:33:15 | 显示全部楼层
armray 发表于 2015-5-1 14:55
问题解决了,第一时间就赶来告诉你,是一个很白痴的问题,不是wire、对象调用这些问题。
单文件中申明这 ...

联合体(union)的真正位置是以其内各项目中最长的为准,
因为里面每个项目都是迭起来的,
并不是串接一起!
这是 union 与 struct 最大的差别!
就是说..
在 struct 内的各项是串接
但在 union 内的各项都是同样的起点 !
回复 支持 反对

使用道具 举报

发表于 2015-5-1 17:44:02 | 显示全部楼层
armray 发表于 2015-5-1 14:55
问题解决了,第一时间就赶来告诉你,是一个很白痴的问题,不是wire、对象调用这些问题。
单文件中申明这 ...

关于联合体, 补充说明..
例如:

               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;
                        int xxx;
                        byte x[20];
                        float ff;
                        int kk[8];
                       /////
                        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  ggyy;

则 sizeof(ggyy) 就是 20
因为里面最长的项目是 byte x[20];
然后 ggyy.xxx 其实就是 ggyy.x[1] 和 ggyy.x[0] 合起来,
  同时 ggyy.xxx 也就是完全与 ggyy.value.x_accel 是占用同样的位置(内存);
  同时 ggyy.xxx 与 ggyy.kk[0] 也用同样的位置 (2 bytes), 当然也与 ggyy.value.x_accel 同样位置
  还有, ggyy.x[0]  就是 ggyy.reg.x_accel_h;
        ggyy.x[1]  就是 ggyy.reg.x_accel_l;

  至于 ggyy.ff 用 4 bytes:  ggyy.x[0], ggyy.x[1], ggyy.x[2], ggyy.x[3]
  该四个 byte 同时也被 ggyy.kk[0] 和 ggyy.kk[1] 占用
     也是 ggyy.value.x_accel; 和 ggyy.value.y_accel;

其他以此类推
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-2 00:03:03 | 显示全部楼层
tsaiwn 发表于 2015-5-1 17:44
关于联合体, 补充说明..
例如:

也看了几个结构体中的对齐原则、最小公倍数原则,但都没你说得细致
,大概懂得了,就是占用空间统共是20,,但是同一个空间可以用不同的名字来访问,
,可以用不同的名字来更改同一个空间的存储值,,是吧。
感觉这样的话,我用ggyy.x对空间进行赋值后,是不是会影响ggyyx.ff中的值?
我回头我编程试试,晚安
回复 支持 反对

使用道具 举报

发表于 2015-5-2 00:39:42 | 显示全部楼层
armray 发表于 2015-5-2 00:03
也看了几个结构体中的对齐原则、最小公倍数原则,但都没你说得细致
,大概懂得了,就是占用空间统共是20 ...

完全正确
你原先使用的那个 accel_t_gyro_union
就是因为 MPU6050 会吐出 14 bytes
每 2 bytes 为 一个 int,
可是因为每个 int 的 2 个 byte 是左右颠倒的,
所以先把每两个 byte 左右对调 swap
然后再把全部看作七个 int 拿来用
回复 支持 反对

使用道具 举报

发表于 2015-5-2 00:48:41 | 显示全部楼层
armray 发表于 2015-5-2 00:03
也看了几个结构体中的对齐原则、最小公倍数原则,但都没你说得细致
,大概懂得了,就是占用空间统共是20 ...

补充一下
为何 MPU 的每个 int 会左右对调呢?
其实这与 CPU 有关,
全世界的 CPU/MCU 分为两派:
   BigEndian vs. LittleEndian
(1)Little Endian:
   High byte at high address
(2)Big Endian
   High byte at Low address
假设有个 2 byte 的 int 占用 2 个 address:
  address    内含
    100      0x23
    101      0x58
这样, 请问在 address 100 的这个 int 是 0x2358 还是 0x5823 ?
请注意, 虽然这 int 占用 2 bytes,
我们只会说在 address 100 的那个 int,
不会说在 address 100 以及address 101 的那个 int !!!
Intel CPU 用 Little Endian, 所以会说该 int 是 0x5823
但 IBM, 以前 HP, 以前 SUN, 和几乎全部大计算机的 CPU,
以及摩托罗拉 等等厂商的 CPU 都是用 Big Endian, 所以会说该int是 0x2358
详细请自己百度一下 "BigEndian vs. LittleEndian"
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-17 09:46 , Processed in 0.041964 second(s), 16 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表