基於STM32+華爲雲IOT設計智能稱重系統

摘要:選擇部署多個重量傳感器和必要的算法、通過WiFi 通信模塊、GPS定位模塊,採集車輛稱重數據一地理位置信息,並通過網絡發送至雲平臺,設計圖形化UI界面展示稱重、地圖位置等重要信息,實現對稱重系統的遠程監測。

本文分享自華爲雲社區《基於STM32+華爲雲IOT設計智能稱重系統》,作者:DS小龍哥

伴隨着網絡技術,各種通訊技術,傳感器技術的飛速發展,物聯網技術成爲了當今技術領域發展爲迅速的技術。而物聯網技術的核心仍然是以互聯網技術爲基礎的,物聯網是新一代信息技術的重要組成部分,也是信息化時代的重要發展階段。物聯網通過智能感知、識別技術與普適計算等通信感知技術,廣泛應用於網絡的融合中,也因此被稱爲繼計算機、互聯網之後世界信息產業發展的第三次浪潮。

本設計的模型來源於物流、礦山、高速公路等場合,車輛稱重地螃的智能化升級要求,設計基於物聯網的智能在線稱重方案,開發智能稱重控制器,合理選擇部署多個重量傳感器和必要的算法、通過WIFF通信模塊、GPS定位模塊,採集車輛重數據一地理位置信息,並通過網絡發送至雲平臺,設計圖形化UI界面展示稱重、地圖位置等重要信息,實現對稱重系統的遠程監測。

隨着物聯網技術的逐步發展和日趨成熟,物聯網技術是一個大而廣的應用技術,並非僅僅侷限於延伸應用。相信對地磅來說必然會有更多創新的應用實踐。總的來說,地磅現代化、信息化、智能化一定緊隨物聯網技術的發展,而物聯網技術的發展也必將促使地磅興起新的技術革命。

1.設計的技術與硬件選項總結:

(1)雲端通信模塊採用ESP8266-WIFI

(2)聯網通信模塊採用:ESP8266

(3)GPS模塊:採用ATGM336H雙模GPS模塊

(4)電子秤模塊:用於稱重

(5)物聯網雲平臺:採用華爲雲物聯網平臺

設計總結:

(1)採用ESP8266連接OneNet上傳稱重數據和GPS數據到雲端(採用HTTP協議)

雲端上顯示2個數據:GPS定位數據–地圖顯示,稱重傳感器的數據值

(2)3個稱重傳感器接一個秤面稱重計算平均值

(3)本地OLED顯示屏顯示GPS經緯度數據、稱重傳感器的數據值。

(4)OLED設計一個頁面顯示並設置當前的報警上限。通過按鍵進行加減

當稱重的閥值超出了設置閥值,蜂鳴器報警。

2. 硬件選型

2.1 STM32F103C8T6

STM32F103C8T6是一款基於ARM Cortex-M 內核STM32系列的32位的微控制器,程序存儲器容量是64KB,需要電壓2V~3.6V,工作溫度爲-40°C ~ 85°C。

2.2 電子秤傳感器

HX711 是一款專爲高精度稱重傳感器而設計的24位A/D 轉換器芯片。

2.3 ESP8266-wifi

2.4 GPS模塊

2.5 蜂鳴器

3. 創建雲端產品與設備

3.1 創建產品

地址:https://www.huaweicloud.com/?locale=zh-cn

3.2 創建設備

地址: https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/device/all-device

3.3 自定義模型數據

鏈接:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-dev/all-product/7211833377cf435c8c0580de390eedbe/product-detail/6277d70223aaf461a0f72a56
這個模型數據就是設備要上傳的數據。

{
    "device_id": "6277d70223aaf461a0f72a56_weigh",
    "secret": "12345678"
}

服務ID: weigh
屬性名稱    數據類型    訪問方式    描述        
weigh       int(整型)    可讀       重量          
GPS       string(字符串)    可讀      GPS定位信息

3.4 MQTT密匙生成

創建完產品、設備之後,接下來就需要知道如何通過MQTT協議登陸華爲雲服務器。

官方的詳細介紹在這裏:
https://support.huaweicloud.com/devg-iothub/iot_01_2127.html#ZH-CN_TOPIC_0240834853__zh-cn_topic_0251997880_li365284516112

屬性上報格式:
https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html

MQTT設備登陸密匙生成地址: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

DeviceId         6277d70223aaf461a0f72a56_weigh
DeviceSecret     12345678
ClientId        6277d70223aaf461a0f72a56_weigh_0_0_2022050814
Username        6277d70223aaf461a0f72a56_weigh
Password       0a3d097c6449b8526a562006a74c8c5e61ce63d6c831ea291560736a3332cf77

華爲雲物聯網平臺的域名是: 161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
華爲雲物聯網平臺的IP地址是:121.36.42.100
在軟件裏參數填充正確之後,就看到設備已經連接成功了。
接下來打開設備頁面,可以看到設備已經在線了。

