如何使用ATtiny85和MPU6050构建计步器

测量仪表

1495人已加入

描述

  在本教程中,我们将使用 ATtiny85 IC、MPU6050 加速度计和陀螺仪以及 OLED 显示模块构建一个简单且便宜的计步器。这款基于 Arduino 的简单计步器由 3V 纽扣电池供电,外出散步或慢跑时便于携带。它还需要很少的组件来构建,代码也相对简单。本项目中的程序使用 MPU6050 测量沿 3 轴(X、Y 和 Z)的加速度大小。然后它计算先前值和当前值之间的加速度幅度之差。如果差值大于某个阈值(步行大于 6 和跑步大于 10),则相应地增加步数。然后,所采取的总步数会显示在 OLED 显示屏上。

  所需组件

  要使用 Arduino构建此 计步器, 您将需要以下组件。

  Attiny85 IC

  MPU6050

  OLED显示模块

  2× 按钮

  5× 10KΩ 电阻器 (SMD)

  MPU6050 传感器模块 – 简介

  MPU6050 基于微机械系统 (MEMS) 技术。该传感器具有一个 3 轴加速度计、一个 3 轴陀螺仪和一个内置温度传感器。它可用于测量加速度、速度、方向、位移等参数。

  MPU6050模块体积小,功耗低,重复次数高,抗冲击能力强,用户价位低。MPU6050 带有 I2C 总线和辅助 I2C 总线接口,可以轻松干扰磁力计和微控制器等其他传感器。

  Attiny85计步器威廉希尔官方网站 图

  MPU6050计步器原理图如下:

计步器

  上图显示了将 MPU6050 和 OLED 显示器与 Attiny85 IC 连接的威廉希尔官方网站 图。MPU6050、OLED Display和Arduino之间的接口必须使用I2C协议实现。因此,ATtiny85 的 SCLPin (PB2) 分别连接到 MPU6050 和 OLED 显示器的 SCLPin。同样,ATtiny85 的 SDAPin (PB0) 连接到 MPU6050 和 OLED Display 的 SDAPin。两个按钮也连接到 ATtiny85 IC 的 PB3 和 PB4 引脚。这些按钮可用于滚动文本或更改显示的文本。

  注意: 按照我们之前的教程 使用 Digispark Bootloader 直接通过 USB 编程 ATtiny85 IC 通过 USB 和 Digispark Boot-loader 对 ATtiny85 IC 进行编程。

  为 Attiny85 计步器制作 PCB

  原理图已经完成,我们可以继续布局 PCB。您可以使用您选择的任何 PCB 软件来设计 PCB。我们已经使用 EasyEDA 为这个项目制造 PCB。

  下面是计步器 PCB 顶层和底层的 3D 模型视图:

计步器

  组装 ATtiny85 计步器 PCB

  几天后,我们收到了整齐包装的 PCB,PCB 质量一如既往地好。板子的顶层和底层如下图所示:

计步器

  在确保轨道和脚印是正确的之后。我继续组装PCB。完全焊接的板如下所示:

计步器

  ATtiny85计步器代码说明

  文档末尾给出了完整的 Arduino 计步器代码。在这里,我们将解释代码的一些重要部分。

  该代码使用 TinyWireM.h&TinyOzOLED.h 库。TinyWireM 库可以从 Arduino IDE 中的库管理器下载并从那里安装。为此,打开 Arduino IDE 并转到Sketch 《 Include Library 《 Manage Libraries。现在搜索 TinyWireM.h 并安装 Adafruit 的 TinyWireM 库。

计步器

  虽然 可以从给定的链接下载TinyOzOLED.h库。

 将库安装到 Arduino IDE 后,通过包含所需的库文件来启动代码。

 

#include "TinyWireM.h"
#include "TinyOzOLED.h"

 

包含库后,定义变量以存储加速度计读数。

 

intaccelX,加速,加速Z;

 

在setup () 循环中,初始化线库并通过电源管理寄存器重置传感器,同时初始化 OLED 显示器的 I2C 通信。然后在下一行设置显示方向并输入加速度计和陀螺仪值的寄存器地址。

 

TinyWireM.begin();
ozOled.init();
OzOled.clearDisplay();
OzOled.setNormalDisplay();
OzOled.sendCommand(0xA1);       
OzOled.sendCommand(0xC8);
TinyWireM.beginTransmission(mpu);
TinyWireM.write(0x6B);
TinyWireM.write(0b00000000);
TinyWireM.write(0x1B);

 

