2017年国赛b题,板球控制系统的一点经验。

                                 基于arm开发板和stm32的半球控制系统

对于2017年国赛b题,想必看到我的这篇博客的朋友也和我一样,是做训练的。没错,我是一个为2019年国赛做准备的菜鸟。刚做完半球控制系统。想来这里交流一下经验。
刚看到这个题目的时候,我想过stm32是最佳的选择。但是用stm32有一个很大的问题,因为stm32裸机限制,不能实时处理多个进程。所以需要用两块stm32开发板。但是由于stm32的运算能力和自己对于算法不熟的局限性。我另外想了一种方案。
armlinux+opencv+stm32做这个题。
下面我们进行对比:
一:两块stm32:
1,(优点) 操作方便,开发简单容易, 低成本,stm32入门简单,逻辑清晰。
2,(缺点)stm32运算能力较arm开发板较低,无实时系统。图像的抗干扰能力差。会受周围光线影响。
二:一块arm开发板作为主控
这里做一下说明,我刚开始就是打算用一块arm开发版做这个题。我用的友善的开发板,用的人家martix库驱动的pwm(不知道的可以google或者维基百科);但是后来我发现他们的程序员写这个驱动的时候没有考虑动态的改变pwm的频率和占空比,只是简单的实现的pwm输出而已。经过我的实践发现,这个pwm驱动动态改变时,每一次都会在linux内核进行文件操作。以至于响应慢。输出还有噪音。最后我放弃了这种做法。改用stm32做电机控制机。
三:arm和是stm32:用stm32做电机控制可以说非常简单了,对于占空比和频率的改变响应迅速。opencv又是开源的图像处理工具,非常强大。经过opencv处理后的图像抗干扰能力强。基本不受光照的影响。但是难点在于串口的通信。32和arm开发板的通信过程需要自己设计。
机械结构及其硬件方案
这里我采用的是舵机驱动,易于调节。采用一块木板和万向节作为板的支撑。然后x,y方向放置两个舵机,利用pwm的占空比控制舵机上下移动来定位。

机械结构图
关于程序设计
首先要解决的问题是,怎么让stm32接受一帧完整的数据,怎么分辨arm发送的数据是有效数据。说白了,就是自己写一个通讯协议。当然,GitHub上面有更加标准化的用数据结构写的也可以拿来用用。这里贴出我写的stm32的接受协议

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{         
			USART_ClearFlag(USART1,USART_IT_RXNE);
     	
     switch(pUartHandle.step)
     {
    case 0:
		  
        if( USART1->DR=='#')
        {
					   
            pUartHandle.step++;               
							pUartHandle.aRxBuf_1[pUartHandle.aRxBufIndex++] =  USART1->DR;/*?????*/
       
				 }
       break;			 
  case 1:
      if( USART1->DR=='$')
      {
           pUartHandle.step++;
           pUartHandle.aRxBuf_1[pUartHandle.aRxBufIndex++] =  USART1->DR;
						  
      }
      else if( USART1->DR=='#')
          pUartHandle.step = 1;
      else
       {
             struct_init();
       }
       
               break;
					 
 case 2:
     if( USART1->DR=='#')
     {
         pUartHandle.step = 1;
         pUartHandle.aRxBufIndex = 1;
					
     }
     else
     {
		       
         pUartHandle.tmpCnt =  USART1->DR;
         pUartHandle.step++;           
					 pUartHandle.aRxBuf_1[pUartHandle.aRxBufIndex++] =  USART1->DR;/*?????*/
      if(((RX_BUF_1_LENGTH - pUartHandle.aRxBufIndex) <  USART1->DR) || ( USART1->DR == 0x00))
         {
					  
            struct_init();
						
         }
					  
     }
 break;
	 
  case 3:
		       // printf("%d",pUartHandle.tmpCnt);
          pUartHandle.aRxBuf_1[pUartHandle.aRxBufIndex++] =  USART1->DR;
          pUartHandle.tmpCnt--;
						if(pUartHandle.aRxBufIndex >= RX_BUF_1_LENGTH)
          {             
              struct_init();								
          }
      if(pUartHandle.tmpCnt==0)
      {
				  
       

						    strcpy(Data,pUartHandle.aRxBuf_1);
						   init_arry(pUartHandle.aRxBuf_1);
					     struct_init();
               
      }
				
  break;
		
   default:
         struct_init();
    break;
}

}
上面粘贴的是stm32中断接收的代码,代码实现了对于帧头的识别和区分,有效数据位识别,请自行研究。说明一下:里面的 pUartHandle是一个结构体,在下面贴出。
struct pos
{
int step;
uint16_t tmpCnt;
int aRxBufIndex;
char aRxBuf_1[RX_BUF_1_LENGTH];
}pUartHandle;

void struct_init(void)
{
pUartHandle.step = 0;

pUartHandle.tmpCnt= 0;

pUartHandle.aRxBufIndex= 0;

}

void init_arry(char *data)
{
int n=strlen(data);
int i;
for(i=0;i<n;i++)
{
*data++=0;

}
}

然后就是发送的函数了:

char *send(char a, short int data)
{
char dat[5];
int n;
sprintf(dat, “%d”, data); //除以140
n = strlen(dat);
// printf("%d\n",n);
char *str;
str = (char *)malloc(n + 4); //申请空间
memset(str, 0, sizeof(str));
str[0] = a;
str[1] = ‘$’;
str[2] = n;
for (int i = 0; i < n; i++)
{
str[i + 3] = dat[i];
}
str[n + 3] = ‘\0’;
//printf("%s\n",str);
return str;
}

包括pid的运算都是在Linux系统上完成的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
主函数中发送x,y坐标我用了"*" ,"#"这两个不同的帧头作为识别。
利用一个子线程去做pid运算,主线程做图像处理。

关于pid
我用的串级pid,内环为速度环,外环是位置环。效果还行。
鉴于后面代码排版问题,直接上传了图片。本人还是萌新,希望对你有用。有不对的地方希望留言指正。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lobmo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值