日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 嵌入式微處理器
[導(dǎo)讀]項(xiàng)目有些久遠(yuǎn),前年的機(jī)器人上需要的功能,當(dāng)時(shí)是需要將STM32上的數(shù)據(jù)上傳到服務(wù)器,比如機(jī)器人的速度,行駛距離,是否在拍照等等。


項(xiàng)目有些久遠(yuǎn),前年的機(jī)器人上需要的功能,當(dāng)時(shí)是需要將STM32上的數(shù)據(jù)上傳到服務(wù)器,比如機(jī)器人的速度,行駛距離,是否在拍照等等。便于管理者在PC或者手機(jī)上了解機(jī)器人的工作狀態(tài),同時(shí)可以遠(yuǎn)程下發(fā)指令給機(jī)器人,控制其完成相應(yīng)動(dòng)作。
因?yàn)樗械倪壿嬇袛嗪涂刂贫荚诜?wù)器或者STM32上面,作為中間的無線模塊僅僅需要上傳STM32的數(shù)據(jù)并接收服務(wù)器下發(fā)的指令即可,所以這里對WiFi模塊的要求不高,僅僅需要它作為透傳功能即可。當(dāng)時(shí)在選型的時(shí)候試過好幾款WiFi模塊,最終敲定了安信可的ESP8266,價(jià)格便宜,開發(fā)簡單,但是搭建環(huán)境是真的不容易,深受其害 。
選擇 好模塊就該考慮使用AT指令還是使用SDK開發(fā),AT指令固然簡單,但是局限性非常大。如果使用AT指令,我那開發(fā)控制端的同事估計(jì)就要跳腳了,代碼里需要寫一大堆的AT指令,如果功能改變,指令代碼就需要重寫,煩不勝煩。
如果使用SDK開發(fā),控制端只需發(fā)送簡單的數(shù)據(jù)就行,完全不用考慮其他任何東西,ESP8266完全當(dāng)做一個(gè)中轉(zhuǎn)站,相對應(yīng)的我的工作就會(huì)繁重,但是,我屈服了,選擇使用SDK。
于是就有了下面基于NONOS 2.0的ESP8266串口透傳。主要有以下幾個(gè)功能:
  • 純串口透傳,接收MCU串口數(shù)據(jù),直接通過MQTT上傳到服務(wù)器,接收服務(wù)器數(shù)據(jù)下發(fā)給MCU。
  • smartconfig+airkiss配網(wǎng),隨意使用,場景豐富。
  • 最多儲(chǔ)存5個(gè)WIFI賬號和密碼,自動(dòng)尋找網(wǎng)絡(luò)連接。
  • 按鍵配網(wǎng),長按重新配網(wǎng),前一次WiFi自動(dòng)儲(chǔ)存,添加配網(wǎng)指示燈。
  • OTA空中升級(待驗(yàn)證)

從程序的入口開始:

//程序入口
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);//低電平  g
et_mac();//獲取MAC地址  
wifi_set_opmode(STATION_MODE); //設(shè)置wifi信息存儲(chǔ)數(shù)量,最大為5個(gè) 
wifi_station_ap_number_set(2);  
mqtt_init();  
set_wifistate_cb(wifi_connect_cb, wifi_disconnect_cb);
}


程序的入口先進(jìn)行串口初始化和按鍵的初始化,以及LED的初始化。串口要初始化波特率,按鍵初始化配網(wǎng)按鍵,用于短按配網(wǎng),長按重新配網(wǎng),LED只要用于判斷模塊是否進(jìn)入配網(wǎng)模式以及是否配網(wǎng)完成。
初始化完成后會(huì)首先讀取MAC地址,該地址是唯一的,每個(gè)模塊都不一樣,用于填充進(jìn)主題中,便于服務(wù)器區(qū)分不同設(shè)備,用于多臺(tái)量產(chǎn)設(shè)備的使用,在連接MQTT服務(wù)器時(shí)會(huì)自動(dòng)填充。