在 getAccel() 函数中,首先读取加速度计数据。每个轴的数据存储在两个字节(高位和低位)或寄存器中。为了全部读取它们,从第一个寄存器开始,并使用 requestFrom() 函数,我们请求读取 X、Y 和 Z 轴的所有 6 个寄存器。然后我们从每个寄存器中读取数据,因为输出是二进制补码,所以适当地组合它们以获得完整的加速度计值。

 

voidgetAccel() {
TinyWireM.beginTransmission(mpu);
TinyWireM.write(0x3B);
TinyWireM.endTransmission();
TinyWireM.requestFrom(mpu, 6);
accelX = TinyWireM.read() << 8|TinyWireM.read();
accelY = TinyWireM.read() << 8|TinyWireM.read();
accelZ = TinyWireM.read() << 8|TinyWireM.read();
}

 

现在在循环函数中,首先读取 X、Y 和 Z 轴值,在获得 3 轴值后,通过取 X、Y 和 Z 轴值的平方根来计算总加速度矢量。然后计算当前向量与前一个向量的差值,如果差值大于 6,则增加步数。

 

获取加速();
向量 = sqrt( (accelX * accelX) + (accelY * accelY) + (accelZ * accelZ) );
总向量 = 向量 - 向量前一个;
如果(总向量> 6){
  步骤++;
}
OzOled.printString("步骤", 0, 4);
OzOled.printNumber(Steps, 0, 8, 4);
矢量上一个 = 矢量;
延迟(600);

 

  让我们带着我们的 Arduino 计步器去散步吧

  完成 PCB 组装后,将 ATtiny85 连接到编程器板,然后上传代码。现在拿起你手中的计步器,开始一步一步地走,它应该会在 OLED 上显示步数。有时,当设置振动非常快或非常慢时,它会增加步数。

计步器

#include "TinyWireM.h"

#include "TinyOzOLED.h"

int accelX, accelY, accelZ;

字符 mpu = 0x68;

浮动矢量previous;

浮动向量;

浮动总向量;

整数步数 = 0;

void setup() {

TinyWireM.begin();

ozOled.init();

OzOled.clearDisplay();

OzOled.setNormalDisplay();

OzOled.sendCommand(0xA1); // 设置方向

OzOled.sendCommand(0xC8);

TinyWireM.beginTransmission(mpu);

TinyWireM.write(0x6B); // 电源设置地址

TinyWireM.write(0b00000000); // 禁用睡眠模式(以防万一)

TinyWireM.endTransmission();

TinyWireM.beginTransmission(mpu);

TinyWireM.write(0x1B); // 陀螺仪配置寄存器

TinyWireM.write(0x00000000); // 每秒 250° 范围(默认)

TinyWireM.endTransmission();

TinyWireM.beginTransmission(mpu); //MPU的I2C地址

TinyWireM.write(0x1C); // 加速度计配置寄存器

TinyWireM.write(0b00000000); // 2g 范围 +/- (默认)

TinyWireM.endTransmission();

}

无效循环() {

getAccel();

向量 = sqrt( (accelX * accelX) + (accelY * accelY) + (accelZ * accelZ) );

//OzOled.printString("Vec:", 0, 2);

//OzOled.printNumber(vector, 0, 5, 2);

总向量 = 向量 - 向量前一个;

//OzOled.printString("Pre:", 0, 4);

//OzOled.printNumber(vectorprevious, 0, 5, 4);

//OzOled.printString("Diff:", 0, 6);

//OzOled.printNumber(totalvector, 0, 5, 6);

if (totalvector > 6){

Steps++;

}

//String Step_count = String(Steps);

//字符数据[2];

//Step_count.toCharArray(data, 2);

//OzOled.printBigNumber(data, 6, 2, 3);

OzOled.printString("步骤", 0, 4);

OzOled.printNumber(Steps, 0, 8, 4);

矢量上一个 = 矢量;

延迟(600);

//OzOled.clearDisplay();

}

void getAccel() {

TinyWireM.beginTransmission(mpu); //MPU的I2C地址

TinyWireM.write(0x3B); // 加速度数据寄存器

TinyWireM.endTransmission();

TinyWireM.requestFrom(mpu, 6); // 获取 6 个字节,每个自由度 2 个

accelX = TinyWireM.read() << 8|TinyWireM.read();

accelY = TinyWireM.read() << 8|TinyWireM.read();

accelZ = TinyWireM.read() << 8|TinyWireM.read();

// OzOled.printNumber(accelX, 0, 0, 0);

// OzOled.printNumber(accelY, 0, 0, 2);

//OzOled.printNumber(accelZ, 0, 0, 4);

}

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分