Make writing a habit together! This is the 7th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.
One, foreword
In recent years, with the progress of science and technology and the arrival of the wave of intelligence, smart wearable devices are also developing rapidly. Various smart health bracelets, smart watches, smart running shoes and smart glasses have been put on the market, and many health management devices for individuals and families have emerged. For example: intelligent blood pressure meter, intelligent heart rate detection, fat scale, intelligent weight scale and so on, all with intelligent, health labels.
A wearable device is a portable device that is worn directly on the body or integrated into a user’s clothing or accessories. Wearable devices are not only hardware devices, but also achieve powerful functions through software support, data interaction and cloud interaction. Wearable devices will bring great changes to life and perception.
This article uses STM32 and a variety of peripheral sensors with Huawei cloud IOT platform to design a health management equipment, through ESP8266+MQTT protocol will lead to the data transmission of Huawei cloud IOT platform, and through the application side of Huawei cloud to complete the application layer software development; The purpose of this project is to experience huawei cloud Internet of Things platform and explore the realization principle of smart devices.
The current design of monitoring and management equipment supports the following functions: (1) human body temperature measurement (2) exercise monitoring, step counting function (3) sleep monitoring (4) heart rate measurement
STM32 collects these sensor data, processes it, and displays it on a local OLED display. Data is then transmitted to Huawei Cloud Internet of Things platform through ESP8266, and the data is displayed on the large visual screen associated with the data.
Here is the heart rate display measured by oscilloscope:
Operation effect of equipment:
2. Hardware introduction
2.1 Main control Chip
The main control chip uses STM32F103C8T6, which is a 32-bit microcontroller based on ARM Cortex-M kernel STM32 series. The program memory capacity is 64KB, THE RAM space is 20K, the working voltage is 2V~3.6V, and the running speed is 72MHZ.
2.2 Temperature Measurement
Human body temperature measurement, using non-contact infrared temperature measurement core gY-MCU90615, working voltage 3-5V, low power consumption, small volume. Its working principle is to read infrared temperature data through single chip microcomputer and output it through serial port (TTL level) communication. Serial port baud rate of 9600bps and 115200bps have continuous output and query output two ways, can adapt to different working environment, and all the microcontroller and computer connection.
2.3 Heart rate Measurement
Heart rate measurement adopts PulseSensor sensor, which is a photoelectric reflection type analog sensor used for pulse heart rate measurement. Through the analog output port, the collected analog signal can be transmitted to STM32 MCU for digital signal conversion, and then the heart rate value can be obtained after simple calculation by MCU.
2.4 Step-counting and sleep monitoring functions
The stepper module, sleep monitoring and motion monitoring functions are realized by the MUP6050 gyroscope, which is a high-performance six-axis sensor with three-axis acceleration and three-axis gyroscope. The module adopts the MPU6050 chip of InvenSense as the core, which integrates the three-axis gyroscope and the three-axis acceleration sensor internally. The hardware acceleration engine of digital motion processor can be used to output the attitude data to the application end through the main IIC interface. With DMP, the motion processing database provided by InvenSense can be used to easily realize attitude calculation, which reduces the load of motion processing operations on the operating system and greatly reduces the difficulty of development. The MPU6050 module has the following features: small size, built-in DMP, built-in temperature sensor, support for IIC slave address setting and interruption, compatible with 3.3V/5V system, easy to use and so on.
(5) The OLED display used for local data display adopts a 0.96 inch SPI interface display with a resolution of 128*64, which mainly displays the collected data, time and other information locally.
(6) The Internet module adopts ESP8266, which is a common wireless network card chip in the field of Internet of Things. ESP8266 supports AT instructions and serial protocol control. Only a few SIMPLE AT instructions can complete network connection and data transmission. In the current project, ESP8266 is used to transfer the collected data to Huawei cloud IOT platform for data display.
3. Create IOT products and test them on the cloud
3.1 Creating a Product
Website address: www.huaweicloud.com/s/JeeJqeiBl…
Select IOTDA to enter and select free trial.
On the product page, select create product in the upper right corner.
Enter parameters as prompted.
After creation, view product details and enter the property configuration page.
Select a custom model.
Add a service.
Next, add attributes, which are the data type uploaded by the sensor, the data that needs to be displayed; Set them according to the number and type of sensors.
Add heart rate sensor data attributes.
Add temperature sensor data attributes.
Add data attributes for step counting.
Successful creation:
3.2 Registering a Device
Open the device page, click on the upper right corner of the device registration button, according to the prompts and product information fill in; Save the resulting information after creation.
After clicking OK, the successful creation effect is as follows; The device is not activated. You need to log in to the server once to activate the device. The next step is how to log in.
3.3 Cloud Test on the device
After the products and devices are created, the MQTT client is used to simulate the devices to test whether huawei cloud can be used normally.
Connection protocol using MQTT protocol, MQTT protocol login server, just like QQ login, need to enter some information such as account number, password; The following uses a huawei cloud gadget to create the data.
Huawei Cloud provides MQTT account information generation online gadget: iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
Fill in the data in the first two lines as shown in the downloaded file when the device is successfully created.
The data generated by my device is as follows:
ClientId 61df9a6bc7fb24029b0c160d_1126626497_0_0_2022011303
Username 61df9a6bc7fb24029b0c160d_1126626497
Password 20618c172eb24418e0910804889c7d2074a5847e9e7205a41a8bf5adeec399f9
Copy the code
The MQTT server address of huawei Cloud IOT platform is as follows:
Port: 1883 Domain name: A161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com IP address: 121.36.42.100Copy the code
Huawei Cloud IOT Platform MQTT protocol subscription subject format:
$OC /devices/{device_id}/sys/messages/down // Subscribe topic: Platform release message to $61 df9a6bc7fb24029b0c160d_1126626497 oc/devices/equipment/sys/messages/downCopy the code
Huawei Cloud IOT Platform MQTT report subject format:
Format: $oc/devices/{device_id}/sys/properties/report // Device reports a topic request $61 oc/devices/df9a6bc7fb24029b0c160d_1126626497 / sys/properties/report / / report the following data format {" services ": [{" service_id" : "healthy","properties":{"HeartRate":127}},{"service_id": "healthy","properties":{"motion":2000}},{"service_id": "Healthy" and "properties" : {" temperature ", 36.2}}}]Copy the code
Open the MQTT client, fill in the corresponding data, and connect to Huawei Cloud Iot platform:
If you need to use the same software as mine, open Baidu search MQTT client _v2.4(protocol 3.1.1).exe to find the download address.
On the Huawei cloud page, you can view that the device is online and the uploaded data is displayed.
Iv. Application software development
4.1 Function Description
In order to display device data and interact with the device more conveniently, a supporting upper computer needs to be developed. API interface and SDK interface of application side development are officially provided. For convenience and general use, I use API interface to complete data interaction here, and QT is used to develop the upper computer software.
Help document address: support.huaweicloud.com/usermanual-…
4.2 Interface for Querying Device Properties
Device attributes are the sensor status data uploaded by the device. The application side provides an API interface to proactively send request instructions to the device side. After receiving the command, the device needs to report the data according to the agreed data format. Therefore, data interaction between the application layer and the device can only be realized through cooperation between the application layer and the device.
The following describes the implementation process of application test and device test respectively.
(1) Instructions issued by the application layer
Help document address: support.huaweicloud.com/api-iothub/…
The online debugging of the interface address: apiexplorer.developer.huaweicloud.com/apiexplorer…
If the request parameters and return values are not clear, experiment with the online debugging interface before writing code to verify that the data interaction is OK.
The two most commonly required parameters in the request parameters are the device ID and the service ID, which are described in Section 3 and can be seen when creating custom properties on the product page.
Request interface summary:
Request method GET URI address/V5 /iot/{project_id}/devices/{device_id}/properties Transport protocol HTTPS Concatenated address: https://iotda.cn-north-4.myhuaweicloud.com/v5/iot/0e5957be8a00f53c2fa7c0045e4d8fbf/devices/61df9a6bc7fb24029b0c160d_1126 626497/properties? Service_id =1126626497 Project_id and device_id must be modified based on your device information. Request header: {" user-agent ": "API Explorer", "x-Auth-token ": "******", this is the authentication Token" content-Type ": {"response": {"services": [{"service_id": "healthy", "properties": {"HeartRate": 127 } }, { "service_id": "healthy", "properties": { "motion": 2000 } }, { "service_id": "healthy", "properties": {"temperature": 36.2}}]}}Copy the code
The x-subject-token parameter needs to be filled in the request header. This parameter is required for accessing any Huawei cloud. The specific process for obtaining this parameter can be found here. Bbs.huaweicloud.com/blogs/31775… Turn to section 3.
(2) The device uploads data
When the application layer requests the device to query device attributes, the device receives the following message:
$oc/devices/61df9a6bc7fb24029b0c160d_1126626497/sys/properties/get/request_id=336bcb57-0e0a-44d0-90f7-31386cb54a3c{"serv ice_id":"1126626497"}Copy the code
The main parameter in this message is request_id request ID, which is parsed by the device and used in the response data to the application layer.
The request attributes detailed documentation here: support.huaweicloud.com/api-iothub/…
Data format of device response:
Theme format: $oc/devices / {device_id} / sys/properties/get/response/request_id = {request_id} in cases of: $oc/devices/61df9a6bc7fb24029b0c160d_1126626497/sys/properties/get/response/request_id=336bcb57-0e0a-44d0-90f7-31386cb54 Data format of a3C response :{" services": [{"service_id": "healthy","properties":{"HeartRate":127}},{"service_id": "Healthy" and "properties" : {" motion ": 2000}}, {" service_id" : "healthy" and "properties" : {" temperature ", 36.2}}]}Copy the code
Response data format can see here is introduced: support.huaweicloud.com/api-iothub/…
4.3 Online API debugging combined with device simulation
The following uses the MQTT client and the online API to simulate the interface effect:
(1) open the debug page: first apiexplorer.developer.huaweicloud.com/apiexplorer…
Then fill in the device DI and service ID:
(2) Open MQTT client and log in to Huawei Cloud Internet of Things platform (that is, analog devices go online) :
(3) Open the online API debugging page and click debug: Click and you can see that the page is already waiting for the response of the client.
(4) Detailed response of MQTT client
Concatenate interfaces and data according to the response format described earlier. Then publish the theme.
(5) The application layer receives the response from the client and debugging is successful
After debugging, the response body receives the device property data uploaded by the device.
4.4 Application Layer Core Code
/* function :GetToken */ void Widget::GetToken() {// indicates to GetToken function_select=3; QString requestUrl; QNetworkRequest request; // set the request address QUrl url; / / access token request address requestUrl = QString (" https://iam.%1.myhuaweicloud.com/v3/auth/tokens "). Arg (SERVER_ID); // create TCP server, test //requestUrl="http://10.0.0.6:8080"; / / set the format of data submission request. SetHeader (QNetworkRequest: : ContentTypeHeader, QVariant (" application/json; charset=UTF-8")); SetUrl (requestUrl); request.setUrl(url); QString text =QString("{"auth":{"identity":{"methods":["password"],"password":" "{"user":{"domain": {" ""name":"%1"},"name": "%2","password": "%3"}}}," ""scope":{"project":{"name":"%4"}}}}") .arg(MAIN_USER) .arg(IAM_USER) .arg(IAM_PASSWORD) .arg(SERVER_ID); Manager ->post(request, text.toutf8 ()); } // Query device properties void Widget::Get_device_properties() {// Obtain token function_select=0; QString requestUrl; QNetworkRequest request; // set the request address QUrl url; / / access token request address requestUrl = QString (" https://iotda.%1.myhuaweicloud.com/v5/iot/%2/devices/%3/properties?service_id=%4 ") .arg(SERVER_ID) .arg(PROJECT_ID) .arg(device_id) .arg(service_id); // create TCP server, test //requestUrl="http://10.0.0.6:8080"; / / set the format of data submission request. SetHeader (QNetworkRequest: : ContentTypeHeader, QVariant (" application/json ")); SetRawHeader (" x-auth-token ", token); SetUrl (requestUrl); request.setUrl(url); Manager ->get(request); }Copy the code
5. Low-level development of equipment
Space is limited, the whole project engineering and PC source can be downloaded here: download.csdn.net/download/xi…
The following lists some of the sensor core processing code at the bottom of the STM32 device.
5.1 Heart rate acquisition calculation algorithm
int BPM; Int Signal; // Hold original data int IBI = 600; unsigned char Pulse = false; unsigned char QS = false; int rate[10]; unsigned long sampleCounter = 0; unsigned long lastBeatTime = 0; int P =512; int T = 512; int thresh = 512; int amp = 100; unsigned char firstBeat = true; unsigned char secondBeat = false; /* Void TIM2_IRQHandler(void) {uint16_t runningTotal=0; uint8_t i; uint16_t Num; If (TIM2-> sr&1 <<0) {TIM2-> sr&1 Signal = Get_AdcCHx_DATA(1); sampleCounter += 2; Num = sampleCounter - lastBeatTime; As the trough of the pulse wave if(Signal < thresh && Num > (IBI/5)*3) {if(Signal < T) {T = Signal; } } if(Signal > thresh && Signal > P) { P = Signal; } // Start looking for the heartbeat // When the pulse comes, If (Num > 250) {if ((signal > thresh) && (Num > (IBI/5)*3)) {Pulse = true; //LED0(0); IBI = sampleCounter - lastBeatTime; lastBeatTime = sampleCounter; if(secondBeat) { secondBeat = false; for(i=0; i<=9; i++) { rate[i] = IBI; } } if(firstBeat) { firstBeat = false; secondBeat = true; return; } for(i=0; i<=8; i++) { rate[i] = rate[i+1]; runningTotal += rate[i]; } rate[9] = IBI; runningTotal += rate[9]; runningTotal /= 10; BPM = 60000/runningTotal; QS = true; If (Signal < thresh && Pulse == true) {Pulse = false; amp = P - T; thresh = amp/2 + T; P = thresh; T = thresh; If (Num > 2500) {thresh = 512; P = 512; T = 512; lastBeatTime = sampleCounter; firstBeat = true; secondBeat = false; } } TIM2->SR&=0x0; // clear interrupt flag}Copy the code
5.2 OLED key codes
// Write a byte to SSD1106. //dat: data to be written/command // CMD: data/command flag 0, indicating the command; 1, data; void OLED_WR_Byte(u8 dat,u8 cmd) { u8 i; if(cmd) OLED_DC_Set(); else OLED_DC_Clr(); OLED_CS_Clr(); for(i=0; i<8; i++) { OLED_SCLK_Clr(); if(dat&0x80) OLED_SDIN_Set(); else OLED_SDIN_Clr(); OLED_SCLK_Set(); dat<<=1; } OLED_CS_Set(); OLED_DC_Set(); } // Set the coordinate position (x range :0~ 127, y range :0~63) // Note: Void OLED_Set_Pos(unsigned char x, unsigned char y) {OLED_WR_Byte(0xb0+y,OLED_CMD); OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD); OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD); }Copy the code
5.3 Temperature collection conversion
u8 Receive_ok; u8 rebuf[20]={0}; void RxTempInfo(void) { static uint8_t i=0; If (USART2 - > SR & 1 < < 5) / / judge receiving symbol {rebuf [i++] = USART2 - > DR; If (rebuf[0]! I =0; if((i==2)&&(rebuf[1]! I =0; Byte REBUf [3] {if(I >3)// If I is equal to 4, the data volume is empty. Byte REBUf [3] {if(I! =(rebuf[3]+5))// If a frame is empty, return; Switch (REBUf [2]) // Unusable {case 0x45: if(! Receive_ok)// New data is received after data processing is complete. {Receive_ok=1; } break; case 0x15:break; case 0x35:break; } i=0; Void GetTempInfo(void) {float TO=0,TA=0; u8 sum=0,i=0; for(sum=0,i=0; i<(rebuf[3]+4); i++) { sum+=rebuf[i]; } the if (sum = = rebuf [I]) / / check and judge {TO = (float) ((rebuf [4] < < 8) | rebuf [5]) / 100; / / get the real temperature TA = (float) ((rebuf [6] < < 8) | rebuf [7]) / 100; Printf ("TO: %f\r\n",TO); printf("TA: %f\r\n",TA); }Copy the code
5.4 Motion step counting algorithm
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LOCAL VARIABLES * / / / store three axis data float oriValues[3] = {0}; Float tempValue[VALUE_NUM] ={0}; float tempValue[VALUE_NUM] ={0}; int tempCount = 0; U8 isDirectionUp = FALSE; Int continueUpCount = 0; continueUpCount = 0; Int continueUpFormerCount = 0; int continueUpFormerCount = 0; U8 lastStatus = FALSE; // Float peakOfWave = 0; Float valleyOfWave = 0; float valleyOfWave = 0; Long timeOfThisPeak = 0; Long timeOfLastPeak = 0; Long timeOfNow = 0; // The value of the current sensor float gravityNew = 0; // Last sensor value float gravityOld = 0; Float initialValue = (float) 1.3; float initialValue = (float) 1.3; // Initial threshold float ThreadValue = (float) 2.0; // accValue_t accValue; Static sportsInfo_t sportsInfo; static sportsInfo_t sportsInfo; Static u8 stepTempCount =0; / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * the function name: DetectorNewStep * function description: * pace update: If the wave peak is detected and meets the conditions of time difference and threshold value, it is judged as 1 step * Threshold update: The time difference condition is met and the difference of peak and trough is greater than initialValue, the difference will be included in the calculation of threshold * parameter Description: Values: Processed G-sensor data timeStamp_p: timestamp * sportsInfo_t *onSensorChanged(accValue_t *pAccValue,timeStamp_t *timeStamp_p,personInfo_t * personInfo) *******************************************************************************/ sportsInfo_t *DetectorNewStep(float values,timeStamp_t *timeStamp_p,personInfo_t * personInfo) { static u32 time_old; personInfo_t *userInfo = personInfo; static u32 step_per_2_second; // Number of steps taken every two seconds float step_lenth,walk_speed,walk_distance,Calories; // Step u32 time_now; timeStamp_t *time_p = timeStamp_p; if (gravityOld == 0) { gravityOld = values; } else {if (DetectorPeak(values, gravityOld)) {timeOfLastPeak = timeOfThisPeak; // Update the time of the last peak // convert the timestamp to milliseconds ms time_now = timeOfNow = ((time_p->hour*60+time_p->minute)*60+time_p->second)*1000+time_p->twentyMsCount*20; If ((timeofnow-timeoflastpeak >= 250)//Jahol Fan set to 300, //&& (timeOfNow - timeOfLastPeak <= 2000) &&(peakOfWave - valleyOfWave >= ThreadValue)) {timeOfThisPeak = timeOfNow; // update the peak time stepTempCount++; //Jahol: step_per_2_second ++; //Jahol: Counting calories this way doesn't filter out human error, If ((time_now - time_old) >= 2000) // if(1 == step_per_2_second) {step_lenth = userInfo->height/5; } else if( 2 == step_per_2_second ) { step_lenth = userInfo->height/4; } else if( 3 == step_per_2_second ) { step_lenth = userInfo->height/3; } else if( 4 == step_per_2_second ) { step_lenth = userInfo->height/2; } else if(5 == step_per_2_second) //Jahol: set the upper limit to 5 steps, sacrificing the accuracy of calories {step_lenth = userInfo->height/1.2f; } else if( 7 == step_per_2_second ) { step_lenth = userInfo->height; } else if(step_per_2_second >= 8) // step_diff>8 {step_lenth = userInfo->height*1.2f; } else { step_lenth = 0; } walk_speed = step_per_2_second*step_lenth/2; Walk_distance = step_per_2_second*step_lenth; // Walking distance, unit: meter = 4.5f*walk_speed*(userInfo->weight/2)/1800; //Jahol:weight is in kg sportsInfo. Calorie += calorie; sportsInfo.distance += walk_distance; time_old = time_now; // Update time step_per_2_second = 0; } else {//do nothing} /* * handle invalid movement: * 1. Step counting starts after 5 consecutive records * 2. For example, if the user stops for more than 3 seconds, the previous record will be invalid and the next time the user starts from the beginning * 3. * */ if ((stepTempCount< 5)&&(timeOfNow - timeOfLastPeak >= 3000)) {stepTempCount = 0; } else if((stepTempCount>= 5)&&(timeOfNow - timeOfLastPeak <= 3000)) { sportsInfo.stepCount += stepTempCount; stepTempCount = 0; } else {//do nothing}} //Jahol: update the threshold. if (timeOfNow - timeOfLastPeak >= 250 && (peakOfWave - valleyOfWave >= initialValue)) { timeOfThisPeak = timeOfNow; ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave); GravityOld = values; return &sportsInfo; }Copy the code