項目有些久遠,前年的機器人上需要的功能,當時是需要將STM32上的數據上傳到服務器,比如機器人的速度,行駛距離,是否在拍照等等。便于管理者在PC或者手機上了解機器人的工作狀態,同時可以遠程下發指令給機器人,控制其完成相應動作。
因為所有的邏輯判斷和控制都在服務器或者STM32上面,作為中間的無線模塊僅僅需要上傳STM32的數據并接收服務器下發的指令即可,所以這里對WiFi模塊的要求不高,僅僅需要它作為透傳功能即可。當時在選型的時候試過好幾款WiFi模塊,最終敲定了安信可的ESP8266,價格便宜,開發簡單,但是搭建環境是真的不容易,深受其害。
選擇好模塊就該考慮使用AT指令還是使用SDK開發,AT指令固然簡單,但是局限性非常大。如果使用AT指令,我那開發控制端的同事估計就要跳腳了,代碼里需要寫一大堆的AT指令,如果功能改變,指令代碼就需要重寫,煩不勝煩。
如果使用SDK開發,控制端只需發送簡單的數據就行,完全不用考慮其他任何東西,ESP8266完全當做一個中轉站,相對應的我的工作就會繁重,但是,我屈服了,選擇使用SDK。
于是就有了下面基于NONOS 2.0的ESP8266串口透傳。主要有以下幾個功能:
初始化完成后會首先讀取MAC地址,該地址是唯一的,每個模塊都不一樣,用于填充進主題中,便于服務器區分不同設備,用于多臺量產設備的使用,在連接MQTT服務器時會自動填充。
- 純串口透傳,接收MCU串口數據,直接通過MQTT上傳到服務器,接收服務器數據下發給MCU。
- smartconfig+airkiss配網,隨意使用,場景豐富。
- 最多儲存5個WIFI賬號和密碼,自動尋找網絡連接。
- 按鍵配網,長按重新配網,前一次WiFi自動儲存,添加配網指示燈。
- OTA空中升級(待驗證)
程序的入口先進行串口初始化和按鍵的初始化,以及LED的初始化。串口要初始化波特率,按鍵初始化配網按鍵,用于短按配網,長按重新配網,LED只要用于判斷模塊是否進入配網模式以及是否配網完成。//程序入口void ICACHE_FLASH_ATTR user_init(void){uart_init(115200, 115200);os_delay_us(60000);keyInit();set_uart_cb(uart_cb);PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); //GPIO12初始化GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);//低電平get_mac();//獲取MAC地址wifi_set_opmode(STATION_MODE);//設置wifi信息存儲數量,最大為5個wifi_station_ap_number_set(2);mqtt_init();set_wifistate_cb(wifi_connect_cb, wifi_disconnect_cb);}
初始化完成后會首先讀取MAC地址,該地址是唯一的,每個模塊都不一樣,用于填充進主題中,便于服務器區分不同設備,用于多臺量產設備的使用,在連接MQTT服務器時會自動填充。

