简历项目整理

毕业设计

这个比较熟悉,暂时不需要整理
(1)两次握手,对三次握手的改进
(2)结合TCP、UDP的传输机制
(3)基于UDP的可靠传输机制

基于openmv的自动跟踪小车

实现思路项目的完整代码

1、基础工作

(1)首先要能驱动小车

写一个run函数,能够给A、B两个直流电机施加动力,并给出PWM调速参数,给两个PWM引脚施加PWM波。驱动直流电机

以下为详细解读:
(1)小车模块:驱动电机运动
使用N20直流减速电机,自带驱动

(2)驱动的作用:
单片机——>弱电——>电机驱动器——>强电——>电机

(3)引脚介绍:

引脚名称作用
AIN1/AIN2控制A路电机转动,一个给高电平,一个给低电平,给的顺序决定转动方向
BIN1/BIN2控制B路电机
PWMA/PWMB与单片机可输出PWM波的IO口相连,控制电机转速

(4)具体代码:

ch1 = tim.channel(1, Timer.PWM, pin=pwma)//tim是一个定时器对象,为这个定时器创建一个通道,向pwma引脚输出PWM波
ch1.pulse_width_percent(value)//value介于0-100之间,设置脉冲活动占定时器周期的百分比
run(30,30)//左右电机都以30%的PWM波驱动,向前运动

(2)PID的初始化及运算:==

创建一个PID class,给定kp,ki,kd值来构造一个PID类。然后能够进行PID运算,输入偏差,输出PWM调速参数==。见上述代码

PID调速原理
公式:Pwm=Kpe(k)+Ki∑e(k)+Kd[e(k)-e(k-1)]
e(k):本次偏差
e(k-1):上一次的偏差
∑e(k):e(k)以及之前的偏差的累积和;其中k为1,2,k;
其中KP为比例系数;Ti为积分时间常数;Td为微分时间常数,每个系统不一样所以需要实验调试获得较为理想的,即能满足稳定性、快速性、准确性。

2、main函数内完成的工作

main函数全部代码:

# Blob Detection Example
#
# This example shows off how to use the find_blobs function to find color
# blobs in the image. This example in particular looks for dark green objects.

import sensor, image, time
import car
from pid import PID

# 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.

# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is constant...
green_threshold   = (76, 96, -110, -30, 8, 66)
size_threshold = 2000
x_pid = PID(p=0.5, i=1, imax=100)
h_pid = PID(p=0.05, i=0.1, imax=50)

def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size:
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob

while(True):
    clock.tick() # Track elapsed milliseconds between snapshots().
    img = sensor.snapshot() # Take a picture and return the image.

    blobs = img.find_blobs([green_threshold])
    if blobs:
        max_blob = find_max(blobs)
        x_error = max_blob[5]-img.width()/2
        h_error = max_blob[2]*max_blob[3]-size_threshold
        print("x error: ", x_error)
        '''
        for b in blobs:
            # Draw a rect around the blob.
            img.draw_rectangle(b[0:4]) # rect
            img.draw_cross(b[5], b[6]) # cx, cy
        '''
        img.draw_rectangle(max_blob[0:4]) # rect
        img.draw_cross(max_blob[5], max_blob[6]) # cx, cy
        x_output=x_pid.get_pid(x_error,1)
        h_output=h_pid.get_pid(h_error,1)
        print("h_output",h_output)
        car.run(-h_output-x_output,-h_output+x_output)
    else:
        car.run(18,-18)

(1)使用openmv自带图像算法

求得目标物体的相关坐标。不管是apriltag标记还是色块,都有固定的识别算法,获取到物体的坐标、偏移角等参数。

blobs = img.find_blobs([green_threshold])//寻找全部色块
max_blob = find_max(blobs)//寻找最大的那个色块

(2)计算两个方向上的误差

(色块的识别例子中的方法,apriltag应该也可以这样用)

左右方向:将物体的中心坐标移到视野的中心位置上
前后方向:使视野内物体的面积达到一定阈值,面积使用“宽X高”来计算,阈值可以自己设置
上下方向:假设该方向固定
计算误差的代码如下:

