【星曈科技】OpenMv笔记——利用OpenMV与STM32进行串口通信
利用OpenMV與STM32進(jìn)行串口通信
OpenMV端的程序
# Untitled - By: dell - 周一 7月 19 2021# Blob Detection and uart transport import sensor, image, time,pyb import ustruct from pyb import UART #import json # For color tracking to work really well you should ideally be in a very, very, # very, controlled enviroment where the lighting is constant... yellow_threshold = (25, 79, 2, 39, 26, 69) # You may need to tweak the above settings for tracking green things... # Select an area in the Framebuffer to copy the color settings. led3 = pyb.LED(3) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4. led1 = pyb.LED(1) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4. sensor.reset() # Initialize the camera sensor. sensor.set_pixformat(sensor.RGB565) # use RGB565. sensor.set_framesize(sensor.QVGA) # use QQVGA for speed. sensor.skip_frames(10) # Let new settings take affect. sensor.set_auto_whitebal(False) # turn this off. clock = time.clock() # Tracks FPS.uart = UART(3, 115200)#初始化串口號(hào)及其波特率 #**************************傳輸數(shù)據(jù)的函數(shù)************************************ def sending_data(cx,cy):global uart;#frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];#data = bytearray(frame)data = ustruct.pack("<bbhhb", #格式為倆個(gè)字符倆個(gè)短整型(2字節(jié))0x2C, #幀頭10x12, #幀頭2int(cx), # up sample by 4 #數(shù)據(jù)1int(cy), # up sample by 4 #數(shù)據(jù)20x5B)uart.write(data); #必須要傳入一字節(jié)的數(shù)組,這個(gè)函數(shù)似乎不能發(fā)送單個(gè)字節(jié),必須得一次發(fā)送多個(gè)字節(jié) #************************************************************************** while(True):img = sensor.snapshot() # Take a picture and return the image.led1.on()led3.on()#LED指示openmv正在工作blobs = img.find_blobs([yellow_threshold])#尋找符合條件的色塊if len(blobs) == 1:#如果只找到一個(gè)符合條件的色塊#print('sum :', len(blobs))img.draw_rectangle(blobs[0].rect())img.draw_cross(blobs[0].cx(), blobs[0].cy())output_str="[%d,%d]" % (blobs[0].cx(),blobs[0].cy())print('you send:',output_str)sending_data(blobs[0].cx(),blobs[0].cy())#發(fā)送色塊框的中心點(diǎn)坐標(biāo)#FH = bytearray([0x2C,0x12,blobs[0].cx(),blobs[0].cy(),0x5B])#uart.write(FH)else:print('not found!')sending_data(567,789)#如果沒有找到符合條件的色塊,那么發(fā)送一個(gè)不可能出現(xiàn)的坐標(biāo)#FH = bytearray([0x2C,0x12,0x77,0x55,0x5B])#uart.write(FH)由于我們圖像大小設(shè)置成了QVGA,所以所有可能出現(xiàn)的坐標(biāo)最大是(320,240),所以x或y最多只需要16bit,也就是兩個(gè)Bit就可以完全發(fā)送出去。
由上圖可知,格式為h,就可以表示2Bit,于是我們把數(shù)據(jù)的打包格式為h。
""bbhhb"就是要發(fā)送數(shù)據(jù)的聲明,bbhhb共5個(gè),代表發(fā)送5個(gè)數(shù)據(jù)。雖然只有5個(gè)數(shù)據(jù),卻需要發(fā)送7個(gè)字節(jié),因?yàn)?個(gè)h就占用兩個(gè)字節(jié),openmv的發(fā)送順序?yàn)?#xff1a;幀頭1>幀頭2>數(shù)據(jù)1的低八位>數(shù)據(jù)1的高八位>數(shù)據(jù)2的低八位>數(shù)據(jù)2的高八位。0x2c為數(shù)據(jù)幀的幀頭,即檢測到數(shù)據(jù)流的開始,但是一個(gè)幀頭可能會(huì)出現(xiàn)偶然性,因此設(shè)置兩個(gè)幀頭0x2c與0x12以便在中斷中檢測是否檢測到了幀頭以便存放有用數(shù)據(jù)。0x5b為幀尾,即數(shù)據(jù)幀結(jié)束的標(biāo)志。
下面,先讓openmv與電腦通訊,通過串口調(diào)試助手看一下數(shù)據(jù)是否成功發(fā)送。
這里注意:openmv需要通過一個(gè)USB to TTL模塊才能與電腦進(jìn)行串口通信,openmv的RXD要連接模塊的TXD,openmv的TXD要連接模塊的RXD,然后再把模塊與openmv共地即可。
通訊結(jié)果:
可以看到,由于攝像頭沒有檢測到符合條件的色塊,所以sending_data(567,789),通過串口助手明顯發(fā)現(xiàn)數(shù)據(jù)傳輸成功,共有7個(gè)字節(jié)。
這樣,我已經(jīng)保證了openmv的串口發(fā)送程序是完全沒有問題的,于是將程序燒錄進(jìn)openmv。
接下來,寫一下stm32的接受程序
以下代碼引用 烏拉~~~~ 博主的 超詳細(xì)OpenMV與STM32單片機(jī)通信 (有完整版源碼) 這一篇文章里的源碼。感謝此博主的文章!!!!
// 串口中斷服務(wù)函數(shù)//USART2 全局中斷服務(wù)函數(shù) void DEBUG_USART_IRQHandler(void) {uint8_t com_data; //接收一個(gè)字節(jié)數(shù)據(jù)的臨時(shí)變量uint8_t i;static uint8_t RxCounter1=0;//數(shù)據(jù)緩沖區(qū)的索引static uint8_t RxBuffer1[10]={0};//存放數(shù)據(jù)的接收緩存區(qū)static uint8_t RxState = 0; //接收標(biāo)志位// static uint8_t RxFlag1 = 0;if( USART_GetITStatus(DEBUG_USARTx ,USART_IT_RXNE)!=RESET) //接收中斷 {USART_ClearITPendingBit(DEBUG_USARTx ,USART_IT_RXNE); //清除中斷標(biāo)志com_data = USART_ReceiveData(DEBUG_USARTx );if(RxState==0&&com_data==0x2C) //0x2c幀頭{RxState=1;RxBuffer1[RxCounter1++]=com_data;//RxBuffer1[0]==0x2c RxCounter1==1}else if(RxState==1&&com_data==0x12) //0x12幀頭{RxState=2;RxBuffer1[RxCounter1++]=com_data;RxBuffer1[0]==0x12 RxCounter1==2}else if(RxState==2)//開始接收有效數(shù)據(jù){RxBuffer1[RxCounter1++]=com_data;//全部接收完,RxCounter1==7if(RxCounter1>=10||com_data == 0x5B) //RxBuffer1接受滿了,接收數(shù)據(jù)結(jié)束{RxState=3; // RxFlag1=1;Cx=(RxBuffer1[RxCounter1-4]<<8)+(RxBuffer1[RxCounter1-5]);//RxBuffer1[2]是openmv發(fā)送的第一個(gè)數(shù)據(jù)的低八位,RxBuffer1[3]是openmv發(fā)送的第一個(gè)數(shù)據(jù)的高八位Cy=(RxBuffer1[RxCounter1-2]<<8)+(RxBuffer1[RxCounter1-3]);RxBuffer1[4]是openmv發(fā)送的第二個(gè)數(shù)據(jù)的低八位,RxBuffer1[5]是openmv發(fā)送的第二個(gè)數(shù)據(jù)的高八位}}else if(RxState==3) //檢測是否接受到結(jié)束標(biāo)志{if(RxBuffer1[RxCounter1-1] == 0x5B){USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,DISABLE);//關(guān)閉DTSABLE中斷 // if(RxFlag1) // { // OLED_ShowNum(0,0,Cx,3,1,2);OLED_ShowNum(0,2,Cy,3,1,2);// } // RxFlag1 = 0;RxCounter1 = 0;RxState = 0;USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,ENABLE);}else //接收錯(cuò)誤{RxState = 0;RxCounter1=0;for(i=0;i<10;i++){RxBuffer1[i]=0xff; //將存放數(shù)據(jù)數(shù)組清零}}} else //接收異常{RxState = 0;RxCounter1=0;for(i=0;i<10;i++){RxBuffer1[i]=0xff; //將存放數(shù)據(jù)數(shù)組清零}}}}將openmv的TXD、RXD分別和單片機(jī)的RXD、和TXD相連,然后兩者共地,再在單片機(jī)上連接oled顯示一下收到的數(shù)據(jù),再把openmv連接電腦,通過IDE觀測其發(fā)送的數(shù)據(jù)和oled接收的是否一致。
結(jié)果:
可以看到,我成功了。
將OLED顯示的兩行代碼改進(jìn)一下:
就成了這個(gè)效果:
這里有個(gè)疑問
openmv一共發(fā)送了7個(gè)數(shù)據(jù),所以我就把RxBuffer1[10]={0};//存放數(shù)據(jù)的接收緩存區(qū)改為了RxBuffer1[7]={0};改完之后,oled就不能正常顯示數(shù)據(jù)。(下標(biāo)最小得是9)
想不出來這到底是因?yàn)槭裁?#xff1f;?????????????????
解決(最新代碼)
疑惑存在是因?yàn)槲抑桓牧薘xBuffer1的角標(biāo),而沒有改動(dòng)接收異常(else)里面for循環(huán)的i<10,這是要改成i<7的。
openmv脫機(jī)運(yùn)行
將openmv脫機(jī),用單片機(jī)的5v給他供電,其余連線保持不變:
同樣可以把openmv的結(jié)果通過串口打印到電腦
只需要在while循環(huán)里加上:
while(1){ printf("(%d,%d)",Cx,Cy);}注意
1.想要單片機(jī)與電腦通信,要另外設(shè)置特定的串口,我的開發(fā)板上單片機(jī)通過USART1和電腦通信,所以要另外設(shè)置USART1。
2.同一個(gè)串口的RXD不可以連接多個(gè)設(shè)備的TXD。比如,我的開發(fā)板的USART1如果連接到openmv的TXD,那么可能就造成程序下載不到單片機(jī),因?yàn)殡娔X的TXD也連接的是USART1的RXD。
我這個(gè)代碼的重定向是寫的USART1(DEBUG_USARTx),是不是就說明,我只要使用printf函數(shù)就是向USART1的TXR端發(fā)送數(shù)據(jù)???
總結(jié)
以上是生活随笔為你收集整理的【星曈科技】OpenMv笔记——利用OpenMV与STM32进行串口通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初学python 记录一下写的练习题
- 下一篇: TK mapper与 PageHelpe