在本教程中,我們將使用 ATtiny85 IC、MPU6050 加速度計(jì)和陀螺儀以及 OLED 顯示模塊構(gòu)建一個(gè)簡(jiǎn)單且便宜的計(jì)步器。這款基于 Arduino 的簡(jiǎn)單計(jì)步器由 3V 紐扣電池供電,外出散步或慢跑時(shí)便于攜帶。它還需要很少的組件來(lái)構(gòu)建,代碼也相對(duì)簡(jiǎn)單。本項(xiàng)目中的程序使用 MPU6050 測(cè)量沿 3 軸(X、Y 和 Z)的加速度大小。然后它計(jì)算先前值和當(dāng)前值之間的加速度幅度之差。如果差值大于某個(gè)閾值(步行大于 6 和跑步大于 10),則相應(yīng)地增加步數(shù)。然后,所采取的總步數(shù)會(huì)顯示在 OLED 顯示屏上。
所需組件
要使用 Arduino構(gòu)建此 計(jì)步器, 您將需要以下組件。
Attiny85 IC
MPU6050
OLED顯示模塊
2× 按鈕
5× 10KΩ 電阻器 (SMD)
MPU6050 傳感器模塊 – 簡(jiǎn)介
MPU6050 基于微機(jī)械系統(tǒng) (MEMS) 技術(shù)。該傳感器具有一個(gè) 3 軸加速度計(jì)、一個(gè) 3 軸陀螺儀和一個(gè)內(nèi)置溫度傳感器。它可用于測(cè)量加速度、速度、方向、位移等參數(shù)。
MPU6050模塊體積小,功耗低,重復(fù)次數(shù)高,抗沖擊能力強(qiáng),用戶價(jià)位低。MPU6050 帶有 I2C 總線和輔助 I2C 總線接口,可以輕松干擾磁力計(jì)和微控制器等其他傳感器。
Attiny85計(jì)步器電路圖
MPU6050計(jì)步器原理圖如下:
上圖顯示了將 MPU6050 和 OLED 顯示器與 Attiny85 IC 連接的電路圖。MPU6050、OLED Display和Arduino之間的接口必須使用I2C協(xié)議實(shí)現(xiàn)。因此,ATtiny85 的 SCLPin (PB2) 分別連接到 MPU6050 和 OLED 顯示器的 SCLPin。同樣,ATtiny85 的 SDAPin (PB0) 連接到 MPU6050 和 OLED Display 的 SDAPin。兩個(gè)按鈕也連接到 ATtiny85 IC 的 PB3 和 PB4 引腳。這些按鈕可用于滾動(dòng)文本或更改顯示的文本。
注意: 按照我們之前的教程 使用 Digispark Bootloader 直接通過(guò) USB 編程 ATtiny85 IC 通過(guò) USB 和 Digispark Boot-loader 對(duì) ATtiny85 IC 進(jìn)行編程。
為 Attiny85 計(jì)步器制作 PCB
原理圖已經(jīng)完成,我們可以繼續(xù)布局 PCB。您可以使用您選擇的任何 PCB 軟件來(lái)設(shè)計(jì) PCB。我們已經(jīng)使用 EasyEDA 為這個(gè)項(xiàng)目制造 PCB。
下面是計(jì)步器 PCB 頂層和底層的 3D 模型視圖:
組裝 ATtiny85 計(jì)步器 PCB
幾天后,我們收到了整齊包裝的 PCB,PCB 質(zhì)量一如既往地好。板子的頂層和底層如下圖所示:
在確保軌道和腳印是正確的之后。我繼續(xù)組裝PCB。完全焊接的板如下所示:
ATtiny85計(jì)步器代碼說(shuō)明
文檔末尾給出了完整的 Arduino 計(jì)步器代碼。在這里,我們將解釋代碼的一些重要部分。
該代碼使用 TinyWireM.h&TinyOzOLED.h 庫(kù)。TinyWireM 庫(kù)可以從 Arduino IDE 中的庫(kù)管理器下載并從那里安裝。為此,打開(kāi) Arduino IDE 并轉(zhuǎn)到Sketch 《 Include Library 《 Manage Libraries?,F(xiàn)在搜索 TinyWireM.h 并安裝 Adafruit 的 TinyWireM 庫(kù)。
雖然 可以從給定的鏈接下載TinyOzOLED.h庫(kù)。
將庫(kù)安裝到 Arduino IDE 后,通過(guò)包含所需的庫(kù)文件來(lái)啟動(dòng)代碼。
?
#include "TinyWireM.h" #include "TinyOzOLED.h"
?
包含庫(kù)后,定義變量以存儲(chǔ)加速度計(jì)讀數(shù)。
?
intaccelX,加速,加速Z;
?
在setup?()?循環(huán)中,初始化線庫(kù)并通過(guò)電源管理寄存器重置傳感器,同時(shí)初始化 OLED 顯示器的 I2C 通信。然后在下一行設(shè)置顯示方向并輸入加速度計(jì)和陀螺儀值的寄存器地址。
?
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()?函數(shù)中,首先讀取加速度計(jì)數(shù)據(jù)。每個(gè)軸的數(shù)據(jù)存儲(chǔ)在兩個(gè)字節(jié)(高位和低位)或寄存器中。為了全部讀取它們,從第一個(gè)寄存器開(kāi)始,并使用?requestFrom()?函數(shù),我們請(qǐng)求讀取 X、Y 和 Z 軸的所有 6 個(gè)寄存器。然后我們從每個(gè)寄存器中讀取數(shù)據(jù),因?yàn)檩敵鍪嵌M(jìn)制補(bǔ)碼,所以適當(dāng)?shù)亟M合它們以獲得完整的加速度計(jì)值。
?
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(); }
?
現(xiàn)在在循環(huán)函數(shù)中,首先讀取 X、Y 和 Z 軸值,在獲得 3 軸值后,通過(guò)取 X、Y 和 Z 軸值的平方根來(lái)計(jì)算總加速度矢量。然后計(jì)算當(dāng)前向量與前一個(gè)向量的差值,如果差值大于 6,則增加步數(shù)。
?
獲取加速(); 向量 = sqrt( (accelX * accelX) + (accelY * accelY) + (accelZ * accelZ) ); 總向量 = 向量 - 向量前一個(gè); 如果(總向量> 6){ 步驟++; } OzOled.printString("步驟", 0, 4); OzOled.printNumber(Steps, 0, 8, 4); 矢量上一個(gè) = 矢量; 延遲(600);
?
讓我們帶著我們的 Arduino 計(jì)步器去散步吧
完成 PCB 組裝后,將 ATtiny85 連接到編程器板,然后上傳代碼?,F(xiàn)在拿起你手中的計(jì)步器,開(kāi)始一步一步地走,它應(yīng)該會(huì)在 OLED 上顯示步數(shù)。有時(shí),當(dāng)設(shè)置振動(dòng)非??旎蚍浅B龝r(shí),它會(huì)增加步數(shù)。
#include "TinyWireM.h"
#include "TinyOzOLED.h"
int accelX, accelY, accelZ;
字符 mpu = 0x68;
浮動(dòng)矢量previous;
浮動(dòng)向量;
浮動(dòng)總向量;
整數(shù)步數(shù) = 0;
void setup() {
TinyWireM.begin();
ozOled.init();
OzOled.clearDisplay();
OzOled.setNormalDisplay();
OzOled.sendCommand(0xA1); // 設(shè)置方向
OzOled.sendCommand(0xC8);
TinyWireM.beginTransmission(mpu);
TinyWireM.write(0x6B); // 電源設(shè)置地址
TinyWireM.write(0b00000000); // 禁用睡眠模式(以防萬(wàn)一)
TinyWireM.endTransmission();
TinyWireM.beginTransmission(mpu);
TinyWireM.write(0x1B); // 陀螺儀配置寄存器
TinyWireM.write(0x00000000); // 每秒 250° 范圍(默認(rèn))
TinyWireM.endTransmission();
TinyWireM.beginTransmission(mpu); //MPU的I2C地址
TinyWireM.write(0x1C); // 加速度計(jì)配置寄存器
TinyWireM.write(0b00000000); // 2g 范圍 +/- (默認(rèn))
TinyWireM.endTransmission();
}
無(wú)效循環(huán)() {
getAccel();
向量 = sqrt( (accelX * accelX) + (accelY * accelY) + (accelZ * accelZ) );
//OzOled.printString("Vec:", 0, 2);
//OzOled.printNumber(vector, 0, 5, 2);
總向量 = 向量 - 向量前一個(gè);
//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);
//字符數(shù)據(jù)[2];
//Step_count.toCharArray(data, 2);
//OzOled.printBigNumber(data, 6, 2, 3);
OzOled.printString("步驟", 0, 4);
OzOled.printNumber(Steps, 0, 8, 4);
矢量上一個(gè) = 矢量;
延遲(600);
//OzOled.clearDisplay();
}
void getAccel() {
TinyWireM.beginTransmission(mpu); //MPU的I2C地址
TinyWireM.write(0x3B); // 加速度數(shù)據(jù)寄存器
TinyWireM.endTransmission();
TinyWireM.requestFrom(mpu, 6); // 獲取 6 個(gè)字節(jié),每個(gè)自由度 2 個(gè)
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);
}
評(píng)論
查看更多