3.5 主題訂閱與發佈

//訂閱主題: 平臺下發消息給設備
$oc/devices/6277d70223aaf461a0f72a56_weigh/sys/messages/down
//設備上報數據
$oc/devices/6277d70223aaf461a0f72a56_weigh/sys/properties/report
//上報的屬性消息 (一次可以上報多個屬性,在json裏增加就行了)
{"services": [{"service_id": "weigh","properties":{"GPS":"lat:12.345,lng:45.678"}}]}

通過MQTT客戶端軟件模擬上報測試:

查看控制檯頁面,數據已經上傳成功了。

3.6 應用側開發

爲了更方便的展示設備數據,與設備完成交互,還需要開發一個配套的上位機,官方提供了應用側開發的API接口、SDK接口,爲了方便通用一點,我這裏採用了API接口完成數據交互,上位機軟件採用QT開發。

幫助文檔地址: https://support.huaweicloud.com/api-iothub/iot_06_v5_0034.html

設備屬性就是設備上傳的傳感器狀態數據信息,應用側提供了API接口,可以主動向設備端下發請求指令;設備端收到指令之後需要按照約定的數據格式上報數據;所以,要實現應用層與設備端的數據交互,需要應用層與設備端配合才能完成。

在使用接口時,最好先使用華爲自己的調試接口測試。
https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ListProperties

上位機軟件採用Qt框架設計,Qt是一個跨平臺的C++圖形用戶界面應用程序框架。Qt是一個1991年由Qt Company開發的跨平臺C++圖形用戶界面應用程序開發框架。它既可以開發GUI程序,也可用於開發非GUI程序,比如控制檯工具和服務器。簡單來說,QT可以很輕鬆的幫你做帶界面的軟件,甚至不需要你投入很大精力。

QT官網: https://www.qt.io/

4. STM32設備端開發

4.1 程序下載

4.2 原理圖

4.3 硬件接線

1)OLED顯示屏接線:
D0----(SCK)------------------->>PB14
D1----(MOSI)------------------>>PB13
RES—(復位腳低電平有效)-------->>PB12
DC--(數據和命令控制管腳)------>>PB1
CS--(片選引腳)---------------->>PA7
GND--------------------------->>GND
VCC--------------------------->>3.3V或者5V

(2)ATK-ESP8266 WIFI接線
PA2(TX)--RXD 模塊接收腳
PA3(RX)--TXD 模塊發送腳
GND---GND 地
VCC---VCC 電源(3.3V~5.0V)

(3)外接蜂鳴器模塊: 高電平響
BEEP----->PB8

(4)外接按鍵:
KEY1 -PB3 按下是低電平  清零
KEY2 -PB2 按下是低電平  翻頁
KEY3 -PB6 按下是低電平  加
KEY4 -PB7 按下是低電平  減

(5)外接LED燈模塊:
LED1-PB4 低電平亮
LED2-PB5 低電平亮

(6)稱重傳感器1
VCC--->5V
SCK--->PA4   時序控制腳--對STM32--輸出模式
DT---->PA5   輸出輸出腳-對STM32--輸入模式
GND--->GND

(7)稱重傳感器2
VCC--->5V
SCK--->PA11   時序控制腳--對STM32--輸出模式
DT---->PA12   輸出輸出腳-對STM32--輸入模式
GND--->GND

(8)稱重傳感器3
VCC--->5V
SCK--->PA6   時序控制腳--對STM32--輸出模式
DT---->PA8   輸出輸出腳-對STM32--輸入模式
GND--->GND

(9)GPS模塊接線說明
GND----GND
VCC---3.3V
PB11----GPS_TX
PB10----GPS_RX

(--)板載LED燈:低電平亮
LED1--PC13  
BEEP2--PC14

(--)板載按鍵: 
KEY1--PA0  按下爲高電平

4.4 MQTT連接代碼

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "bluetooth.h"
#include "esp8266.h"
#include "mqtt.h"

//華爲物聯網服務器的設備信息
#define MQTT_ClientID "61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510"
#define MQTT_UserName "61b9ba3a2b2aa20288c1e7f1_QQ1126626497"
#define MQTT_PassWord "385ce91dfe7da5b7431868d5d87e7998163c493344040935d5a00024d6324242"

//訂閱與發佈的主題
#define SET_TOPIC  "$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down"  //訂閱
#define POST_TOPIC "$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report"  //發佈

char mqtt_message[200];//上報數據緩存區