x_error = max_blob[5]-img.width()/2  //5号索引色块的中心x位置
h_error = max_blob[2]*max_blob[3]-size_threshold   //2号索引边界框的w坐标(宽度),3号索引边界框的h坐标(高度),计算得到视野内的色块面积。后面的是设置的阈值

(3)利用初始参数初始化PID类

这里的参数在实例中已经给出,现实中是需要自己调节的。将上述计算得到的两个方向上的误差作为输入参数进行计算,得到下一步的PWM参数值。代码如下:

x_output=x_pid.get_pid(x_error,1)
h_output=h_pid.get_pid(h_error,1)

(4)将PWM参数输入run函数,驱动电机旋转。

car.run(-h_output-x_output,-h_output+x_output)

这里比较有意思。
1、x_output代表左右这个方向的输出值,小车运动过程中的左右调整是通过两电机的差速实现的,所以run函数的参数中x_output的符号不同
2、h_output是前后方向的输出值,两电机在这个方向上“共进退”,所以参数中是相同符号

基于stm32的步进电机控制系统

参考本篇

1、主要器件的型号及特性

器件名称型号作用特性
四相五线步进电机28BYJ48控制脉冲频率(即两个高电平之间的delay)控制速度,控制给高电平的顺序控制转动方向。A->B->C->D或者反过来,挨个给高电平,完成一个循环后,转过一个齿距
大电流驱动阵列ULN2003放大电流,增强驱动能力IO口的高电平输出可以直接作为ULN2003的控制输入
字符型液晶显示模块LCD1602对转速、转动方向进行显示首先用1号命令清理显示界面。把字符串存在数组,将数组作为形参进行显示;若想显示变量,需要使用sprintf将变量格式转换为字符指针,然后将该指针作为形参进行显示

2、具体实现细节

贴一下代码:

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "lcd1602.h" 
#include "timer.h"
#include "stdio.h"
#include "beep.h" 
u8 speed=0;//档位,是一个全局变量
short count=0;//圈数,同样是全局变量
u8 flag=1;//旋转标志,高电平顺时针,低电平逆时针
void step_motor_forward(void);//顺时针旋转子程序
void step_motor_back(void);//逆时针旋转子程序
void check();	//按键检查
void display();	//LCD显示
 
 
/************************************************
 ALIENTEK精英STM32开发板实验3
 按键输入实验     
 技术支持:www.openedv.com
 淘宝店铺:http://eboard.taobao.com 
 关注微信公众平台微信号:"正点原子",免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者:正点原子 @ALIENTEK
************************************************/



 int main(void)
 {
 	vu8 key=0;
 
    delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为 115200
	LED_Init();		  		//初始化与LED连接的硬件接口
	KEY_Init();         //按键初始化
	BEEP_Init();
	GPIO_Configuration();
	LCD1602_Init();     //LCD初始化
	LCD1602_ClearScreen();

	 
    check();
}

 
void check()
{
	vu8 key=0;
	speed=0;
	count=0;
	while(1)
	{
 		key=KEY_Scan(0);	//得到键值
	   	if(key)
		{						   
			switch(key)
			{				 
				case KEY1_PRES:	//进入顺时针旋转子程序
	     	speed=1;
				count=0;					
         step_motor_forward()				;
				break;
				case KEY0_PRES:	//进入逆时针旋转子程序
				speed=1;
                count=0;
                step_motor_back();
				break;
				case WKUP_PRES://进入LCD显示子程序
					display();
					break;
			}
		}
	}	 ;
}

