今年19年,电赛国赛年,暑假在学校准备了一个多月吧,搞四轴飞行器,我负责视觉方面,然后学习了openmv,不幸的是,封箱前几个小时,临阵加电路,没想到电压问题把飞机搞炸了,最终遗憾弃赛,不过还是去了现场,说多了一把泪,往事如烟。
暑假在学校准备电赛的时候同时准备了另一个比赛,写了代码,那就是如题stm32f4结合openmv的循迹小车的代码,没有加PID,因为功夫不到位,只靠单纯的两侧车轮差速来实现转弯,效果可以但是不如加PID来的顺滑吧,加PID小车可以随时改变两侧车轮的PWM从而可以随时改变两侧车轮的转速,转弯过程中体现的尤为显著,加了PID的小车它可以一点点蹭着转弯看起来非常灵活,没加PID的小车占空比固定进而PWM是固定的,没有那一点灵活看起来很钝,大家自己做出来后可以对比星瞳官网的巡线小车,就知道差距了。
先说openmv方面,参照星瞳科技巡线小车的源码(打开星瞳科技官网,然后点上手教程,左侧栏目寻找项目实例就可以看到了),不过要改一点他们的代码再加上一些UART串口的代码,其中比较重要的点是,与stm32进行UART通信时最好别传输带符号的数据(负数),所以这就是星瞳科技提供的代码我们需要修改的地方:
1、平面坐标系需要旋转90度(因为如果根据它定的坐标系我们返回的line.theta()会出现负号,出现了不必要的麻烦,我们只需加上点角度就可以把line.theta()返回的值全变成正的,避免这种麻烦,何乐而不为?)
2、直接返回line.rho()的数据就好(即返回距离画面最左侧的距离),不必返回距离画面中心线的距离。还有一个重要的地方,使用openmv进行通信时,一定要使用帧头来确保数据传输正常,不要一上来就传输数据,一不好判断,二容易产生失误,所以谨记,一定使用帧头,不管多简单哪怕就几个字母,一定不要忘记。
THRESHOLD = (4, 31, -20, 49, -36, 58)
from pyb import Pin, Timer, LED, UART
import sensor, image, time
import json,struct
LED(1).off()
LED(2).off()
LED(3).off()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQQVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_whitebal(False)
clock = time.clock()
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
def send_data_packet(x, y):
temp = struct.pack("
给大家附上openmv的代码块
关于32端的代码也没什么好说的,就是一个简单的小车代码,几个PWM,几个串口输出高低电平,让电机转动从而小车可以运作,不过在这注意的一点是,小车转弯时,差速法,你要试一下是两侧一正一反小车转弯效果好还是一正或一反另一边不动效果好,优先选择效果好的情况。
由于上传32端代码就卡死的缘故就先不上传了。。。。
第一篇博客就这样完结了(其实是今天晚上不想学习想码字的成果)
终于会帖代码了
给大家贴上32端的代码
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//ʹÄÜUSART1ʱÖÓ
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate=115200;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1 ,ENABLE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
}
extern int ov_frame;
u8 X,Y; //СÇòµÄ×ø±êÐÅÏ¢
void Data_Processing(u8 *data_buf,u8 num)
{
int theta_org,rho_org;
theta_org = (int)(*(data_buf+1)<<0) | (int)(*(data_buf+2)<<8) | (int)(*(data_buf+3)<<16) | (int)(*(data_buf+4)<<24) ;
X = theta_org;
rho_org = (int)(*(data_buf+5)<<0) | (int)(*(data_buf+6)<<8) | (int)(*(data_buf+7)<<16) | (int)(*(data_buf+8)<<24) ;
Y = rho_org;
}
void Receive_Prepare(u8 data)
{
static u8 RxBuffer[10];
static u8 _data_cnt = 0;
static u8 state = 0;
if(state==0 && data==0xAA)
{
state=1;
}
else if(state==1 && data==0xAE)
{
state=2;
_data_cnt = 0;
}
else if(state==2)
{
RxBuffer[++_data_cnt]=data;
if(_data_cnt>=8)
{
state = 0;
Data_Processing(RxBuffer,_data_cnt);
}
}
else
state = 0;
}
void USART1_IRQHandler(void)
{
u8 temp;
if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET )
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
temp = USART_ReceiveData(USART1);
Receive_Prepare(temp);
}
}