每連接一次WiFi都會將WiFi信息保存在模塊內部,每次上電都會自動掃描暴露的WiFi,直接連接,就像手機的WIFI連接,目前最大支持五個WiFi信息的保存,超過5個會剔除最早的WiFi信息,通過短按D5(GPIO14)可進入配網模式。
/*** 按鍵短按回調*/LOCAL void ICACHE_FLASH_ATTR key1ShortPress(void) {start_smartconfig(smartconfig_cd);INFO("start_smartconfig ");}/*** 按鍵長按回調*/LOCAL void ICACHE_FLASH_ATTR key1LongPress(void) {start_smartconfig(smartconfig_cd);INFO("start_smartconfig ");}/*** 按鍵初始化*/LOCAL void ICACHE_FLASH_ATTR keyInit(void) {//設置按鍵數量set_key_num(1);//長按、短按的按鍵回調key_add(D5, NULL, key1ShortPress);key_add(D5, NULL, key1LongPress);}
由于找不到最新的代碼。這里的長按我沒做處理,應該是斷開WiFi重新進入配網模式, 或者軟復位模塊,再進入start_smartconfig()函數:
/*** 開始Smartconfig配置* @param cd: Smartconfig狀態回調* @retval None*/void ICACHE_FLASH_ATTR start_smartconfig(smartconfig_cd_t cd) {smartconfig_flag = 1;smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS); //SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISSwifi_station_disconnect();wifi_set_opmode(STATION_MODE);finish_cd = cd;smartconfig_start(smartconfig_done);os_timer_disarm(&OS_Timer_Wifichange); // 關閉定時器if(connect_flag == 1){w_disconnect();connect_flag = 0;}os_timer_disarm(&OS_Timer_SM); // 關閉定時器os_timer_setfn(&OS_Timer_SM, (os_timer_func_t *) sm_wait_time, NULL);// 設置定時器os_timer_arm(&OS_Timer_SM, 1000, 1); // 使能定時器}

smartconfig_set_type();函數可選3個參數:分別是:SC_TYPE_ESPTOUCH、SC_TYPE_AIRKISS和SC_TYPE_ESPTOUCH_AIRKISS
第一個是smartconfig配網(手機APP),第二個是airkiss配網(微信公眾號),最后一個兩者都可以。進入該函數會調用smartconfig_start();,該函數會調用smartconfig_done()函數進行配網,配網成功后會點亮LED燈。
網絡連接成功以后可以開始MQTT的初始化,初始化包涵一系列的連接初始化回調,連接成功或不成功回調,主題訂閱發布回調等等。
當模塊的WiFi和MQTT服務器都連接上之后,模塊就開始監聽串口和服務器的數據,如果串口有數據過來便轉發到服務器或者進行OTA升級,如果服務器有指令下發就轉發給串口。
第一個是smartconfig配網(手機APP),第二個是airkiss配網(微信公眾號),最后一個兩者都可以。進入該函數會調用smartconfig_start();,該函數會調用smartconfig_done()函數進行配網,配網成功后會點亮LED燈。
/*** Smartconfig 狀態處理* @param status: 狀態* @param *pdata: AP數據* @retval None*/void ICACHE_FLASH_ATTRsmartconfig_done(sc_status status, void *pdata) {switch (status) {case SC_STATUS_WAIT:INFO("SC_STATUS_WAIT ");break;case SC_STATUS_FIND_CHANNEL:INFO("SC_STATUS_FIND_CHANNEL ");break;case SC_STATUS_GETTING_SSID_PSWD:INFO("SC_STATUS_GETTING_SSID_PSWD ");sc_type *type = pdata;if (*type == SC_TYPE_ESPTOUCH) {INFO("SC_TYPE:SC_TYPE_ESPTOUCH ");} else {INFO("SC_TYPE:SC_TYPE_AIRKISS ");}break;case SC_STATUS_LINK:INFO("SC_STATUS_LINK ");sm_comfig_status = SM_STATUS_GETINFO;struct station_config *sta_conf = pdata;wifi_station_set_config(sta_conf);wifi_station_disconnect();wifi_station_connect();break;case SC_STATUS_LINK_OVER:sm_comfig_status = SM_STATUS_FINISH;INFO("SC_STATUS_LINK_OVER ");if (pdata != NULL) {//SC_TYPE_ESPTOUCHuint8 phone_ip[4] = { 0 };os_memcpy(phone_ip, (uint8*) pdata, 4);INFO("Phone ip: %d.%d.%d.%d ", phone_ip[0], phone_ip[1],phone_ip[2], phone_ip[3]);} else {//SC_TYPE_AIRKISS - support airkiss v2.0airkiss_start_discover();}smartconfig_stop();smartconfig_flag = 0;connect_flag = 0;os_timer_disarm(&OS_Timer_SM); // 關閉定時器finish_cd(sm_comfig_status);os_timer_arm(&OS_Timer_Wifichange, 3000, 1); // 使能定時器break;}}/*** WIFI連接回調*/void wifi_connect_cb(void){INFO("wifi connect! ");os_printf("----- WiFi連接成功,打開綠燈--- ");GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);MQTT_Connect(&mqttClient);}/*** WIFI斷開回調*/void wifi_disconnect_cb(void){INFO("wifi disconnect! ");os_printf("----- WiFi斷開,關閉綠燈--- ");GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);MQTT_Disconnect(&mqttClient);}
連接MQTT服務器:
網絡連接成功以后可以開始MQTT的初始化,初始化包涵一系列的連接初始化回調,連接成功或不成功回調,主題訂閱發布回調等等。
/*** MQTT初始化*/void ICACHE_FLASH_ATTR mqtt_init(void) {MQTT_InitConnection(&mqttClient, MQTT_HOST, MQTT_PORT, DEFAULT_SECURITY);MQTT_InitClient(&mqttClient, mac_str, MQTT_USER,MQTT_PASS, MQTT_KEEPALIVE, 1);MQTT_InitLWT(&mqttClient, lwt_topic, LWT_MESSAGE, 0, 0);MQTT_OnConnected(&mqttClient, mqttConnectedCb);MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);MQTT_OnPublished(&mqttClient, mqttPublishedCb);MQTT_OnData(&mqttClient, mqttDataCb);}void ICACHE_FLASH_ATTRMQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security){uint32_t temp;INFO("MQTT_InitConnection ");os_memset(mqttClient, 0, sizeof(MQTT_Client));temp = os_strlen(host);mqttClient->host = (uint8_t*)os_zalloc(temp + 1);os_strcpy(mqttClient->host, host);mqttClient->host[temp] = 0;mqttClient->port = port;mqttClient->security = security;}void ICACHE_FLASH_ATTRMQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession){uint32_t temp;INFO("MQTT_InitClient ");os_printf("CD MQTT_InitClient++++++++++++++++++++++ ");os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t));temp = os_strlen(client_id);mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1);os_strcpy(mqttClient->connect_info.client_id, client_id);mqttClient->connect_info.client_id[temp] = 0;if (client_user){temp = os_strlen(client_user);mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1);os_strcpy(mqttClient->connect_info.username, client_user);mqttClient->connect_info.username[temp] = 0;}if (client_pass){temp = os_strlen(client_pass);mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1);os_strcpy(mqttClient->connect_info.password, client_pass);mqttClient->connect_info.password[temp] = 0;}mqttClient->connect_info.keepalive = keepAliveTime;mqttClient->connect_info.clean_session = cleanSession;mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE);mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE;mqttClient->mqtt_state.out_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE);mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE;mqttClient->mqtt_state.connect_info = &mqttClient->connect_info;mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length);QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE);system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE);system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient);}
WiFi連接成功和失敗會觸發不同的回調函數:
串口透傳:/*** MQTT連接回調*/void mqttConnectedCb(uint32_t *args) {MQTT_Client* client = (MQTT_Client*) args;INFO("MQTT: Connected ");MQTT_Publish(client, birth_topic, BIRTH_MESSAGE, os_strlen(BIRTH_MESSAGE), 0,0);MQTT_Subscribe(client,ota_topic, 0);if(updata_status_check()){MQTT_Publish(client, ota_topic, "updata_finish", os_strlen("updata_finish"), 0,0);}}/*** MQTT斷開連接回調*/void mqttDisconnectedCb(uint32_t *args) {MQTT_Client* client = (MQTT_Client*) args;INFO("MQTT: Disconnected ");}/*** MQTT發布消息回調*/void mqttPublishedCb(uint32_t *args) {MQTT_Client* client = (MQTT_Client*) args;INFO("MQTT: Published ");}
當模塊的WiFi和MQTT服務器都連接上之后,模塊就開始監聽串口和服務器的數據,如果串口有數據過來便轉發到服務器或者進行OTA升級,如果服務器有指令下發就轉發給串口。
其他問題:連接的服務器地址,端口號等信息需要寫在代碼里燒錄進模塊,這些信息在在mqtt_config.h文件中定義。/*** MQTT接收數據回調(用于OTA升級和串口透傳)*/void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len,const char *data, uint32_t data_len) {char *topicBuf = (char*) os_zalloc(topic_len + 1), *dataBuf =(char*) os_zalloc(data_len + 1);uint8 *pdata = (uint8*)data;uint16 len = data_len;uart0_tx_buffer(pdata, len);//串口輸出MQTT_Client* client = (MQTT_Client*) args;os_memcpy(topicBuf, topic, topic_len);topicBuf[topic_len] = 0;os_memcpy(dataBuf, data, data_len);dataBuf[data_len] = 0;// INFO("Receive topic: %s, data: %s ", topicBuf, dataBuf);//data = {"url"="http://yourdomain.com:9001/ota/"}if (os_strcmp(topicBuf, ota_topic) == 0) {char url_data[200];if(get_josn_str(dataBuf,"url",url_data)){// INFO("ota_start ");ota_upgrade(url_data,ota_finished_callback);}}os_free(topicBuf);os_free(dataBuf);}/*** ota升級回調*/void ICACHE_FLASH_ATTR ota_finished_callback(void * arg) {struct upgrade_server_info *update = arg;if (update->upgrade_flag == true) {INFO("OTA Success ! rebooting! ");system_upgrade_reboot();} else {INFO("OTA Failed! ");}}

上電后可以在串口助手看到打印的MAC地址:

按下配網按鍵(GPIO14接地),進入配網模式,使用APP或者微信公眾號將信息發給模塊便可聯網,聯網后自動連接MQTT服務器。


至此連接完成,后續只需要串口發數據給模塊,便可在服務器收到信息,服務器下發指令,單片機串口也可以接收到數據。但是要記得訂閱主題哦。該透傳代碼燒錄完成可搭配任意MCU的串口使用。非常便捷。由于項目期較遠,可能介紹的不是很詳細,需要的大大們可以點擊閱讀原文回帖獲取源碼。自行查看。
責任編輯:xj
原文標題:什么?單片機還在裸奔?ESP8266純串口透傳,助力設備上云端
文章出處:【微信公眾號:嵌入式ARM】歡迎添加關注!文章轉載請注明出處。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
單片機
+關注
關注
6076文章
45500瀏覽量
670725 -
云端
+關注
關注
0文章
126瀏覽量
17582 -
ESP8266
+關注
關注
51文章
970瀏覽量
49528
原文標題:什么?單片機還在裸奔?ESP8266純串口透傳,助力設備上云端
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
熱點推薦
【ESP8266系列】WT8266-S3模組規格書
概述ESP-07S(WT8266-S3)Wi-Fi模塊是由啟明云端科技開發的、低功耗高性價比的嵌入式無線網絡控制模塊。可滿足智能電網、樓宇自動化、安防、智能家居、遠程醫療等物聯網應用的需求。該模塊
【ESP8266系列】WT8266-S5模組規格書
概述ESP-12F(WT8266-S5)WiFi模塊是由啟明云端科技開發的、低功耗高性價比的嵌入式無線網絡控制模塊。可滿足智能電網、樓宇自動化、安防、智能家居、遠程醫療等物聯網應用的需求。該模塊核心
【ESP8266系列】WT8266-S6模組規格書
ESP-12S(WT8266-S6)Wi-Fi模塊是由啟明云端科技開發的、低功耗高性價比的嵌入式無線網絡控制模塊。可滿足智能電網、樓宇自動化、安防、智能家居、遠程醫療等物聯網應用的需求。該模塊核心
【ESP8266系列】WT8266-S1模組產品介紹
WT8266-S1WiFi模塊是由啟明云端科技開發的、低功耗高性價比的嵌入式無線網絡控制模塊。可滿足智能電網、樓宇自動化、安防、智能家居、遠程醫療等物聯網應用的需求。該模塊核心處理器ESP8266在
【ESP8266系列】WT8266-S6模組產品介紹
ESP-12S(WT8266-S6)Wi-Fi模塊是由啟明云端科技開發的、低功耗高性價比的嵌入式無線網絡控制模塊。可滿足智能電網、樓宇自動化、安防、智能家居、遠程醫療等物聯網應用的需求。該模塊核心
無需安裝!在瀏覽器里就能玩轉ESP32/ESP8266,這個神器絕了!
無需安裝!在瀏覽器里就能玩轉ESP32/ESP8266,這個神器絕了!【往期精選】十年嵌入式最深的痛,不是Bug,而是抓不到日志!vivo宣布原生支持HomeAssistant生態設備接入(含
【瑞薩RA6E2地奇星開發板試用】基于RA6E2+ESP8266在STA模式下數據透傳到Python服務器整體系統演示總結
基于RA6E2+ESP8266在STA模式下數據透傳到Python服務器整體系統演示總結
1. 需求描述
1.1. 系統實現概述
使用RA6E2驅動 esp8266 WiFi模塊,
用串口
發表于 12-28 20:16
晶科鑫 | 國產26MHz晶振匹配Espressif(樂鑫) ESP8285/ESP8266芯片案例
【應用】國產26MHz頻率晶振應用于物聯網WIFI物聯網模塊(串口轉WiFi模塊),Espressif(樂鑫)ESP8285/ESP8266芯片匹配測試OKESP8285其實是ESP8266
ESP8266和ESP32開發板常見的2種下載方式
ESP32和ESP8266是性價比很高而且使用較為廣泛的的Wi-Fi模塊,在物聯網(IoT)領域的DIY項目中可以首先考慮這2款產品。
兩款芯片都屬于32位處理器。ESP32是低功耗雙核80MHz
ESP8266和ESP32開發板常見的2種下載方式
協議,完整的 TCP/IP 協議棧以及藍牙協議棧。用戶可以使用這兩款模塊為現有的設備添加WIFI聯網功能或藍牙(ESP32),輕松的構建獨立的網絡控制器和遠程控制監控設備。
ESP8266
發表于 10-24 18:04
【ESP8266】進入透傳模式后,數據間隔怎么調整,
01.TCP客戶端用ESP8266透傳模式發送數據是10ms發送一次,(連續發送)
02.TCP服務器接收到的數據是200ms左右接收一次,數據未丟失,但是更新不及時;
03.通過TCP調試助手已
發表于 09-15 10:16
ESP8266燒錄與機智云一鍵配網教程
ESP8266模塊因其低成本和高性能,廣泛應用于智能家居和工業自動化等領域。機智云平臺提供了一鍵配網功能,簡化了設備的聯網過程。本教程將詳細介紹如何使用ESP8266進行燒錄,并通過機智云實現一鍵配
【RA-Eco-RA4M2開發板評測】RA4M2 + ESP8266獲取城市天氣預報(二)使用串口助手獲取天氣+破解任意類型AT指令
:就是用串口來進行透傳,把串口助手上發送的AT指令通過調試串口接收來發送給ESP8266模塊的
發表于 05-04 10:07
ESP8266純串口透傳,助力設備上云端
評論