这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取手持数字示波器】使用树莓派PICO驱动BMI160

共5条 1/1 1 跳转至

【换取手持数字示波器】使用树莓派PICO驱动BMI160

助工
2024-05-21 00:07:18   被打赏 45 分(兑奖)     打赏

背景

        最近在倒腾RP2040,板卡上灯珠玩完了,就开始倒腾I2C接口,而玩I2C接口最好的方法就是跳线到I2C外设上把玩。刚好手头上有之前做项目剩下的BMI160的板子,就用这个板子玩I2C。

BMI160简介

        BMI160是一款高性能的惯性测量单元(IMU),它集成了加速度计和陀螺仪,旨在提供稳定且精确的运动数据。以下是BMI160的一些详细特点:

高精度测量

        加速度计:BMI160的加速度计具有极高的灵敏度,能够准确测量设备在三维空间中的加速度变化。无论是静止、匀速运动还是加速运动,它都能提供可靠的数据。

        陀螺仪:陀螺仪部分采用了先进的角速度检测技术,能够实时监测设备的旋转和倾斜角度,为设备提供准确的姿态信息。

低功耗设计

        智能电源管理:BMI160具备智能电源管理功能,可以根据应用需求动态调整工作模式,降低功耗。同时,它还支持休眠和唤醒功能,进一步延长了设备的使用时间。

        低噪声设计:传感器内部的低噪声电路设计使得BMI160在保持高精度测量的同时,具有较低的功耗表现。

集成度高

        单一芯片解决方案:BMI160将加速度计和陀螺仪集成在单个芯片上,大大简化了电路设计。这种设计不仅减少了生产成本,还提高了系统的稳定性和可靠性。

        易于集成:BMI160提供了标准的数字接口(如I²C和SPI),便于与其他电子元件进行连接和通信。这使得它在各种应用场景中都能轻松集成。

小尺寸封装

        紧凑外观:BMI160采用了紧凑的封装设计,使得它在保持高性能的同时,能够轻松适应各种小型设备的需求。

        轻量级:由于采用了先进的材料和技术,BMI160具有较轻的重量,不会对设备造成额外的负担。


        总的来说,BMI160凭借其高精度测量、低功耗设计、高集成度和小尺寸封装等特点,成为各类需要运动检测和测量设备的理想选择。

接线方法

1.jpg图一

        图一中画红色圈位置飞线到BMI160的I2C接口上。

2.jpg图二

        图二中,画红色圈部分与树莓派 PICO的I2C连接,绿色部分在我的板卡上接到VDDIO上

代码编写

commands.py

# command
START_FOC       = const(0x03)
ACC_MODE_NORMAL = const(0x11)
GYR_MODE_NORMAL = const(0x15)
FIFO_FLUSH      = const(0xB0)
INT_RESET       = const(0xB1)
STEP_CNT_CLR    = const(0xB2)
SOFT_RESET      = const(0xB6)

registers.py

# register
PMU_STATUS        = const(0x03)
GYRO_X_L          = const(0x0C)
ACCEL_RANGE       = const(0X41)
GYRO_RANGE        = const(0X43)
INT_MAP_0         = const(0x55)
INT_MAP_1         = const(0x56)
INT_MAP_2         = const(0x57)
CMD               = const(0x7E)

definitions.py

## bit field offsets and lengths
ACC_PMU_STATUS_BIT  = const(4)
ACC_PMU_STATUS_LEN  = const(2)
GYR_PMU_STATUS_BIT  = const(2)
GYR_PMU_STATUS_LEN  = const(2)
GYRO_RANGE_SEL_BIT  = const(0)
GYRO_RANGE_SEL_LEN  = const(3)
ACCEL_RANGE_SEL_BIT = const(0)
ACCEL_RANGE_SEL_LEN = const(4)

## Gyroscope Sensitivity Range options
# see setFullScaleGyroRange()
GYRO_RANGE_2000     = const(0)    # +/- 2000 degrees/second
GYRO_RANGE_1000     = const(1)    # +/- 1000 degrees/second
GYRO_RANGE_500      = const(2)    # +/-  500 degrees/second
GYRO_RANGE_250      = const(3)    # +/-  250 degrees/second 
GYRO_RANGE_125      = const(4)    # +/-  125 degrees/second

## Accelerometer Sensitivity Range options
# see setFullScaleAccelRange()
ACCEL_RANGE_2G      = const(0X03)  # +/-  2g range
ACCEL_RANGE_4G      = const(0X05) # +/-  4g range
ACCEL_RANGE_8G      = const(0X08) # +/-  8g range
ACCEL_RANGE_16G     = const(0X0C) # +/- 16g range

bmi160.py

import registers
import commands
import definitions
from time import sleep_ms, sleep_us
from struct import unpack

