23电赛E题激光追踪练习

这个练习是在暑假电赛集训期间做的,尽力而为了,但是结果还是有很大误差,仅供参考。

算是对自己学习的记录。

先看一下题目要求:

首先分析

云台分为两个,一个是红激光云台,一个是绿激光云台。分成两个看:

红激光云台需要做两件事:

第一件:绕背景大框运动,这个矩形大框的识别要求太高,所以最后选择了开环手动定点获取坐标,然后再执行,对于复位,也是如此。

第二件:绕黑色胶带矩形运动,激光在胶带上识别的效果很差,通过改变曝光度等,最后做到在上面能够识别,但是一旦运动起来,在画面中完全看不到激光的影子,所以最后选择了半开环,先识别矩形的四个角坐标,然后传给32,以pid进行激光位置的计算运动。(在这里将任务3和任务4结合了,如果第三位自己手动写死,那么精度自然更高)

绿激光云台只需要做一件事:

识别红绿激光的坐标,将绿的当作输入,红的当作目标,不断进行pid运算,其难点依然是在胶带上的识别。

下面说我的处理方法:

对于红绿激光的识别,一开始我是在正常亮度下进行,能够识别到,但是发现,从白天到晚上,开灯或不开灯,环境光线的变化会导致识别不正常。所以后面大胆将曝光度直接拉低到画面全黑,只能看到红色和激光,识别效果反而非常稳定。

import sensor, image, time
from machine import UART
from pyb import UART
import json
redblack_threshold   =(10, 63, 17, 65, 9, 50) #胶带
red_threshold =(11, 100, 16, 127, 1, 68)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_windowing(100,40,140,140)
sensor.set_vflip(True)##上下
#sensor.set_hmirror(True)##左右
sensor.skip_frames(10)
clock = time.clock()
sensor.set_auto_whitebal(False)#禁用白平衡
#sensor.set_auto_gain(False)#关闭自动增益
t=0
p=0
d = {}
i=0
mode=0
rx_buff=[]
state = 0
f=0
uart = UART(3, 115200, timeout_char=1000)
#串口接收函数
def Receive_Prepare(da):
    global state
    if state==0:
        if da == 0x0d:#帧头
            state = 1
        else:
            state = 0
            rx_buff.clear()
    elif state==1:
        rx_buff.append(da)
        mode=da
    else:
        state = 0
        rx_buff.clear()

while(True):
    img = sensor.snapshot()
    red_blobs = img.find_blobs([red_threshold])
    redblack_blobs=img.find_blobs([redblack_threshold])

    if(uart.any()>0):
       f=uart.readchar()
       Receive_Prepare(f)
       p=mode
       mode=f

    if mode==0:
        sensor.set_auto_exposure(False,10000)#设置曝光度

        if red_blobs:
            for a in red_blobs:
                img.draw_cross(a[5], a[6])
                print(a[5],a[6],mode)
                data = bytearray([0xb3,0xb3,0,0,0,0,0,0,0,0,a[5],a[6],0x0d,0x0a])
                uart.write(data)
    if p<mode:
        t=0
    if mode>=1:

        if t==0:
            sensor.set_auto_exposure(False,94000)#设置曝光度
        rects=img.find_rects(threshold = 10000)
        if rects:
            t=1
            for b in rects:
                img.draw_rectangle(b.rect())
                i=0
                for p in b.corners():
                    d[i]=p[0]
                    d[i+1]=p[1]
                    i+=2
                print(d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],mode)
                data = bytearray([0xb3,0xb3,d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],70, 70,0x0d,0x0a])
                uart.write(data)
        sensor.set_auto_exposure(False,120000)#设置曝光度
        if redblack_blobs or red_blobs:
            for a in redblack_blobs or red_blobs:
                img.draw_cross(a[5], a[6])
                data = bytearray([0xb3,0xb3,0,0,0,0,0,0,0,0,a[5], a[6],0x0d,0x0a])
                uart.write(data)

对于舵机运动,进行PID控制,这是keil里的控制代码,输入量和目标量都是位置参数,x轴舵机和y轴舵机是独立的。

//PID函数
uint16_t Motorx_PID_Cal(int input_cx,int setx)
{
	static int pwmout=0,last_error=0,last_last_error=0;
	int error =setx - input_cx;	// 误差
	int d_error=error-last_error;
	int dd_error = -2*last_error+error+last_last_error; 
	 
	pwmout+=(cmd_P-1)*d_error/10 +(cmd_I-1.1)*error/10+cmd_D*dd_error/10; // 输出pwm信号
	last_last_error=last_error;
	last_error = error;
	if(pwmout > 970) pwmout=970;
	if(pwmout < 550) pwmout=550;
	comx_Set(pwmout);
	return pwmout;
}

uint16_t Motory_PID_Cal(int input_cy,int sety)
{
	static int pwmout=0,last_error=0,last_last_error=0;
	int error =sety - input_cy;	// 误差
	int d_error=error-last_error;
	int dd_error = -2*last_error+error+last_last_error; 
	 
	pwmout+=cmd_P*d_error/10 +cmd_I*error/10+cmd_D*dd_error/10; // 输出pwm信号
	last_last_error=last_error;
	last_error = error;
	if(pwmout > 1660) pwmout=1660;
	if(pwmout < 1450) pwmout=1450;
	comy_Set(pwmout);
	return pwmout;
}

最后结果:

集训电赛2023e题 激光追踪

其他的可以详见工程

23电赛e: 2023电赛e题激光追踪 (gitee.com)icon-default.png?t=N7T8https://gitee.com/lin-zhiquan11/23-electric-racing-e

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值