I have been in graduate school for nearly three months. Graduate study is very different from undergraduate study. I should be good at finding information and summarizing myself. Therefore, I also decided to write a blog from now on to summarize various difficulties and solutions encountered in each period of time, so as to accumulate experience for future work and facilitate future reference.
This is my first blog. I have been working on projects about raspberry pie and opencv before. Some time ago, the teacher also gave me the idea of a new project, which should be based on visual processing. However, just after the 21 year video game, some students use openmv during the game, so I also want to try openmv to deal with this project, And meet old friends again stm32.
To get back to the point, image processing based on openmv is very simple. The official has given various libraries, which can be used if you take a good look at the examples. However, there are too few pins in openmv, so the functions that can be realized are too single. Therefore, at this time, openmv can only be used as a sensor, and most functions have to rely on stm32. Since openmv is used as a sensor, Therefore, communication between openmv and stm32 must be realized in many ways. I chose the most basic serial communication.
Although the undergraduate has also done a lot of communication between STM32 and various sensors, this time I encountered some little trouble and checked a lot of information on the Internet, but how to say, either the code given is incomplete and I don't know the connection between the top and bottom, or simply talking about STM32 serial communication is not compatible with the subject at all.
Don't talk nonsense. Summarize the code directly. (remember to connect P4 of openmv to PA10 of stm32 and P5 to PA9)
Code about openmv:
# Blob Detection and uart transport import sensor, image, time,math 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 = (65, 100, -10, 6, 24, 51) # You may need to tweak the above settings for tracking green things... # Select an area in the Framebuffer to copy the color settings. sensor.reset() # Initialize the camera sensor. sensor.set_pixformat(sensor.RGB565) # use RGB565. sensor.set_framesize(sensor.QQVGA) # 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) def find_max(blobs): max_size=0 for blob in blobs: if blob.pixels() > max_size: max_blob=blob max_size = blob.pixels() return max_blob while(True): img = sensor.snapshot() # Take a picture and return the image. blobs = img.find_blobs([yellow_threshold]) img_data=bytearray([0x2C,7,1,2,3,4,0X5B]) uart.write(img_data)
This code prototype is the official code for finding the largest color block. It is just used to simply transmit data through the serial port, so many core components are deleted. It should be noted that bytearry() is used in the last two lines, so it is necessary to import math at the beginning, in which the 0 bit is the start flag, the last bit is the end flag, and the 1 bit is the total number of digits 7, Others are data to be transmitted.
Code for stm32:
(1)usart.c
#include "sys.h" #include "usart.h" #include "openmv.h" #include "lcd.h" // //If ucos is used, include the following header file #if SYSTEM_SUPPORT_OS #include "includes.h" // ucos usage #endif // //Add the following code to support the printf function without selecting use MicroLIB #if 1 #pragma import(__use_no_semihosting) //Support functions required by the standard library struct __FILE { int handle; }; FILE __stdout; //Definition_ sys_exit() to avoid using half host mode void _sys_exit(int x) { x = x; } //Redefine fputc function int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//Cycle sending until sending is completed USART1->DR = (u8) ch; return ch; } #endif #if EN_USART1_RX / / if receive is enabled //Serial port 1 interrupt service program //Note that reading usartx - > SR can avoid inexplicable errors u8 USART_RX_BUF[USART_REC_LEN]; //Receive buffer, maximum USART_REC_LEN bytes //Receiving status //bit15, Reception completion flag //bit14, 0x0d received //bit13~0, Number of valid bytes received u16 USART_RX_STA=0; //Receive status flag //Initialize IO serial port 1 //bound: baud rate void uart_init(u32 bound){ //GPIO port settings GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //Enable GPIOA clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//Enable USART1 clock //Serial port 1 corresponding pin multiplexing mapping GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9 multiplexed to USART1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10 multiplexed to USART1 //USART1 port configuration GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9 and GPIOA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//Reuse function GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Speed 50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //Push pull multiplex output GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //Pull up GPIO_Init(GPIOA,&GPIO_InitStructure); //Initialize PA9, PA10 //USART1 initialization settings USART_InitStructure.USART_BaudRate = bound;//Baud rate setting USART_InitStructure.USART_WordLength = USART_WordLength_8b;//The word length is in 8-bit data format USART_InitStructure.USART_StopBits = USART_StopBits_1;//A stop bit USART_InitStructure.USART_Parity = USART_Parity_No;//No parity bit USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//No hardware data flow control USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //Transceiver mode USART_Init(USART1, &USART_InitStructure); //Initialize serial port 1 USART_Cmd(USART1, ENABLE); //Enable serial port 1 //USART_ClearFlag(USART1, USART_FLAG_TC); #if EN_USART1_RX USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//Turn on related interrupt //Usart1 NVIC configuration NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//Serial port 1 interrupt channel NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//Preemption priority 3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //Sub priority 3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ channel enable NVIC_Init(&NVIC_InitStructure); //Initializes the VIC register according to the specified parameters #endif } void USART1_IRQHandler(void) //Serial port 1 interrupt service program { u8 Res; #if SYSTEM_SUPPORT_OS // If system_ SUPPORT_ If OS is true, you need to support OS OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //Receive interrupt (the received data must end in 0x0D and 0x0a) { Res =USART_ReceiveData(USART1);//(USART1->DR); // Read received data Openmv_Receive_Data(Res); Openmv_Data(); if((USART_RX_STA&0x8000)==0)//Reception incomplete { if(USART_RX_STA&0x4000)//0x0d received { if(Res!=0x0a)USART_RX_STA=0;//Receive error, restart else USART_RX_STA|=0x8000; //Reception is complete } else //I haven't received 0X0D yet { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//Error receiving data, restart receiving } } } } #if SYSTEM_SUPPORT_OS // If system_ SUPPORT_ If OS is true, you need to support OS OSIntExit(); #endif } #endif
(2)usart.h
#ifndef __USART_H #define __USART_H #include "stdio.h" #include "stm32f4xx_conf.h" #include "sys.h" #define USART_REC_LEN two hundred // Define the maximum number of bytes received 200 #define EN_USART1_RX one // Enable (1) / disable (0) serial port 1 reception extern u8 USART_RX_BUF[USART_REC_LEN]; //Receive buffer, maximum USART_REC_LEN bytes. The last byte is a newline character extern u16 USART_RX_STA; //Receive status flag //If you want to interrupt reception through the serial port, please do not comment on the following macro definitions void uart_init(u32 bound); #endif
The official serial port code is used. Anyone who has used stm32 has this code, except when res = USART_ Two lines of openmv functions are added after receivedata (usart1).
(3)openmv.c
#include "openmv.h" #include "usart.h" int openmv[7];//stm32 receive data array int16_t data1; int16_t data2; int16_t data3; int16_t data4; int i=0; void Openmv_Receive_Data(int16_t data)//Receive data from Openmv { static u8 state = 0; if(state==0&&data==0x2C) { state=1; openmv[0]=data; } else if(state==1&&data==7) { state=2; openmv[1]=data; } else if(state==2) { state=3; openmv[2]=data; } else if(state==3) { state = 4; openmv[3]=data; } else if(state==4) { state = 5; openmv[4]=data; } else if(state==5) { state = 6; openmv[5]=data; } else if(state==6) //Detect whether the end flag is accepted { if(data == 0x5B) { state = 0; openmv[6]=data; Openmv_Data(); } else if(data != 0x5B) { state = 0; for(i=0;i<7;i++) { openmv[i]=0x00; } } } else { state = 0; for(i=0;i<7;i++) { openmv[i]=0x00; } } } void Openmv_Data(void) { data1=openmv[0]; data2=openmv[3]; data3=openmv[4]; data4=openmv[5]; }
(4)openmv.h
#include "sys.h" extern int openmv[7];//stm32 receive data array extern int16_t data1; extern int16_t data2; extern int16_t data3; extern int16_t data4; void Openmv_Receive_Data(int16_t data); void Openmv_Data(void);
(5)main.c
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" #include "openmv.h" int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Set system interrupt priority group 2 delay_init(168); //Initialization delay function uart_init(115200); //The baud rate of initialization serial port is 115200 LED_Init(); //Initialize LED LCD_Init(); //Initialize LCD FSMC interface POINT_COLOR=RED; //Brush color: Red while(1) { LCD_ShowNum(0,20,200,10,24); LCD_ShowNum(0,40,data1,10,24); } }
Among them, 7 in openmv[7] is the same as the total number of bits of bytearry () in openmv code.
Then download the code and you can see the results on the lcd screen (the lcd screen code is not pasted, and the official information is very detailed).