91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于睿擎派的工業(yè)FOC無刷電機(jī)控制系統(tǒng)與WEB推流監(jiān)看系統(tǒng)| 技術(shù)集結(jié)

RT-Thread官方賬號(hào) ? 2025-11-26 18:25 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

項(xiàng)目背景及功能


在小型自動(dòng)化調(diào)試或簡易設(shè)備控制場景中,無刷電機(jī)的速度調(diào)控與運(yùn)行狀態(tài)監(jiān)看存在明顯不便:傳統(tǒng)方案下,電機(jī)轉(zhuǎn)速調(diào)節(jié)需依賴現(xiàn)場專用工具連接調(diào)試,無法遠(yuǎn)程操作;設(shè)備運(yùn)行畫面、電機(jī)工作狀態(tài)的查看也需人員到場,導(dǎo)致運(yùn)維效率較低。睿擎派嵌入式開發(fā)板具備串口外設(shè)接口與網(wǎng)絡(luò)傳輸能力,可同時(shí)承載控制與監(jiān)看需求,因此本項(xiàng)目基于該硬件展開開發(fā)。項(xiàng)目通過串口實(shí)現(xiàn)電機(jī)速度環(huán)控制,精準(zhǔn)調(diào)節(jié)轉(zhuǎn)速;同時(shí)集成視頻推流功能,將電機(jī)運(yùn)行畫面或設(shè)備現(xiàn)場視頻遠(yuǎn)程傳輸,實(shí)現(xiàn)狀態(tài)的實(shí)時(shí)遠(yuǎn)程監(jiān)看。該方案有效解決了傳統(tǒng)方式中現(xiàn)場調(diào)試繁瑣和遠(yuǎn)程監(jiān)看缺失的問題,適配了此類輕量場景下的實(shí)際需求。


RTT使用情況


本項(xiàng)目基于 RT-Thread開發(fā),充分依托 RTT 嵌入式操作系統(tǒng)的多線程調(diào)度、設(shè)備驅(qū)動(dòng)框架、FinSH 調(diào)試終端、WebNet 組件四大核心能力,實(shí)現(xiàn)了 FOC 電機(jī)控制與 WEB 視頻推流的高效集成,大幅簡化開發(fā)流程并提升系統(tǒng)穩(wěn)定性。


3b57f18e-cab2-11f0-8ce9-92fbcf53809c.png


1、UART 串口(電機(jī)控制)依托 RTT 的串口設(shè)備驅(qū)動(dòng),通過rt_device_find(“uart3”)查找電機(jī)連接的 UART3 設(shè)備,rt_device_open(serial, RT_DEVICE_FLAG_RDWR)打開設(shè)備并配置為 “讀寫模式”;后續(xù)通過rt_device_write()發(fā)送電機(jī)控制指令(含 CRC 校驗(yàn)),rt_device_read()丟棄電機(jī)響應(yīng)數(shù)據(jù),全程無需操作寄存器,適配效率提升 80%。

2、UVC 攝像頭(視頻推流)項(xiàng)目中 UVC 攝像頭通過 RTT 的usbh_uvc驅(qū)動(dòng)適配,直接調(diào)用rt_device_find(“uvc”)獲取設(shè)備句柄,rt_device_control()設(shè)置視頻幀回調(diào)函數(shù)(video_frame_callback),實(shí)現(xiàn) “攝像頭采集→幀數(shù)據(jù)回調(diào)→WEB 推流” 的端到端流程,底層 USB 枚舉、數(shù)據(jù)傳輸?shù)冗壿嬐耆?RTT 驅(qū)動(dòng)封裝,開發(fā)者僅需關(guān)注應(yīng)用層數(shù)據(jù)處理。

3、網(wǎng)絡(luò)設(shè)備(WEB 服務(wù))無需手動(dòng)配置網(wǎng)卡,RTT 通過sal(套接字抽象層)自動(dòng)適配以太網(wǎng) / 無線網(wǎng)卡,WebNet 組件直接基于lwIP協(xié)議棧創(chuàng)建 TCP 監(jiān)聽(80 端口),通過webnet_start()一鍵啟動(dòng) WEB 服務(wù),簡化網(wǎng)絡(luò)編程復(fù)雜度。


項(xiàng)目的 WEB 視頻推流功能完全基于 RTT 官方webnet組件實(shí)現(xiàn),無需從零開發(fā) HTTP 服務(wù):