int main()
{
   u32 time_cnt=0;
   u32 i;
   u8 key;
   LED_Init();
   BEEP_Init();
   KEY_Init();
   USART1_Init(115200);
   TIMER1_Init(72,20000); //超時時間20ms
   USART2_Init(9600);//串口-藍牙
   TIMER2_Init(72,20000); //超時時間20ms
   USART3_Init(115200);//串口-WIFI
   TIMER3_Init(72,20000); //超時時間20ms
   USART1_Printf("正在初始化WIFI請稍等.\n");
   if(ESP8266_Init())
   {
      USART1_Printf("ESP8266硬件檢測錯誤.\n");  
   }
   else
   {
      //非加密端口
      USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode("CMCC-Cqvn","99pu58cb","121.36.42.100",1883,1));
  
   }
   
    //2. MQTT協議初始化    
    MQTT_Init(); 
    //3. 連接華爲服務器        
    while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
    {
        USART1_Printf("服務器連接失敗,正在重試...\n");
        delay_ms(500);
    }
    USART1_Printf("服務器連接成功.\n");
    
    //3. 訂閱主題
    if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
    {
        USART1_Printf("主題訂閱失敗.\n");
    }
    else
    {
        USART1_Printf("主題訂閱成功.\n");
    }        
    
    .........

4.5 ESP8266代碼

#include "esp8266.h"
u8 ESP8266_IP_ADDR[16]; //255.255.255.255
u8 ESP8266_MAC_ADDR[18]; //硬件地址
/*
函數功能: ESP8266命令發送函數
函數返回值:0表示成功  1表示失敗
*/
u8 ESP8266_SendCmd(char *cmd)
{
    u8 i,j;
    for(i=0;i<10;i++) //檢測的次數--發送指令的次數
    {
        USARTx_StringSend(USART3,cmd);
        for(j=0;j<100;j++) //等待的時間
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                USART3_RX_FLAG=0;
                USART3_RX_CNT=0;
                if(strstr((char*)USART3_RX_BUFFER,"OK"))
                {
                    return 0;
                }
            }
        }
    }
    return 1;
}

/*
函數功能: ESP8266硬件初始化檢測函數
函數返回值:0表示成功  1表示失敗
*/
u8 ESP8266_Init(void)
{
    //退出透傳模式
    USARTx_StringSend(USART3,"+++");
    delay_ms(50);
    return ESP8266_SendCmd("AT\r\n");
}

/*
函數功能: 一鍵配置WIFI爲AP+TCP服務器模式
函數參數:
char *ssid  創建的熱點名稱
char *pass  創建的熱點密碼 (最少8位)
u16 port    創建的服務器端口號
函數返回值: 0表示成功 其他值表示對應錯誤值
*/
u8 ESP8266_AP_TCP_Server_Mode(char *ssid,char *pass,u16 port)
{
    char *p;
    u8 i;
    char ESP8266_SendCMD[100]; //組合發送過程中的命令
    /*1. 測試硬件*/
    if(ESP8266_SendCmd("AT\r\n"))return 1;
    /*2. 關閉回顯*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 2;
    /*3. 設置WIFI模式*/
    if(ESP8266_SendCmd("AT+CWMODE=2\r\n"))return 3;
    /*4. 復位*/
    ESP8266_SendCmd("AT+RST\r\n");
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    /*5. 關閉回顯*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 5;
    /*6. 設置WIFI的AP模式參數*/
    sprintf(ESP8266_SendCMD,"AT+CWSAP=\"%s\",\"%s\",1,4\r\n",ssid,pass);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 6;
    /*7. 開啓多連接*/
    if(ESP8266_SendCmd("AT+CIPMUX=1\r\n"))return 7;
    /*8. 設置服務器端口號*/
    sprintf(ESP8266_SendCMD,"AT+CIPSERVER=1,%d\r\n",port);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 8;
    /*9. 查詢本地IP地址*/
    if(ESP8266_SendCmd("AT+CIFSR\r\n"))return 9;
    //提取IP地址
    p=strstr((char*)USART3_RX_BUFFER,"APIP");
    if(p)
    {
        p+=6;
        for(i=0;*p!='"';i++)
        {
            ESP8266_IP_ADDR[i]=*p++;
        }
        ESP8266_IP_ADDR[i]='\0';
    }
    //提取MAC地址
    p=strstr((char*)USART3_RX_BUFFER,"APMAC");
    if(p)
    {
        p+=7;
        for(i=0;*p!='"';i++)
        {
            ESP8266_MAC_ADDR[i]=*p++;
        }
        ESP8266_MAC_ADDR[i]='\0';
    }
    
    //打印總體信息
    USART1_Printf("當前WIFI模式:AP+TCP服務器\n");
    USART1_Printf("當前WIFI熱點名稱:%s\n",ssid);
    USART1_Printf("當前WIFI熱點密碼:%s\n",pass);
    USART1_Printf("當前TCP服務器端口號:%d\n",port);
    USART1_Printf("當前TCP服務器IP地址:%s\n",ESP8266_IP_ADDR);
    USART1_Printf("當前TCP服務器MAC地址:%s\n",ESP8266_MAC_ADDR);
    return 0;
}

