比派科技banana pi专区
直播中

ALSET

3年用户 269经验值
擅长:可编程逻辑,电源/新能源,嵌入式技术,处理器/DSP
私信 关注
[经验]

【Banana PI Leaf S3开发板试用体验】Banana PI Leaf S3 驱动MPU6050六轴陀螺仪的开发

BananaPI Leaf S3 - 驱动MPU6050六轴陀螺仪的开发
大信(QQ:8125036)
        上次的实验已经初步的掌握了Banana PI的开发环境和掌握简便的开发方法。
这次再尝试使用BananaPI连接其它硬件来做一些功能测试。这次首先使用一个设备MPU6050传感器,它是一款六轴陀螺仪,使用i2c的方式与主机进行通讯。
       9.jpg
     MPU6050是一款6轴运动处理传感器。集成了三轴加速度,三轴角速度,以及一个可扩展的数字运动处理器DMP(Digital Motion Processor:数字运动处理器),能够通过I2C协议进行传输数据,本次目标就是将MPU6050使用I2C协议与Banana PI Leaf S3进行通讯,获取角速度、加速度以及温度数据,使用串口显示在电脑上。
204.png
       关于MPU6050笔者在之前的一个实验中已经对它有详细的介绍,需要了解的可以点这个链接看一下。这里不再重复赘述了。
https://bbs.elecfans.com/jishu_2273503_1_1.html
一、连接MPU6050传感器
           首先连接Banana PI Leaf S3开发板与MPU6050传感器,这里使用开发板的硬i2c口,即PIN15,PIN16脚。具体连线如下图;
203.png
实物连线如下图:
212.jpg 210.jpg
       然后看MPU6050的驱动c/c++例程,主要看它的初始化,以及读取数据的,写入数据的控制命令,以及数据读取后的处理方法,其主要的参数定义如下,需要着重关注MPU的内部寄存器地址,以及其参数含义,这些寄存器的操作,需要在Banana PI LeafS3上完成
  1. #define     DEV_ADDR            0x68
  2. #define     SMPLRT_DIV          0x19   //陀螺仪采样率,典型值:0x07(125Hz)
  3. #define     CONFIG              0x1A   //低通滤波频率,典型值:0x06(5Hz)
  4. #define     GYRO_CONFIG         0x1B   //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  5. #define     ACCEL_CONFIG        0x1C   //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  6. #define     ACCEL_XOUT_H        0x3B
  7. #define     ACCEL_XOUT_L        0x3C
  8. #define     ACCEL_YOUT_H        0x3D
  9. #define     ACCEL_YOUT_L        0x3E
  10. #define     ACCEL_ZOUT_H        0x3F
  11. #define     ACCEL_ZOUT_L        0x40
  12. #define     TEMP_OUT_H          0x41
  13. #define     TEMP_OUT_L           0x42
  14. #define     GYRO_XOUT_H          0x43
  15. #define     GYRO_XOUT_L          0x44
  16. #define     GYRO_YOUT_H          0x45
  17. #define     GYRO_YOUT_L          0x46
  18. #define     GYRO_ZOUT_H          0x47
  19. #define     GYRO_ZOUT_L          0x48
  20. #define     PWR_MGMT_1           0x6B  //电源管理,典型值:0x00(正常启用)
  21. #define     WHO_AM_I             0x75  //IIC地址寄存器(默认数值0x68,只读)
  22. #define     SlaveAddressW        0xD0  //IIC写入时的地址字节数据,+1为读取
  23. #define     SlaveAddressR        0xD1  //IIC写入时的地址字节数据,+1为读取

  24. bool check()
  25. {
  26.          char temp;
  27.    temp = MPU6050_ReadOneByte(WHO_AM_I);
  28.    if(temp==0x68)
  29.             return true;
  30.    else
  31.             return false;
  32. }

  33. Void mpu6050_Initation()
  34. {
  35.    MPU6050_WriteOneByte(PWR_MGMT_1, 0x00);   //解除休眠状态
  36.    time_delay(200);
  37.    //MPU6050_WriteOneByte(PWR_MGMT_1, 0x80);       //复位
  38.    MPU6050_WriteOneByte(SMPLRT_DIV, 0x07);
  39.    MPU6050_WriteOneByte(CONFIG, 0x06);
  40.          MPU6050_WriteOneByte(GYRO_CONFIG, 0x18);
  41.          MPU6050_WriteOneByte(ACCEL_CONFIG, 0x01);
  42. }


二、MucroPython下的I2C 使用方法
     查询MicroPython的文档,可以看到有关i2c的用法,该开发板的I2C有两种使用方式,分别是硬I2C , 和软I2C
硬I2C端口定义如下,
           
I2C(0)
     
      
scl
      
16
   
     
sda
      
15
   
硬I2C micropython操作代码如下:
from machine import Pin, I2C
i2c = I2C(1, scl=Pin(16), sda=Pin(15), freq=400000)
软I2C硬I2C操作代码如下:
在使用软I2C下,任何两个空余的GPIO 都可以用来作为I2C的接口,通过软件对端口电平的翻转来模拟出I2C的通讯时序。
from machine import Pin, SoftI2C i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)i2c.scan()              # scan for devicesi2c.readfrom(0x3a, 4)   # read 4 bytes from device with address 0x3ai2c.writeto(0x3a, '12') # write '12' to device with address 0x3abuf = bytearray(10)     # create a buffer with 10 bytesi2c.writeto(0x3a, buf)  # write the given buffer to the peripheral
有了操作代码后,就可以尝试使用micropython在命令行去读写mpu6050设备了。读写尝试如下;
  1. >>>
  2. >>> import machine #引入硬件库
  3. >>> import utime #引入时间函数库
  4. >>> from machine import Pin, I2C #引入I2C硬设备
  5. >>>
  6. >>> i2c = I2C(0, scl=Pin(16), sda=Pin(15)) #设定SCL,SDA 脚
  7. >>> i2c.scan() #扫描该脚下的所有I2C设备
  8. [104] #获得地址为 104, 即0x68的I2C设备
  9. >>>
     到此说明已经操作成功MPU6050设备了,下一步该开发读取数据了。