1、WEB 服務(wù)啟動(dòng):通過webnet_start(80, “/webroot”)啟動(dòng) 80 端口 WEB 服務(wù),指定網(wǎng)頁資源根目錄為/webroot(FTP 上傳的 HTML 頁面存于此目錄);

2、視頻推流 CGI 注冊:通過webnet_cgi_register(“mjpeg_stream”, cgi_mjpeg_stream_handler)注冊推流接口,當(dāng)瀏覽器訪問mjpeg_stream時(shí),自動(dòng)觸發(fā)cgi_mjpeg_stream_handler回調(diào);

3、流數(shù)據(jù)傳輸:在回調(diào)函數(shù)中,通過webnet_session_printf()設(shè)置 HTTP 響應(yīng)頭(multipart/x-mixed-replace格式),webnet_session_write()發(fā)送 JPEG 視頻幀,實(shí)現(xiàn) “一幀一響應(yīng)” 的 MJPEG 推流,瀏覽器無需插件即可實(shí)時(shí)播放。



技術(shù)路徑


開箱上手

首先是到手的開箱,有一個(gè)電源和一個(gè)主板,經(jīng)過驗(yàn)證,便宜的DAP-Link無法使用,因此該DAP-Link用作串口調(diào)試,燒錄就使用USB進(jìn)行下載。


3b6c4b34-cab2-11f0-8ce9-92fbcf53809c.png


接著安裝RTT的工業(yè)開發(fā)平臺(tái),沒有什么需要注意的,直接一直下一步就好了。

3b847cd6-cab2-11f0-8ce9-92fbcf53809c.png


新建項(xiàng)目就好了,但是要注意jtag和daplink的區(qū)分即可,接著就使用RKtool刷一下系統(tǒng)升級(jí),這個(gè)太簡單了,就跳過。然后使用moba就可以進(jìn)入系統(tǒng)了。

3b918e3a-cab2-11f0-8ce9-92fbcf53809c.png


這個(gè)就是我們的RTT操作系統(tǒng)了,很容易上手。接著,輸入一下。

help

就可以看到所有支持的指令了。

3ba2f92c-cab2-11f0-8ce9-92fbcf53809c.png


接著把RTT的歷程燒寫進(jìn)去,體驗(yàn)一下多線程的系統(tǒng)效果。

3bb4cf30-cab2-11f0-8ce9-92fbcf53809c.png


可以看到打印了預(yù)期的結(jié)果。


開發(fā)過程

先去建立一個(gè)空的工程,我們先測試一下串口的功能,下面給出串口控制的代碼。

/*** RT-Thread RuiChing** COPYRIGHT (C) 2024-2025 Shanghai Real-Thread Electronic Technology Co., Ltd.* All rights reserved.** The license and distribution terms for this file may be* found in the file LICENSE in this distribution.*/#include#include#defineUART_NAME"uart3"staticrt_device_tserial;staticcharrx_buffer[64];staticrt_size_trx_len =0;staticrt_err_tuart_rx_ind(rt_device_tdev,rt_size_tsize){ charch; while(rt_device_read(dev,0, &ch,1) ==1) { if(rx_len

就是一個(gè)簡單的數(shù)據(jù)發(fā)送與接受,測試ok后進(jìn)入下一個(gè)階段,進(jìn)行FOC的開發(fā)。


首先,介紹一下次使用的電機(jī):本末科技的m0603a

M0603A電機(jī)具有靜音、結(jié)構(gòu)緊湊、安裝簡便、運(yùn)行穩(wěn)定等特點(diǎn),采用雙驅(qū)動(dòng)輪設(shè)計(jì)提升智能操控體驗(yàn),已成功應(yīng)用于追覓智能洗地機(jī)等產(chǎn)品,并成為家用機(jī)器人、AGV、驅(qū)動(dòng)輪等領(lǐng)域的首選動(dòng)力方案。


其次,給出我的硬件接線結(jié)構(gòu)整體圖:

3bc2570e-cab2-11f0-8ce9-92fbcf53809c.png


接著我們看一下電機(jī)的控制參數(shù):

3bd572b2-cab2-11f0-8ce9-92fbcf53809c.png


可看到是LIN轉(zhuǎn)到UART,38400的速度,接著我們來看協(xié)議

