在本教程中,我們將使用 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);
}
評論
查看更多