每連接一次WiFi都會(huì)將WiFi信息保存在模塊內(nèi)部,每次上電都會(huì)自動(dòng)掃描暴露的WiFi,直接連接,就像手機(jī)的WIFI連接,目前最大支持五個(gè)WiFi信息的保存,超過5個(gè)會(huì)剔除最早的WiFi信息,通過短按D5(GPIO14)可進(jìn)入配網(wǎng)模式。

/*** 按鍵短按回調(diào)*/
LOCAL void ICACHE_FLASH_ATTR key1ShortPress(void) {  
start_smartconfig(smartconfig_cd); 
INFO("start_smartconfig\n");
}
/*** 按鍵長按回調(diào)*/
LOCAL void ICACHE_FLASH_ATTR key1LongPress(void) {  
start_smartconfig(smartconfig_cd); 
INFO("start_smartconfig\n");
}
/*** 按鍵初始化*/
LOCAL void ICACHE_FLASH_ATTR keyInit(void) {  
//設(shè)置按鍵數(shù)量 
set_key_num(1); 
//長按、短按的按鍵回調(diào) 
key_add(D5, NULL, key1ShortPress); 
key_add(D5, NULL, key1LongPress); 
} 
由于找不到最新的代碼。這里的長按我沒做處理,應(yīng)該是斷開WiFi重新進(jìn)入配網(wǎng)模式, 或者軟復(fù)位模塊,再進(jìn)入start_smartconfig()函數(shù):
/*** 開始Smartconfig配置 * @param cd: Smartconfig狀態(tài)回調(diào)* @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_AIRKISS 
wifi_station_disconnect(); 
wifi_set_opmode(STATION_MODE); 
finish_cd = cd; 
smartconfig_start(smartconfig_done); 
os_timer_disarm(&OS_Timer_Wifichange); 
// 關(guān)閉定時(shí)器  
if(connect_flag == 1){ 
w_disconnect(); 
connect_flag = 0; 
}  
os_timer_disarm(&OS_Timer_SM); 
// 關(guān)閉定時(shí)器 
os_timer_setfn(&OS_Timer_SM, (os_timer_func_t *) sm_wait_time, NULL);
// 設(shè)置定時(shí)器 
os_timer_arm(&OS_Timer_SM, 1000, 1); // 使能定時(shí)器
} 


smartconfig_set_type();函數(shù)可選3個(gè)參數(shù):分別是:SC_TYPE_ESPTOUCH、SC_TYPE_AIRKISS和SC_TYPE_ESPTOUCH_AIRKISS
第一個(gè)是smartconfig配網(wǎng)(手機(jī)APP),第二個(gè)是airkiss配網(wǎng)(微信公眾號),最后一個(gè)兩者都可以。進(jìn)入該函數(shù)會(huì)調(diào)用smartconfig_start();,該函數(shù)會(huì)調(diào)用smartconfig_done()函數(shù)進(jìn)行配網(wǎng),配網(wǎng)成功后會(huì)點(diǎn)亮LED燈。
/*** Smartconfig 狀態(tài)處理* @param status: 狀態(tài)* @param *pdata: AP數(shù)據(jù)* @retval None*/
void ICACHE_FLASH_ATTRsmartconfig_done(sc_status status, void *pdata) { 
switch (status) { 
case SC_STATUS_WAIT: 
INFO("SC_STATUS_WAIT\n"); 
break; 
case SC_STATUS_FIND_CHANNEL: 
INFO("SC_STATUS_FIND_CHANNEL\n"); 
break; 
case SC_STATUS_GETTING_SSID_PSWD: 
INFO("SC_STATUS_GETTING_SSID_PSWD\n"); 
sc_type *type = pdata; 
if (*type == SC_TYPE_ESPTOUCH) { 
INFO("SC_TYPE:SC_TYPE_ESPTOUCH\n"); 
} else { 
INFO("SC_TYPE:SC_TYPE_AIRKISS\n"); 
} 
break; 
case SC_STATUS_LINK: 
INFO("SC_STATUS_LINK\n"); 
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\n"); 
if (pdata != NULL) { //SC_TYPE_ESPTOUCH uint8 
phone_ip[4] = { 0 }; 
os_memcpy(phone_ip, (uint8*) pdata, 4); 
INFO("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]); 
} else { 
//SC_TYPE_AIRKISS - support airkiss v2.0 
airkiss_start_discover(); 
} 
smartconfig_stop(); 
smartconfig_flag = 0; 
connect_flag = 0; 
os_timer_disarm(&OS_Timer_SM); // 關(guān)閉定時(shí)器 
finish_cd(sm_comfig_status); 
os_timer_arm(&OS_Timer_Wifichange, 3000, 1); // 使能定時(shí)器 
break; 
} 
}
 /*** WIFI連接回調(diào)*/
void wifi_connect_cb(void){  
INFO("wifi connect!\r\n"); 
os_printf("----- WiFi連接成功,打開綠燈---\r\n"); 
GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1); 
MQTT_Connect(&mqttClient);
} 
/*** WIFI斷開回調(diào)*/
void wifi_disconnect_cb(void){ 
INFO("wifi disconnect!\r\n"); 
os_printf("----- WiFi斷開,關(guān)閉綠燈---\r\n"); 
GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0); 
MQTT_Disconnect(&mqttClient);
} 
連接MQTT服務(wù)器:

網(wǎng)絡(luò)連接成功以后可以開始MQTT的初始化,初始化包涵一系列的連接初始化回調(diào),連接成功或不成功回調(diào),主題訂閱發(fā)布回調(diào)等等。
/*** 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\r\n"); 
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\r\n"); 
os_printf("CD MQTT_InitClient++++++++++++++++++++++\n"); 
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連接成功和失敗會(huì)觸發(fā)不同的回調(diào)函數(shù):
/*** MQTT連接回調(diào)*/
void mqttConnectedCb(uint32_t *args) { 
MQTT_Client* client = (MQTT_Client*) args;  
INFO("MQTT: Connected\r\n"); 
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斷開連接回調(diào)*/
void mqttDisconnectedCb(uint32_t *args) { 
MQTT_Client* client = (MQTT_Client*) args; 
INFO("MQTT: Disconnected\r\n");
} 
/*** MQTT發(fā)布消息回調(diào)*/
void mqttPublishedCb(uint32_t *args) { 
MQTT_Client* client = (MQTT_Client*) args; 
INFO("MQTT: Published\r\n");
}

串口透傳:
當(dāng)模塊的WiFi和MQTT服務(wù)器都連接上之后,模塊就開始監(jiān)聽串口和服務(wù)器的數(shù)據(jù),如果串口有數(shù)據(jù)過來便轉(zhuǎn)發(fā)到服務(wù)器或者進(jìn)行OTA升級,如果服務(wù)器有指令下發(fā)就轉(zhuǎn)發(fā)給串口。
/*** MQTT接收數(shù)據(jù)回調(diào)(用于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 \r\n", 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\n"); 
ota_upgrade(url_data,ota_finished_callback); 
} 
}  
os_free(topicBuf); 
os_free(dataBuf);   }
/*** ota升級回調(diào)*/
void ICACHE_FLASH_ATTR ota_finished_callback(void * arg) { 
struct upgrade_server_info *update = arg; 
if (update->upgrade_flag == true) { 
INFO("OTA Success ! rebooting!\n"); 
system_upgrade_reboot(); 
} else { 
INFO("OTA Failed!\n"); 
}
}


其他問題: 連接的服務(wù)器地址,端口號等信息需要寫在代碼里燒錄進(jìn)模塊,這些信息在在mqtt_config.h文件中定義。



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


按下配網(wǎng)按鍵(GPIO14接地),進(jìn)入配網(wǎng)模式,使用APP或者微信公眾號將信息發(fā)給模塊便可聯(lián)網(wǎng),聯(lián)網(wǎng)后自動(dòng)連接MQTT服務(wù)器。


至此連接完成,后續(xù)只需要串口發(fā)數(shù)據(jù)給模塊,便可在服務(wù)器收到信息,服務(wù)器下發(fā)指令,單片機(jī)串口也可以接收到數(shù)據(jù)。但是要記得訂閱主題哦。該透傳代碼燒錄完成可搭配任意MCU的串口使用。非常便捷。由于項(xiàng)目期較遠(yuǎn),可能介紹的不是很詳細(xì),需要的大大們可以點(diǎn)擊閱讀原文回帖獲取源碼。自行查看。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