3be9688a-cab2-11f0-8ce9-92fbcf53809c.png3bf9c70c-cab2-11f0-8ce9-92fbcf53809c.png


使用10幀格式和crc8的末尾校驗(yàn)格式,為此我們可以在RT中進(jìn)行編程CRC生成代碼。

staticrt_err_tmotor_send_speed(int16_tspeed){ // 若未初始化,先執(zhí)行初始化 if(motor_inited == RT_FALSE) { if(motor_init() != RT_EOK) { returnRT_ERROR; } } // 構(gòu)造速度控制指令(對齊CH55x的mot_control_data) speed = speed *10; uint8_tcmd_speed[9] = { MOTOR_ADDR, // 第1字節(jié):設(shè)備地址 CMD_SPEED_CTRL, // 第2字節(jié):速度指令碼(0x64) (speed >>8) &0xFF, // 第3字節(jié):速度高8位 speed &0xFF, // 第4字節(jié):速度低8位 0x00,0x00,0x00,0x00,0x00 // 保留字節(jié) }; // 發(fā)送速度指令(復(fù)用通用指令發(fā)送函數(shù)) if(motor_send_cmd(cmd_speed) == RT_EOK) { rt_kprintf("當(dāng)前速度:%d\n", speed); returnRT_EOK; } returnRT_ERROR;}


接著就是電機(jī)初始化系統(tǒng)指令控制的代碼:


// 功能:執(zhí)行CH55x中的初始化流程:發(fā)送使能指令 → 延時(shí) → 發(fā)送速度模式指令staticrt_err_t motor_init(void){ if(motor_inited==RT_TRUE) { rt_kprintf("電機(jī)已初始化,無需重復(fù)執(zhí)行!\n"); returnRT_EOK; } // 1. 構(gòu)造“電機(jī)使能指令”(對齊CH55x的enable數(shù)組:0x01,0xA0,0x08,...) uint8_t cmd_enable[9]={ MOTOR_ADDR, // 第1字節(jié):設(shè)備地址 CMD_ENABLE, // 第2字節(jié):控制指令碼(0xA0) SUB_CMD_ENABLE,// 第3字節(jié):子指令(使能:0x08) 0x00,0x00, // 第4-5字節(jié):保留 0x00,0x00, // 第6-7字節(jié):保留 0x00,0x00 // 第8-9字節(jié):保留 }; // 發(fā)送使能指令 if(motor_send_cmd(cmd_enable)!=RT_EOK) { rt_kprintf("電機(jī)使能失??!\n"); returnRT_ERROR; } rt_kprintf("電機(jī)使能成功!\n"); rt_thread_mdelay(INIT_DELAY); // 延時(shí)500ms(與CH55x一致,等待使能完成) // 2. 構(gòu)造“速度模式指令”(對齊CH55x的position_mode數(shù)組:0x01,0xA0,0x02,...) uint8_t cmd_speed_mode[9]={ MOTOR_ADDR, // 第1字節(jié):設(shè)備地址 CMD_ENABLE, // 第2字節(jié):控制指令碼(0xA0) SUB_CMD_SPEED_MODE,// 第3字節(jié):子指令(速度模式:0x02) 0x00,0x00, // 第4-5字節(jié):保留 0x00,0x00, // 第6-7字節(jié):保留 0x00,0x00 // 第8-9字節(jié):保留 }; // 發(fā)送速度模式指令 if(motor_send_cmd(cmd_speed_mode)!=RT_EOK) { rt_kprintf("切換速度模式失敗!\n"); returnRT_ERROR; } rt_kprintf("已切換到速度模式!\n"); rt_thread_mdelay(10); // 短延時(shí),確保模式生效 // 3. 初始化標(biāo)志置位(避免重復(fù)執(zhí)行) motor_inited=RT_TRUE; current_speed=0; // 初始化速度為0 returnRT_EOK;}

然后針對電機(jī)特性,創(chuàng)建一個(gè)DEMO線程

staticrt_err_tmotor_send_speed(int16_tspeed){ // 若未初始化,先執(zhí)行初始化 if(motor_inited == RT_FALSE) { if(motor_init() != RT_EOK) { returnRT_ERROR; } } // 構(gòu)造速度控制指令(對齊CH55x的mot_control_data) speed = speed *10; uint8_tcmd_speed[9] = { MOTOR_ADDR, // 第1字節(jié):設(shè)備地址 CMD_SPEED_CTRL, // 第2字節(jié):速度指令碼(0x64) (speed >>8) &0xFF, // 第3字節(jié):速度高8位 speed &0xFF, // 第4字節(jié):速度低8位 0x00,0x00,0x00,0x00,0x00 // 保留字節(jié) }; // 發(fā)送速度指令(復(fù)用通用指令發(fā)送函數(shù)) if(motor_send_cmd(cmd_speed) == RT_EOK) { rt_kprintf("當(dāng)前速度:%d\n", speed); returnRT_EOK; } returnRT_ERROR;}

這樣我們的電機(jī)就成功驅(qū)動(dòng)了,速度環(huán)控制成功。

3c0959f6-cab2-11f0-8ce9-92fbcf53809c.png


電機(jī)控制的完整代碼:

#include#include// -------------------------- 1. 硬件與協(xié)議配置(完全對齊CH55x代碼)--------------------------#defineMOTOR_UART_NAME "uart3" // 電機(jī)UART設(shè)備名#defineMOTOR_ADDR 0x01 // 電機(jī)從機(jī)地址(與CH55x一致:0x01)// 電機(jī)協(xié)議指令(從CH55x代碼提取)#defineCMD_ENABLE 0xA0 // 使能/模式控制指令碼(CH55x中0xA0)#defineSUB_CMD_ENABLE 0x08 // 子指令:電機(jī)使能(CH55x中0x08)#defineSUB_CMD_SPEED_MODE 0x02 // 子指令:速度模式(CH55x中0x02,對應(yīng)sel_2_mode=1)#defineCMD_SPEED_CTRL 0x64 // 速度控制指令碼(原代碼不變)// 速度參數(shù)#defineSPEED_STEP 5 // 速度變化步長#defineSPEED_DELAY 100 // 速度變化間隔(ms)#defineINIT_DELAY 500 // 初始化指令間隔(ms,與CH55x一致)// -------------------------- 2. 全局變量 --------------------------staticrt_device_tmotor_uart = RT_NULL; // 電機(jī)UART句柄staticint16_tcurrent_speed =0; // 當(dāng)前速度(-100~100)staticuint8_tspeed_dir =1; // 速度方向:1=0→100,2=100→-100,3=-100→100staticrt_bool_tmotor_inited = RT_FALSE;// 電機(jī)初始化標(biāo)志(避免重復(fù)初始化)// -------------------------- 3. 基礎(chǔ)工具函數(shù)(位反轉(zhuǎn)+CRC8,原代碼不變)--------------------------staticuint8_treverse_bits(uint8_tbyte){ uint8_treversed =0; for(uint8_ti =0; i >=1; } returnreversed;}staticuint8_tcrc8_maxim(constuint8_t* data,size_tlen){ uint8_tcrc =0x00; constuint8_tpoly =0x31; for(size_ti =0; i < len; i++)? ? {? ? ? ? uint8_t?reversed_byte =?reverse_bits(data[i]);? ? ? ? crc ^= reversed_byte;? ? ? ? for?(uint8_t?j =?0; j >8) &0xFF, // 第3字節(jié):速度高8位 speed &0xFF, // 第4字節(jié):速度低8位 0x00,0x00,0x00,0x00,0x00 // 保留字節(jié) }; // 發(fā)送速度指令(復(fù)用通用指令發(fā)送函數(shù)) if(motor_send_cmd(cmd_speed) == RT_EOK) { rt_kprintf("當(dāng)前速度:%d\n", speed); returnRT_EOK; } returnRT_ERROR;}// -------------------------- 7. 速度循環(huán)線程(原邏輯不變,新增初始化檢查)--------------------------staticvoidspeed_loop_thread(void*parameter){ // 線程啟動(dòng)時(shí)先檢查初始化(雙重保障) if(motor_inited == RT_FALSE) { if(motor_init() != RT_EOK) { rt_kprintf("線程啟動(dòng)失?。弘姍C(jī)初始化失??!\n"); return; // 初始化失敗,線程退出 } } while(1) { // 速度方向邏輯(原代碼不變) switch(speed_dir) { case1: // 0→100(遞增) current_speed += SPEED_STEP; if(current_speed >=100) { current_speed =100; speed_dir =2; } break; case2: // 100→-100(遞減) current_speed -= SPEED_STEP; if(current_speed <=?-100)? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? current_speed =?-100;? ? ? ? ? ? ? ? ? ? speed_dir =?3;? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? break;? ? ? ? ? ? case?3: ?// -100→100(遞增)? ? ? ? ? ? ? ? current_speed += SPEED_STEP;? ? ? ? ? ? ? ? if?(current_speed >=100) { current_speed =100; speed_dir =2; } break; default: speed_dir =1; current_speed =0; break; } // 發(fā)送速度(此時(shí)電機(jī)已初始化完成) motor_send_speed(current_speed); rt_thread_mdelay(SPEED_DELAY); }}// -------------------------- 8. 主初始化函數(shù)(UART配置+線程創(chuàng)建)--------------------------staticintmotor_speed_loop_init(void){ // 1. 配置電機(jī)UART(原邏輯不變) motor_uart =rt_device_find(MOTOR_UART_NAME); if(motor_uart == RT_NULL) { rt_kprintf("未找到UART設(shè)備:%s\n", MOTOR_UART_NAME); returnRT_ERROR; } // 打開UART(讀+寫:需讀取電機(jī)響應(yīng)并丟棄,所以用RDWR模式) if(rt_device_open(motor_uart, RT_DEVICE_FLAG_RDWR) != RT_EOK) { rt_kprintf("打開UART失?。?s\n", MOTOR_UART_NAME); returnRT_ERROR; } // 配置UART參數(shù)(波特率38400,8N1,與CH55x一致) structserial_configureconfig = RT_SERIAL_CONFIG_DEFAULT; config.baud_rate = BAUD_RATE_38400; config.data_bits = DATA_BITS_8; config.stop_bits = STOP_BITS_1; config.parity = PARITY_NONE; rt_device_control(motor_uart, RT_DEVICE_CTRL_CONFIG, &config); // 2. 先執(zhí)行電機(jī)初始化(使能+速度模式) if(motor_init() != RT_EOK) { rt_kprintf("電機(jī)初始化失敗,無法啟動(dòng)線程!\n"); rt_device_close(motor_uart); // 初始化失敗,關(guān)閉UART returnRT_ERROR; } // 3. 創(chuàng)建并啟動(dòng)速度循環(huán)線程 rt_thread_ttid =rt_thread_create( "speed_loop", speed_loop_thread, RT_NULL, 4096, 25, 10 ); if(tid != RT_NULL) { rt_thread_startup(tid); rt_kprintf("電機(jī)速度環(huán)線程啟動(dòng)成功!\n"); } else { rt_kprintf("線程創(chuàng)建失??!\n"); returnRT_ERROR; } returnRT_EOK;}// -------------------------- 9. 導(dǎo)出Msh命令(啟動(dòng)+停止)--------------------------MSH_CMD_EXPORT(motor_speed_loop_init, 啟動(dòng)電機(jī)速度環(huán)(含初始化+速度模式切換));// 新增:一鍵停止(發(fā)送0速度+刪除線程)staticintmotor_speed_loop_stop(void){ // 1. 發(fā)送0速度停電機(jī) if(motor_uart != RT_NULL && motor_inited == RT_TRUE) { motor_send_speed(0); rt_kprintf("電機(jī)已停轉(zhuǎn)(速度0)\n"); } // 2. 查找并刪除速度環(huán)線程 rt_thread_ttid =rt_thread_find("speed_loop"); if(tid != RT_NULL) { rt_thread_delete(tid); rt_kprintf("速度環(huán)線程已刪除\n"); } // 3. 重置狀態(tài)(下次啟動(dòng)可重新初始化) motor_inited = RT_FALSE; if(motor_uart != RT_NULL) { rt_device_close(motor_uart); motor_uart = RT_NULL; } returnRT_EOK;}MSH_CMD_EXPORT(motor_speed_loop_stop, 停止電機(jī)速度環(huán)(停電機(jī)+刪線程))


下面進(jìn)行推流的設(shè)置

3c177126-cab2-11f0-8ce9-92fbcf53809c.png


配一下ip地址,然后使用FTP傳輸web代碼到RT睿擎派上面

下面給出web代碼:

html> <2;title>RT-Thread 視頻流控制中心title>