/*
函數功能: TCP服務器模式下的發送函數
發送指令: 
*/
u8 ESP8266_ServerSendData(u8 id,u8 *data,u16 len)
{
    u8 i,j,n;
    char ESP8266_SendCMD[100]; //組合發送過程中的命令
    for(i=0;i<10;i++)
    {
        sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d,%d\r\n",id,len);
        USARTx_StringSend(USART3,ESP8266_SendCMD);
        for(j=0;j<10;j++)
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                USART3_RX_FLAG=0;
                USART3_RX_CNT=0;
                if(strstr((char*)USART3_RX_BUFFER,">"))
                {
                    //繼續發送數據
                    USARTx_DataSend(USART3,data,len);
                    //等待數據發送成功
                    for(n=0;n<200;n++)
                    {
                        delay_ms(50);
                        if(USART3_RX_FLAG)
                        {
                            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                            USART3_RX_FLAG=0;
                            USART3_RX_CNT=0;
                            if(strstr((char*)USART3_RX_BUFFER,"SEND OK"))
                            {
                                return 0;
                            }
                         }            
                    }   
                }
            }
        }
    }
    return 1;
}

/*
函數功能: 配置WIFI爲STA模式+TCP客戶端模式
函數參數:
char *ssid  創建的熱點名稱
char *pass  創建的熱點密碼 (最少8位)
char *p     將要連接的服務器IP地址
u16 port    將要連接的服務器端口號
u8 flag     1表示開啓透傳模式 0表示關閉透傳模式
函數返回值:0表示成功  其他值表示對應的錯誤
*/
u8 ESP8266_STA_TCP_Client_Mode(char *ssid,char *pass,char *ip,u16 port,u8 flag)
{
    char ESP8266_SendCMD[100]; //組合發送過程中的命令
    //退出透傳模式
    //USARTx_StringSend(USART3,"+++");
    //delay_ms(50);
    /*1. 測試硬件*/
    if(ESP8266_SendCmd("AT\r\n"))return 1;
    /*2. 關閉回顯*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 2;
    /*3. 設置WIFI模式*/
    if(ESP8266_SendCmd("AT+CWMODE=1\r\n"))return 3;
    /*4. 復位*/
    ESP8266_SendCmd("AT+RST\r\n");
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    /*5. 關閉回顯*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 5;
    /*6. 配置將要連接的WIFI熱點信息*/
    sprintf(ESP8266_SendCMD,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pass);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 6;
    /*7. 設置單連接*/
    if(ESP8266_SendCmd("AT+CIPMUX=0\r\n"))return 7;
    /*8. 配置要連接的TCP服務器信息*/
    sprintf(ESP8266_SendCMD,"AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",ip,port);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 8;
    /*9. 開啓透傳模式*/
    if(flag)
    {
       if(ESP8266_SendCmd("AT+CIPMODE=1\r\n"))return 9; //開啓
       if(ESP8266_SendCmd("AT+CIPSEND\r\n"))return 10;  //開始透傳
       if(!(strstr((char*)USART3_RX_BUFFER,">")))
       {
            return 11;
       }
        //如果想要退出發送:  "+++"
    }
    
     //打印總體信息
    USART1_Printf("當前WIFI模式:STA+TCP客戶端\n");
    USART1_Printf("當前連接的WIFI熱點名稱:%s\n",ssid);
    USART1_Printf("當前連接的WIFI熱點密碼:%s\n",pass);
    USART1_Printf("當前連接的TCP服務器端口號:%d\n",port);
    USART1_Printf("當前連接的TCP服務器IP地址:%s\n",ip);
    return 0;
}
/*
函數功能: TCP客戶端模式下的發送函數
發送指令: 
*/
u8 ESP8266_ClientSendData(u8 *data,u16 len)
{
    u8 i,j,n;
    char ESP8266_SendCMD[100]; //組合發送過程中的命令
    for(i=0;i<10;i++)
    {
        sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d\r\n",len);
        USARTx_StringSend(USART3,ESP8266_SendCMD);
        for(j=0;j<10;j++)
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                USART3_RX_FLAG=0;
                USART3_RX_CNT=0;
                if(strstr((char*)USART3_RX_BUFFER,">"))
                {
                    //繼續發送數據
                    USARTx_DataSend(USART3,data,len);
                    //等待數據發送成功
                    for(n=0;n<200;n++)
                    {
                        delay_ms(50);
                        if(USART3_RX_FLAG)
                        {
                            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                            USART3_RX_FLAG=0;
                            USART3_RX_CNT=0;
                            if(strstr((char*)USART3_RX_BUFFER,"SEND OK"))
                            {
                                return 0;
                            }
                         }            
                    }   
                }
            }
        }
    }
    return 1;
}

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章