0 前言
?? 這兩年開始畢業(yè)設(shè)計和畢業(yè)答辯的要求和難度不斷提升,傳統(tǒng)的畢設(shè)題目缺少創(chuàng)新和亮點,往往達不到畢業(yè)答辯的要求,這兩年不斷有學弟學妹告訴學長自己做的項目系統(tǒng)達不到老師的要求。
為了大家能夠順利以及最少的精力通過畢設(shè),學長分享優(yōu)質(zhì)畢業(yè)設(shè)計項目,今天要分享的是
?? 基于stm32的智能運動計步系統(tǒng)
??學長這里給一個題目綜合評分(每項滿分5分)
- 難度系數(shù):2分
- 工作量:3分
- 創(chuàng)新點:4分
1 簡介
基于STM32的智能運動計步系統(tǒng),OLED液晶顯示當前時間,心率,血氧,卡路里,運動時間,步數(shù),最大步數(shù);通過DS1302顯示當前時間,并且具有掉電行走功能;MAX30102模塊檢測當前心率和血氧;ADXL3軸傳感器采集當前行走步數(shù),并且具有掉電保存功能;第一個按鍵進行設(shè)置,第二個按鍵加,第三個按鍵減;第四個一鍵清除當前行走步數(shù);可以設(shè)置當前實時時間和設(shè)置最大運動步數(shù)。
當前步數(shù)大于等于最大運動步數(shù)時主板pa2腳會發(fā)出一個脈沖,從板接收到后通過gsm模塊發(fā)送短信給目標手機提示運動量達到
2 主要器件
- STM32單片機
- MAX30102心率血氧
- DS1302時鐘模塊
- GSM模塊
- ADXL345加速度傳感器
- OLED液晶顯示
- 按鍵設(shè)置
3 實現(xiàn)效果
按鍵設(shè)置
4 設(shè)計原理
4.1 MAX30102模塊
MAX30102是一個集成的脈搏血氧儀和心率監(jiān)測儀生物傳感器的模塊。它集成了一個紅光LED和一個紅外光LED、光電檢測器、光器件,以及帶環(huán)境光抑制的低噪聲電子電路。MAX30102采用一個1.8V電源和一個獨立的5.0V用于內(nèi)部LED的電源,應用于可穿戴設(shè)備進行心率和血氧采集檢測,佩戴于手指、耳垂和手腕等處。標準的2C兼容的通信接口可以將采集到的數(shù)值傳輸給Arduino、KL25Z等單片機進行心率和血氧計算。此外,該芯片還可通過軟件關(guān)斷模塊,待機電流接近為零,實現(xiàn)電源始終維持供電狀態(tài)。正因為其優(yōu)異的性能,該芯片被大量應用在了三星 Galaxy S7 手機。與前代產(chǎn)品 MAX30100 相比 (MAX30100 目前已經(jīng)停產(chǎn)淘汰 ) , MAX30102 集成了玻璃蓋可以有效排除外界和內(nèi)部光干擾,擁有最優(yōu)可靠的性能。
傳統(tǒng)的脈搏測量方法主要有三種:
- 一是從心電信號中提?。?/li>
- 二是從測量血壓時壓力傳感器測到的波動來計算脈率;
- 三是光電容積法。
前兩種方法提取信號都會限制病人的活動,如果長時間使用會增加病人生理和心理上的不舒適感。而光電容積法脈搏測量作為監(jiān)護測量中最普遍的方法之一,其具有方法簡單、佩戴方便、可靠性高等特點。 光電容積法的基本原理是利用人體組織在血管搏動時造成透光率不同來進行脈搏和血 氧飽和度測量的。其使用的傳感器由光源和光電變換器兩部分組成,通過綁帶或夾子固定 在病人的手指、手腕或耳垂上。光源一般采用對動脈血中氧合血紅蛋白( HbO2 )和血紅蛋 白( Hb )有選擇性的特定波長的發(fā)光二極管(一般選用 660nm 附近的紅光和 900nm 附近的 紅外光)。當光束透過人體外周血管,由于動脈搏動充血容積變化導致這束光的透光率發(fā) 生改變,此時由光電變換器接收經(jīng)人體組織反射的光線,轉(zhuǎn)變?yōu)殡娦盘柌⑵浞糯蠛洼?出。由于脈搏是隨心臟的搏動而周期性變化的信號,動脈血管容積也周期性變化,因此光 電變換器的電信號變化周期就是脈搏率。同時根據(jù)血氧飽和度的定義,其表示為:
MAX30102 本身集成了完整的發(fā)光 LED 及驅(qū)動部分,光感應和 AD 轉(zhuǎn)換部分,環(huán)境光干 擾消除及數(shù)字濾波部分,只將數(shù)字接口留給用戶,極大地減輕了用戶的設(shè)計負擔。用戶只 需要使用單片機通過硬件 I2C或者模擬I2C接口來讀取 MAX30102 本身的FIFO ,就可以得到轉(zhuǎn)換后的光強度數(shù)值,通過編寫相應算法就可以得到心率值和血氧飽和度。
主要原理圖
4.2 GSM模塊
簡介
GSM模塊是將GSM射頻芯片,基帶處理芯片,存儲器,放大器設(shè)備等集成在基板上的功能模塊,以提供獨立的OS,GSM射頻處理,基帶處理和標準接口。
GSM模塊具有發(fā)送SMS短信,語音通話,GPRS數(shù)據(jù)傳輸?shù)然贕SM網(wǎng)絡進行通信的所有基本功能。簡單來講,GSM模塊加上鍵盤、顯示屏和電池,就是一部手機。
gsm模塊工作原理
1、GSM 是一個蜂窩網(wǎng)絡,也就是說移動電話要連接到它能搜索到的最近的蜂窩單元區(qū)域。GSM網(wǎng)絡運行在多個不同的無線電頻率上。
2、GSM網(wǎng)絡一共有4種不同的蜂窩單元尺寸:巨蜂窩,微蜂窩,微微蜂窩和傘蜂窩。覆蓋面積因不同的環(huán)境而不同。巨蜂窩可以被看作那種基站天線安裝在天線桿或者建筑物頂上那種。微蜂窩則是那些天線高度低于平均建筑高度的那些,一般用于市區(qū)內(nèi)。微微蜂窩則是那種很小的蜂窩只覆蓋幾十米的范圍,主要用于室內(nèi)。傘蜂窩則是用于覆蓋更小的蜂窩網(wǎng)的盲區(qū),填補蜂窩之間的信號空白區(qū)域。
3、蜂窩半徑范圍根據(jù)天線高度、增益和傳播條件可以從百米以上至數(shù)十公里。實際使用的最長距離GSM規(guī)范支持到35公里。還有個擴展蜂窩的概念,蜂窩半徑可以增加一倍甚至更多。
GSM同樣支持室內(nèi)覆蓋,通過功率分配器可以把室外天線的功率分配到室內(nèi)天線分布系統(tǒng)上。這是一種典型的配置方案,用于滿足室內(nèi)高密度通話要求,在購物中心和機場十分常見。然而這并不是必須的,因為室內(nèi)覆蓋也可以通過無線信號穿越建筑物來實現(xiàn),只是這樣可以提高信號質(zhì)量減少干擾和回聲。
4.3 ADXL345加速度傳感器
ADXL345 是 ADI 公司推出的基于 iMEMS 技術(shù)的 3 軸、數(shù)字輸出加速度傳感器。該加速度傳感器的特點有:
-
分辨率高。最高 13 位分辨率。
-
量程可變。具有+/-2g, +/-4g, +/-8g, +/-16g 可變的測量范圍。
-
靈敏度高。最高達 3.9mg/LSB,能測量不到 1.0°的傾斜角度變化。
-
功耗低。 40~145uA 的超低功耗,待機模式只有 0.1uA。
-
尺寸小。整個 IC 尺寸只有 3mm5mm1mm, LGA 封裝。
ADXL 支持標準的 I2C 或 SPI 數(shù)字接口,自帶 32 級 FIFO 存儲,并且內(nèi)部有多種運動狀態(tài)檢測和靈活的中斷方式等特性。
ADXL345引腳介紹
引腳功能簡介:文章來源:http://www.zghlxwxcb.cn/news/detail-830693.html
5 部分核心代碼
/*
* ADXL345 三軸加速度傳感器DEMO
* powered by 零知實驗室-[url=http://www.lingzhilab.com]www.lingzhilab.com[/url]
*/
#include "ADXL345.h"
// 默認的I2C地址為0x53
ADXL345 accel;
int16_t ax, ay, az;//原始值
float nx,ny,nz;//重力加速度
#define LED_PIN LED_BUILTIN
bool blinkState = false;
//檢測單擊、雙擊動作參數(shù)設(shè)置
void checkActivitySetup()
{
accel.setTapAxisXEnabled(false);//設(shè)置X軸方向敲擊檢測
accel.setTapAxisYEnabled(false);//y軸方向檢測
accel.setTapAxisZEnabled(true);
accel.setTapThreshold(40);//界限設(shè)置:40*0.0625 = 2.5g
accel.setTapDuration(32);//持續(xù)時間:32*0.625ms = 20 ms
accel.setDoubleTapLatency(80);//延遲:80*1.25ms = 100ms
accel.setDoubleTapWindow(240);//窗口:240*1.25ms = 300ms
}
void checkActivity()
{
Activites act = accel.readActivites();
if (act.isDoubleTap)
{
Serial.println("Double Tap Detected");
} else if (act.isTap)
{
Serial.println("Tap Detected");
}else
{
Serial.println("no activity");
}
}
void setup() {
Serial.begin(9600);
// 初始化ADXL345
Serial.println("Initializing I2C devices...");
accel.initialize();
// 檢測是否連接ADXL345
Serial.println("Testing device connections...");
if(accel.testConnection()){
Serial.println("ADXL345 connection successful");
}else{
Serial.println("ADXL345 connection failed");
}
// Set measurement range
// +/- 2G: ADXL345_RANGE_2G
// +/- 4G: ADXL345_RANGE_4G
// +/- 8G: ADXL345_RANGE_8G
// +/- 16G: ADXL345_RANGE_16G
accel.setRange(ADXL345_RANGE_16G);
checkActivitySetup();//開啟單擊、雙擊動作檢測
// 用LED指示數(shù)據(jù)讀取
pinMode(LED_PIN, OUTPUT);
}
void loop() {
#if 0
// 獲取原始的X,Y,Z三軸的數(shù)據(jù)
accel.getAcceleration(&ax, &ay, &az);
// 顯示 x/y/z 原始數(shù)值
Serial.print("accel:\t");
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.println(az);
#endif
#if 1
//獲取重力轉(zhuǎn)換后的加速度數(shù)值
accel.readNormalize(&nx,&ny,&nz);
//使用低通濾波進行處理,以去除尖峰的不準確結(jié)果
float fx, fy, fz;
//系數(shù)范圍 0.1~0.9
// accel.lowPassFilter(nx,ny,nz,&fx,&fy,&fz,0.5);
Serial.print("gravity:\t");
Serial.print(nx); Serial.print("\t");
Serial.print(ny); Serial.print("\t");
Serial.println(nz);
//
// Serial.print("filter:\t");
// Serial.print(fx); Serial.print("\t");
// Serial.print(fy); Serial.print("\t");
// Serial.println(fz);
#endif
#if 1
checkActivity();//單雙擊動作檢測
#endif
// 閃爍LED
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
delay(300);
}
/** \file max30102.cpp ******************************************************
*
* Project: MAXREFDES117#
* Filename: max30102.cpp
* Description: This module is an embedded controller driver for the MAX30102
*
* Revision History:
*\n 1-18-2016 Rev 01.00 GL Initial release.
*\n
*/
#include "max30102.h"
#include "myiic.h"
#define max30102_WR_address 0xAE
bool maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
/**
* \brief Write a value to a MAX30102 register
* \par Details
* This function writes a value to a MAX30102 register
*
* \param[in] uch_addr - register address
* \param[in] uch_data - register data
*
* \retval true on success
*/
{
/* 第1步:發(fā)起I2C總線啟動信號 */
i2c_Start();
/* 第2步:發(fā)起控制字節(jié),高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(max30102_WR_address | I2C_WR); /* 此處是寫指令 */
/* 第3步:發(fā)送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第4步:發(fā)送字節(jié)地址 */
i2c_SendByte(uch_addr);
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第5步:開始寫入數(shù)據(jù) */
i2c_SendByte(uch_data);
/* 第6步:發(fā)送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 發(fā)送I2C總線停止信號 */
i2c_Stop();
return true; /* 執(zhí)行成功 */
cmd_fail: /* 命令執(zhí)行失敗后,切記發(fā)送停止信號,避免影響I2C總線上其他設(shè)備 */
/* 發(fā)送I2C總線停止信號 */
i2c_Stop();
return false;
}
bool maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
/**
* \brief Read a MAX30102 register
* \par Details
* This function reads a MAX30102 register
*
* \param[in] uch_addr - register address
* \param[out] puch_data - pointer that stores the register data
*
* \retval true on success
*/
{
/* 第1步:發(fā)起I2C總線啟動信號 */
i2c_Start();
/* 第2步:發(fā)起控制字節(jié),高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(max30102_WR_address | I2C_WR); /* 此處是寫指令 */
/* 第3步:發(fā)送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第4步:發(fā)送字節(jié)地址, */
i2c_SendByte((uint8_t)uch_addr);
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第6步:重新啟動I2C總線。下面開始讀取數(shù)據(jù) */
i2c_Start();
/* 第7步:發(fā)起控制字節(jié),高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(max30102_WR_address | I2C_RD); /* 此處是讀指令 */
/* 第8步:發(fā)送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第9步:讀取數(shù)據(jù) */
{
*puch_data = i2c_ReadByte(); /* 讀1個字節(jié) */
i2c_NAck(); /* 最后1個字節(jié)讀完后,CPU產(chǎn)生NACK信號(驅(qū)動SDA = 1) */
}
/* 發(fā)送I2C總線停止信號 */
i2c_Stop();
return true; /* 執(zhí)行成功 返回data值 */
cmd_fail: /* 命令執(zhí)行失敗后,切記發(fā)送停止信號,避免影響I2C總線上其他設(shè)備 */
/* 發(fā)送I2C總線停止信號 */
i2c_Stop();
return false;
}
bool maxim_max30102_init(void)
/**
* \brief Initialize the MAX30102
* \par Details
* This function initializes the MAX30102
*
* \param None
*
* \retval true on success
*/
{
if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1, 0xc0)) // INTR setting
return false;
if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2, 0x00))
return false;
if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR, 0x00)) //FIFO_WR_PTR[4:0]
return false;
if(!maxim_max30102_write_reg(REG_OVF_COUNTER, 0x00)) //OVF_COUNTER[4:0]
return false;
if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR, 0x00)) //FIFO_RD_PTR[4:0]
return false;
if(!maxim_max30102_write_reg(REG_FIFO_CONFIG, 0x6f)) //sample avg = 8, fifo rollover=false, fifo almost full = 17
return false;
if(!maxim_max30102_write_reg(REG_MODE_CONFIG, 0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
return false;
if(!maxim_max30102_write_reg(REG_SPO2_CONFIG, 0x2F)) // SPO2_ADC range = 4096nA, SPO2 sample rate (400 Hz), LED pulseWidth (411uS)
return false;
if(!maxim_max30102_write_reg(REG_LED1_PA, 0x17)) //Choose value for ~ 4.5mA for LED1
return false;
if(!maxim_max30102_write_reg(REG_LED2_PA, 0x17)) // Choose value for ~ 4.5mA for LED2
return false;
if(!maxim_max30102_write_reg(REG_PILOT_PA, 0x7f)) // Choose value for ~ 25mA for Pilot LED
return false;
return true;
}
bool maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
/**
* \brief Read a set of samples from the MAX30102 FIFO register
* \par Details
* This function reads a set of samples from the MAX30102 FIFO register
*
* \param[out] *pun_red_led - pointer that stores the red LED reading data
* \param[out] *pun_ir_led - pointer that stores the IR LED reading data
*
* \retval true on success
*/
{
uint32_t un_temp;
uint8_t uch_temp;
*pun_ir_led = 0;
*pun_red_led = 0;
maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
/* 第1步:發(fā)起I2C總線啟動信號 */
i2c_Start();
/* 第2步:發(fā)起控制字節(jié),高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(max30102_WR_address | I2C_WR); /* 此處是寫指令 */
/* 第3步:發(fā)送ACK */
if (i2c_WaitAck() != 0)
{
printf("read fifo failed");
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第4步:發(fā)送字節(jié)地址, */
i2c_SendByte((uint8_t)REG_FIFO_DATA);
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第6步:重新啟動I2C總線。下面開始讀取數(shù)據(jù) */
i2c_Start();
/* 第7步:發(fā)起控制字節(jié),高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(max30102_WR_address | I2C_RD); /* 此處是讀指令 */
/* 第8步:發(fā)送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
un_temp = i2c_ReadByte();
i2c_Ack();
un_temp <<= 16;
*pun_red_led += un_temp;
un_temp = i2c_ReadByte();
i2c_Ack();
un_temp <<= 8;
*pun_red_led += un_temp;
un_temp = i2c_ReadByte();
i2c_Ack();
*pun_red_led += un_temp;
un_temp = i2c_ReadByte();
i2c_Ack();
un_temp <<= 16;
*pun_ir_led += un_temp;
un_temp = i2c_ReadByte();
i2c_Ack();
un_temp <<= 8;
*pun_ir_led += un_temp;
un_temp = i2c_ReadByte();
i2c_Ack();
*pun_ir_led += un_temp;
*pun_red_led &= 0x03FFFF; //Mask MSB [23:18]
*pun_ir_led &= 0x03FFFF; //Mask MSB [23:18]
/* 發(fā)送I2C總線停止信號 */
i2c_Stop();
return true;
cmd_fail: /* 命令執(zhí)行失敗后,切記發(fā)送停止信號,避免影響I2C總線上其他設(shè)備 */
/* 發(fā)送I2C總線停止信號 */
i2c_Stop();
return false;
}
bool maxim_max30102_reset()
/**
* \brief Reset the MAX30102
* \par Details
* This function resets the MAX30102
*
* \param None
*
* \retval true on success
*/
{
if(!maxim_max30102_write_reg(REG_MODE_CONFIG, 0x40))
return false;
else
return true;
}
5 最后
?? 項目分享與指導:https://gitee.com/sinonfin/sharing文章來源地址http://www.zghlxwxcb.cn/news/detail-830693.html
到了這里,關(guān)于【單片機畢設(shè)選題】 stm32智能運動計步系統(tǒng) - 物聯(lián)網(wǎng) 嵌入式 單片機的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!