205.png
三、编写MicroPython代码获取MPU6050的传感器数据
下面就在上面建立连接的基础上,继续编写代码,完成设备的校验,以及传感器数据的读取。

  1. from machine import Pin, I2C
  2. import machine
  3. import utime

  4. DEV_ADDR=0x68

  5. PWR_MGMT_1=0x6B
  6. SMPLRT_DIV=0x19
  7. CONFIG=0x06
  8. GYRO_CONFIG=0x18
  9. ACCEL_CONFIG=0x01
  10. ACCEL_XOUT_H=0x3B

  11. i2c = I2C(0, scl=Pin(16),  sda=Pin(15),  freq=100000)
  12. i2c.scan()

  13. i2c.writeto_mem(DEV_ADDR, PWR_MGMT_1, bytearray([0]))
  14. i2c.writeto_mem(DEV_ADDR, SMPLRT_DIV, bytearray([0x07]));
  15. i2c.writeto_mem(DEV_ADDR, CONFIG, bytearray([0x06]));
  16. i2c.writeto_mem(DEV_ADDR, GYRO_CONFIG, bytearray([0x18]));
  17. i2c.writeto_mem(DEV_ADDR, ACCEL_CONFIG, bytearray([0x01]));

  18. i2c.readfrom_mem(DEV_ADDR, ACCEL_XOUT_H, 14)
执行结果如下图:
206.png
四、优化脚本代码模块
虽然上面完成了整个I2C的连接,到设备验证,数据读取,但作为软件开发,需要将开发好的模块提供给业务应用人员进一步开发应用,因此不能只使用交互命令行的方式来交付代码成果。
需要把验证通过的交互式代码进行适当的分装,成为函数或者类,形成自定义的末块,让调用者不必关心外设的读写实现细节等,直接调用完成应用的业务逻辑。
代码优化后如下:
mpu6050操作库代码
  1. import machine

  2. class accel():
  3.     def __init__(self, i2c, addr=0x68):
  4.         self.iic = i2c
  5.         self.addr = addr
  6.         self.iic.start()
  7.         self.iic.writeto(self.addr, bytearray([107, 0]))
  8.         self.iic.stop()

  9.     def get_raw_values(self):
  10.         self.iic.start()
  11.         a = self.iic.readfrom_mem(self.addr, 0x3B, 14)
  12.         self.iic.stop()
  13.         return a

  14.     def get_ints(self):
  15.         b = self.get_raw_values()
  16.         c = []
  17.         for i in b:
  18.             c.append(i)
  19.         return c

  20.     def bytes_toint(self, firstbyte, secondbyte):
  21.         if not firstbyte & 0x80:
  22.             return firstbyte << 8 | secondbyte
  23.         return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

  24.     def get_values(self):
  25.         raw_ints = self.get_raw_values()
  26.         vals = {}
  27.         vals["AcX"] = self.bytes_toint(raw_ints[0], raw_ints[1])
  28.         vals["AcY"] = self.bytes_toint(raw_ints[2], raw_ints[3])
  29.         vals["AcZ"] = self.bytes_toint(raw_ints[4], raw_ints[5])
  30.         vals["Tmp"] = self.bytes_toint(raw_ints[6], raw_ints[7]) / 340.00 + 36.53
  31.         vals["GyX"] = self.bytes_toint(raw_ints[8], raw_ints[9])
  32.         vals["GyY"] = self.bytes_toint(raw_ints[10], raw_ints[11])
  33.         vals["GyZ"] = self.bytes_toint(raw_ints[12], raw_ints[13])
  34.         return vals  # returned in range of Int16
  35.         # -32768 to 32767

  36.     def val_test(self):  
  37.         from time import sleep
  38.         while 1:
  39.             print(self.get_values())
  40.             sleep(0.05)

调用代码:
  1. import mpu6050
  2. from machine import SoftI2C,Pin
  3. import utime

  4. i2c = SoftI2C(scl=Pin(21), sda=Pin(22))
  5. accel = mpu6050.accel(i2c)
  6. while True:
  7.     accel_dict = accel.get_values()
  8.     print(accel_dict)
  9.     utime.sleep(3)         


五、开发试用总结
         通过很短的时间的使用,完成Banana PI Leaf S3开发板连接上了MPU6050六轴传感器,有了micropython的支持,连接I2C设备和使用I2C变的非常简单容易,只要写几行代码就完成I2C总线的控制,简单的读写函数就可以完成对外设寄存器的读写,顺利的读取到数据。完全抛弃了示波器,逻辑分析仪等大凶器来调试硬件通讯了,大大简化了硬件开发难度,降低了硬件开发门槛,使得开发者只要了解外设的寄存定义和数据结构的定义就能很快的开发出相应的应用出来。
        可以看到有了micropython使得I2C这样的硬件开发变得非常简单容易,而且也不容易出错,


更多回帖

发帖
×
20
完善资料,
赚取积分