void step_motor_forward(void)
{
		 vu8 key=0;
	int delaytime=7;
	int n1=0;//循环数
	flag=1;
while(1)
	{
		
		
	GPIO_SetBits(GPIOB,GPIO_Pin_5);  //引脚GPIOB.5置位
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);  

	GPIO_ResetBits(GPIOE,GPIO_Pin_0);  	
	GPIO_ResetBits(GPIOE,GPIO_Pin_1);   		
	delay_ms(delaytime);  		   //延时
	
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);  
	GPIO_SetBits(GPIOE,GPIO_Pin_5);  //引脚GPIOE.5置位
	GPIO_ResetBits(GPIOE,GPIO_Pin_0);   
	GPIO_ResetBits(GPIOE,GPIO_Pin_1); 		
	delay_ms(delaytime);  		   //延时
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);  
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);  
	GPIO_SetBits(GPIOE,GPIO_Pin_0);  //引脚GPIOE.0置位
	GPIO_ResetBits(GPIOE,GPIO_Pin_1); 	
	delay_ms(delaytime);  		   //延时
	
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);   
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);  
	GPIO_ResetBits(GPIOE,GPIO_Pin_0);  		
	GPIO_SetBits(GPIOE,GPIO_Pin_1);  //引脚GPIOE.1置位		
	delay_ms(delaytime);  		   //延时
	
	n1++;
			if((n1%400==0)&&(n1>0))
		{
			n1=0;//清0
			count++;//圈数加1
		}
		
		

		key = KEY_Scan(0);
		if(key==KEY1_PRES)
		{
			delaytime--;
			speed++;
		}
		if(key==KEY0_PRES)
		{
				speed=1;
                count=0;
			step_motor_back();
		}			
		if((delaytime==1)||(speed==7))
       check();
	  if(key==WKUP_PRES)
			display();
	
}	
	}

	
	
	


void step_motor_back(void)
{
		 vu8 key=0;
	int delaytime=7;
	int n1=0;
	flag=0;
	while(1)
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);  

	GPIO_ResetBits(GPIOE,GPIO_Pin_0); 
	GPIO_SetBits(GPIOE,GPIO_Pin_1);   //GPIOE.1置位
	delay_ms(delaytime);  		   //延时
	
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);  
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);  
	GPIO_SetBits(GPIOE,GPIO_Pin_0);   //GPIOE.0置位	
	GPIO_ResetBits(GPIOE,GPIO_Pin_1);  	
	delay_ms(delaytime);  		   //延时
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);  
	GPIO_SetBits(GPIOE,GPIO_Pin_5);   //GPIOE.5置位
	GPIO_ResetBits(GPIOE,GPIO_Pin_0);  
	GPIO_ResetBits(GPIOE,GPIO_Pin_1);  	
	delay_ms(delaytime);  		   //延时
	
	
	GPIO_SetBits(GPIOB,GPIO_Pin_5);   //LED1对应引脚GPIOE.5拉高,灭 等同LED1=1;
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);  
	GPIO_ResetBits(GPIOE,GPIO_Pin_0);  
	GPIO_ResetBits(GPIOE,GPIO_Pin_1);  	
	delay_ms(delaytime);  		   //延时300ms
	
	
		n1++;
		
if((n1%400==0)&&(n1>0))
		{
			n1=0;//记得清0
			count++;
		}

	key = KEY_Scan(0);
		if(key==KEY0_PRES)
		{
			delaytime--;
			speed++;
		}
	if(key==KEY1_PRES)
		{
				speed=1;
                count=0;
			step_motor_forward();
		}
		if((delaytime==1)||(speed==7))
       check();
	  if(key==WKUP_PRES)
			display();
}
	}

	
	void display(void)
{	


	u8 direction1[] = "clkwise";//顺时针
		u8 direction2[] = "anticlk";//逆时针
	u8 gear[]="gear:";//档位
	u8 circle[] = "circle:";//圈数
	u8 s0[3],s1[3];
	u8 key = 0;
	int n1=0;
while(1)
	{
		
     if(n1%200==0)
		{
			LCD1602_Write_Cmd(0x01);
			LCD1602_Show_Str(9, 0,gear);// 0列1行
			LCD1602_Show_Str(0, 1, circle);
			if(flag==1)
			LCD1602_Show_Str(0, 0, direction1);
			else
			LCD1602_Show_Str(0, 0, direction2);
		}

		    
		
		n1++;
		
		sprintf((char*)s0,"%d",speed);
		sprintf((char*)s1,"%d",count);
		LCD1602_Show_Str(15, 0, s0);
		LCD1602_Show_Str(9, 1,s1);// 0列1行
		TIM_SetCompare2(TIM3,10);
		TIM_SetCompare2(TIM5,420);
		


		key = KEY_Scan(0);
		if((key==KEY1_PRES)||(key==KEY0_PRES)||(n1==400))
		{			
	      return;
		}
			if(key==WKUP_PRES)
          n1=0;
		
		
		
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值