class BMI160:

    def __init__(self):
        self._reg_write(registers.CMD, commands.SOFT_RESET)
        sleep_ms(1)

        self._reg_read(0x7F)
        sleep_ms(1)

        self._reg_write(registers.CMD, commands.ACC_MODE_NORMAL)
        while (1 != self._reg_read_bits(registers.PMU_STATUS, definitions.ACC_PMU_STATUS_BIT, definitions.ACC_PMU_STATUS_LEN)):
            pass
        sleep_ms(1)

        self._reg_write(registers.CMD, commands.GYR_MODE_NORMAL)
        sleep_ms(1)
        while (1 != self._reg_read_bits(registers.PMU_STATUS, definitions.GYR_PMU_STATUS_BIT, definitions.GYR_PMU_STATUS_LEN)):
            pass
        sleep_ms(1)

        self.setFullScaleGyroRange(definitions.GYRO_RANGE_250, 250.0)
        self.setFullScaleAccelRange(definitions.ACCEL_RANGE_2G, 2.0)

        self._reg_write(registers.INT_MAP_0, 0xFF)
        self._reg_write(registers.INT_MAP_1, 0xF0)
        self._reg_write(registers.INT_MAP_2, 0x00)

    def _reg_read_bits(self, reg, pos, len):
        b = self._reg_read(reg)
        mask = (1 << len) - 1
        b >>= pos
        b &= mask
        return b

    def _reg_write_bits(self, reg, data, pos, len):
        b = self._reg_read(reg)
        mask = ((1 << len) - 1) << pos
        data <<= pos
        data &= mask
        b &= ~(mask)
        b |= data
        self._reg_write(reg, b)

    def setFullScaleGyroRange(self, range, real):
        self._reg_write_bits(registers.GYRO_RANGE, range, definitions.GYRO_RANGE_SEL_BIT, definitions.GYRO_RANGE_SEL_LEN)
        gyro_range = real

    def setFullScaleAccelRange(self, range, real):
        self._reg_write_bits(registers.ACCEL_RANGE, range, definitions.ACCEL_RANGE_SEL_BIT, definitions.ACCEL_RANGE_SEL_LEN)
        accel_range = real

    def getRawData(self):
        raw = self._regs_read(registers.GYRO_X_L, 12)
        vals = unpack('<6h', bytes(raw))
        return vals
    
    def getRegister(self, reg):
        return self._reg_read(reg)

    def setRegister(self, reg, data):
        self._reg_write(reg, data)


class BMI160_I2C(BMI160):
    def __init__(self, i2c, addr=0x69):
        self.i2c = i2c
        self.addr = addr
        super().__init__()

    def _reg_write(self, reg, data):
        self.i2c.writeto(self.addr, bytes([reg, data]))

    def _reg_read(self, reg):
        return self._regs_read(reg, 1)[0]

    def _regs_read(self, reg, n):
        self.i2c.writeto(self.addr, bytes([reg]))
        sleep_us(2)
        return self.i2c.readfrom(self.addr, n)

main.py

from machine import Pin, I2C
from bmi160 import BMI160_I2C
from time import sleep_ms

i2c = I2C(sda=Pin(21), scl=Pin(22))
bmi160 = BMI160_I2C(i2c)
while True:
    print("{0:>8}{1:>8}{2:>8}{3:>8}{4:>8}{5:>8}".format(*bmi160.getRawData()))
    sleep_ms(1000//25)

运行结果

>>> %Run -c $EDITOR_CONTENT

MPY: soft reboot
   31264  -23835  -21161  -11473  -16412  -15670
   22743   -3364   -3696   10350   -8500    -689
  -19636   -4658  -29486  -29934   15991    1511
  -19540  -25601   -5009   24609   -5118   -3268
   -2341   28048   13233    7505    5471  -12547
  -10720  -24762  -23464   12531   18157    1582
   13790   20958   -6130  -30365   19096   -2712
    8038  -12694  -21511   -6470    9043  -14693
    2005  -25850  -23514   22028   12103   19144
  -16240   -4796    6153  -17913   -8854   15680
   10561  -15754   30936   28389   14195   -1150

总结

        用了一周的micropython了,发现这种应用层便准化的写法真的是太方便了,写出来的代码也几乎不需要修改便可迁移到其他支持micropython的平台上。唯一不确定的是,micropython对比纯C写法性能的消耗相差有多大,需要同一平台详细测试才清楚。






关键词: BMI160     RP2040    

专家
2024-05-21 08:42:20     打赏
2楼

谢谢楼主分享


菜鸟
2024-05-22 12:51:53     打赏
3楼

谢谢分享


工程师
2024-05-22 14:54:03     打赏
4楼

666


专家
2024-05-23 07:53:52     打赏
5楼

学习一下


共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]