K210云台追踪色块

K210为sipeed的Dock,全引脚引出,比较好操作。

云台为二维云台,舵机:SG90,最常用的一款。

基于前面一位大佬的学习笔记的学习笔记,做了自己的一些理解以及修改,现在实现的功能为设定指定色块,实时追踪实现色块始终在屏幕中央。

做的比较匆忙,没有很多解释,以后会再来改进

很新手,有错误请指正。程序不完善会有想不到的bug,有更进方法也请在评论区发言

用到的库有:

from machine import Timer,PWM
import sensor, time, image, lcd     # 导入感光元件模块 sensor 跟踪运行时间模块 time 机器视觉模块 image
import utime                   # 导入延时模块 utime
from fpioa_manager import fm   # 从 GPIO 模块中导入 引脚注册模块 fm
from Maix import GPIO          # 从 Maix 模块中导入 模块 GPIO
import lcd                     # 导入 LCD 模块
from machine import UART
1.注册串口

根据需要注册自己想要的串口,其实这些到后面都没有用过,是LED指示灯以及串口通信用的,这里都没用到。

#------------------------------------------------------------------------------------------
#注册串口
#------------------------------------------------------------------------------------------
fm.register(6, fm.fpioa.UART2_RX)
fm.register(8, fm.fpioa.UART2_TX)
fm.register(16,fm.fpioa.GPIO1)
fm.register(14,fm.fpioa.GPIOHS0)
fm.register(13,fm.fpioa.GPIOHS1)
fm.register(12,fm.fpioa.GPIOHS2)

K_1 = GPIO(GPIO.GPIO1,GPIO.IN)
yb_uart = UART(UART.UART2, 115200, 8, 0, 0, timeout=1000, read_buf_len=4096)
2.普通正常的相机初始化
#--------------------------------------------------------------------------------------------------------------------
# 感光元件设置初始化
#--------------------------------------------------------------------------------------------------------------------
sensor.reset()                                              # 重置并初始化感光元件 默认设置为 摄像头频率 24M 不开启双缓冲模式
#sensor.reset(freq=24000000, dual_buff=True)                # 设置摄像头频率 24M 开启双缓冲模式 会提高帧率 但内存占用增加

sensor.set_pixformat(sensor.RGB565)                         # 设置图像格式为 RGB565 (彩色) 除此之外 还可设置格式为 GRAYSCALE 或者 YUV422
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)         #水平
sensor.set_hmirror(1)       #垂直
sensor.set_auto_exposure(1)             #自动曝光
#sensor.set_contrast(1)
#sensor.set_auto_gain(0, gain_db = 30)   #增益加强
sensor.set_auto_gain(False)

sensor.skip_frames(time = 2000)
lcd.init()


clock = time.clock()
3.设置定时器0,1

定时器0用来回调,定时器1用来输出PWM使舵机转动。

一般SG90的周期为20ms,故我们设置定时器1的频率为50Hz,这样到后面好驱动

#--------------------------------------------------------------------------------------------------------------------
# 定时器使用,定义定时器属性
#--------------------------------------------------------------------------------------------------------------------
class timer_property():
    cnt     = 0     #定时器计数值
    cnt_max = 0     #定时器计数上线
    period  = 0     #定时器周期
    freq    = 0     #定时器频率

#定时器0 配置
#定时器0 实例化类
timer0 = timer_property()
timer0.cnt_max = 9          #设定 定时器0 的计数上限为9
timer0.period = 100         #设定 定时器0 的周期为100

#定时器0 定义回调函数
def timer0_back(tim_0):
    if timer0.cnt < timer0.cnt_max:
        timer0.cnt += 1
    else:
        timer0.cnt = 0      #超出计数值上限,归零

# 定时器初始化,
tim_0 = Timer(Timer.TIMER0,Timer.CHANNEL0,  # 定时器编号 定时器0
              mode = Timer.MODE_PERIODIC,   # 定时器模式,为周期性
              unit = Timer.UNIT_MS,         # 定时器周期单位,为ms
              period = timer0.period,       # 定时器周期,单位ms
              callback = timer0_back)       # 定时器触发中断后执行的回调函数timer0_back

#定时器1 实例化类
timer1 = timer_property()
timer1.freq    = 50

# 定时器1 通道0
tim_1_ch0 = Timer(Timer.TIMER1,
                    Timer.CHANNEL0,
                    mode = Timer.MODE_PWM)   # 定时器模式,为PWM
# 定时器1 通道1
tim_1_ch1 = Timer(Timer.TIMER0,
                    Timer.CHANNEL0,
                    mode = Timer.MODE_PWM)   # 定时器模式,为周期性

#定时器使用:在while循环中,当定时器0的计数器值被重置为0的时候,执行函数

4.定义颜色类,以及实例

#--------------------------------------------------------------------------------------------------------------------
#定义寻找颜色类
#--------------------------------------------------------------------------------------------------------------------
class color_property():
    cx                      =  0                            # x轴中心坐标
    cy                      =  0                            # y轴中心坐标
    flag                    =  0                            # 色块标志位: 1找到 0没找到
    color                   =  0                            # 色块颜色标志位,可以用 1 来表示黑色这种
    density                 =  0                            # 色块密度比,反映色块锁定程度,值越大,锁定程度越好
    pixels_max              =  0                            # 色块像素最大值
    led_flag                =  0                            # LED标志位 方便调试用

    color_threshold         = (0, 0, 0, 0, 0, 0)            # 色块颜色阈值, 返回为LAB
    color_roi               = (0,0,320,240)                 # 色块寻找区域(感兴趣区域)
    color_x_stride          =  1                            # 色块 x轴 像素最小宽度 色块如果比较大可以调大此参数 提高寻找精确度
    color_y_stride          =  1                            # 色块 y轴 像素最小宽度
    color_pixels_threshold  =  100                          # 色块 像素个数阈值 例如调节此参数为100 则可以滤除色块像素小于100的色块
    color_area_threshold    =  100                          # 色块 被框面积阈值 例如调节此参数为100 则可以滤除色块被框面积小于100的色块
    color_merge             =  True                         # 是否合并寻找到的色块 True 则合并 False 则不合并
    color_margin            =  1                            # 色块合并间距 例如调节此参数为1 若上面选择True合并色块 且被找到的色块有多个 相距1像素 则会将这些色块合并

# 实例化类
# 黑色
black = color_property()
black.color_threshold         = (98, 57, -62, 40, 50, 127)# 线的色块颜色阈值LAB
black.color_roi               = (0,0,320,240)            # 色块寻找区域,x,y,w,h
black.color_x_stride          =  1
black.color_y_stride          =  1
black.color_pixels_threshold  =  150            # 像素个数阈值 越大查找色块越精确
black.color_area_threshold    =  150            # 被框面积阈值 越大查找色块越精确
black.color_merge             =  True
black.color_margin            =  2             # 色块合并间距 例如调节此参数为1 若上面选择True合并色块 且被找到的色块有多个 相距1像素 则会将这些色块合并
5.定义寻找色块的函数
# 定义寻找色块函数
def opv_find_blobs(color,led_flag):
    color.pixels_max = 0                                    # 重置 色块 最大像素数量
    color.flag       = 0                                    # 重置 色块 标志位
    color.led_flag   = 0                                    # 重置 led 标志位

    for blobs in img.find_blobs([color.color_threshold],                                # 色块颜色阈值
                                roi = color.color_roi,                                  # 色块寻找区域(感兴趣区域)
                                x_stride = color.color_x_stride,                        # 色块 x轴 像素最小宽度 色块如果比较大可以调大此参数 提高寻找速度
                                y_stride = color.color_y_stride,                        # 色块 y轴 像素最小宽度 色块如果比较大可以调大此参数 提高寻找速度
                                pixels_threshold = color.color_pixels_threshold,        # 色块 像素个数阈值 例如调节此参数为100 则可以滤除色块像素小于100的色块
                                area_threshold = color.color_area_threshold,            # 色块 被框面积阈值 例如调节此参数为100 则可以滤除色块被框面积小于100的色块
                                merge = color.color_merge,                              # 是否合并寻找到的色块 True 则合并 False 则不合并
                                margin = color.color_margin):                           # 色块合并间距 例如调节此参数为1 若上面选择True合并色块 且被找到的色块有多个 相距1像素 则会将这些色块合并
        img.draw_rectangle(blobs[0:4])                      # 圈出找到的色块
        if  color.pixels_max < blobs.pixels():               # 找到面积最大的色块
            color.pixels_max = blobs.pixels()
            color.cx = blobs.cx()                           # 将面积最大的色块的 x轴 中心坐标值 赋值给 color
            color.cy = blobs.cy()                           # 将面积最大的色块的 y轴 中心坐标值 赋值给 color
            color.flag = 1                                  # 标志画面中有找到色块
            color.density = blobs.density()                 # 将面积最大的色块的 色块密度比 赋值给 color
            color.led_flag = led_flag                       # 将控制led颜色的标志位的值 赋值给 color

    if color.flag == 1:                                     # 标记画面中被找到的最大色块的中心坐标
        img.draw_cross(color.cx,color.cy, color=127, size = 15)
        img.draw_circle(color.cx,color.cy, 15, color = 127)
6.电机类以及实例

初设了4个电机,其实不需要这么多,因为太懒了没把电机改成舵机,其实motor这代表的是舵机

#--------------------------------------------------------------------------------------------------------------------
# 电机类定义
#--------------------------------------------------------------------------------------------------------------------

class Motor_Property():
    motor1_duty      = 0         # 电机1 占空比
    motor2_duty      = 0         # 电机2 占空比
    motor3_duty      = 0         # 电机3 占空比
    motor4_duty      = 0         # 电机4 占空比

    duty1_center   = 0      #当物体移至画面中心时,占空比中间值,即舵机的位置,
    duty2_center   = 0

    motor1_pin  = 0              # 电机1 引脚
    motor2_pin  = 0              # 电机2 引脚
    motor3_pin  = 0              # 电机3 引脚
    motor4_pin  = 0              # 电机4 引脚

    control_x   = 0            # 被控坐标 x
    control_y   = 0            # 被控坐标 y
    control_flag_x = 'x'       #打个向哪个地方转的标签
    control_flag_y = 'y'

# 实例化电机类
motor = Motor_Property()     # 实例化电机类 Motor_Property() 为 motor
motor.motor1_duty = 7.5            # 电机1的占空比 初始设置, x轴是7.5%为中心,duty范围为2-13
motor.motor2_duty = 8            # 电机2的占空比 初始设置, y轴是 8%为水平线
motor.duty1_center   = 7.5
motor.duty2_center   = 6
motor.motor1_pin  = 11       # 电机1的引脚 也就是x轴
motor.motor2_pin  = 12       # 电机2的引脚 也就是y轴
motor.control_x = 160
motor.control_y = 120                        # 被控坐标 y
control_flag_x = 'x'                   #打个向哪个地方转的标签
control_flag_y = 'y'
7.初始化俩舵机的PWM
motor1 = PWM(tim_1_ch0, freq=timer1.freq,duty=motor.motor1_duty,pin=11)# 电机1, x轴
motor2 = PWM(tim_1_ch1, freq=timer1.freq,duty=motor.motor2_duty,pin=12)# 电机2, y轴
8.定义舵机的占空比,控制舵机移动
#定义电机占空比控制函数
def motor_control(motor,x,y):           #比如控制舵机也可以在这里写
    val_1 = 0
    val_2 = 0
    if x <= motor.control_x:                    # 若色块当前x坐标小于画面中心,物体在小车左边,向左走
        val_1 = (motor.control_x - x) *0.004375 # 这里算的是与中心相差距离,得出屏幕的相对距离
        control_flag_x = 'left'
        motor.motor1_duty = motor.duty1_center + val_1     #减小电机1的占空比
        #print("x_duty:",motor.motor1_duty)
        yb_uart.write(control_flag_x)

    if x > motor.control_x:                 # 若当前x坐标大于画面中心,物体在小车右边,向左走
        #val_1 = (x - motor.control_x) *0.034375
        val_1 = (x - motor.control_x) *0.0045
        control_flag_x = 'right'
        motor.motor1_duty = motor.duty1_center - val_1     #增大电机1的占空比,现在发现是反的
        #print("x_duty:",motor.motor1_duty)
        yb_uart.write(control_flag_x)

    if y <= motor.control_y:                # 若当前y坐标小于画面中心,物体在小车上边
        #val_2 = (motor.control_y - y) *0.016665
        val_2 = (motor.control_y - y) *0.008465
        control_flag_y = 'forward'
        motor.motor2_duty = motor.duty2_center - val_2
        yb_uart.write(control_flag_y)
        print("y_duty:",motor.motor2_duty)

    if y > motor.control_y:                 # 若当前y坐标大于画面中心,物体在小车下边,向后走
        val_2 = (y - motor.control_y) *0.008465
        control_flag_y = 'backward'
        yb_uart.write(control_flag_y)
        motor.motor2_duty = motor.duty2_center + val_2
        print("y_duty:",motor.motor2_duty)
9.主要函数

这里实现的便是驱动舵机运转,我们知道SG90的转动有限,从0-180°,占空比一般为5%-10%,所以我先提前做了测试,测出舵机极限的占空比以及对应的位置:

当到了极限的时候,需要让舵机一直等于极限值即可,不要让舵机发疯

while(black.cx!=motor.control_x or black.cy!=motor.control_y):  # 不在中心点
        motor1.duty(motor.motor1_duty)  # 将获取到的电机1占空比 装载,x轴
        motor2.duty(motor.motor2_duty)  # y轴
        if (motor.motor1_duty>=13 ):
            motor.motor1_duty = 13
        if (motor.motor2_duty>=8):
            motor.motor2_duty = 8
        if (motor.motor1_duty <=3):
            motor.motor1_duty = 3
        if (motor.motor2_duty<=3):
            motor.motor2_duty = 3       # 3是向上抬头

        if black.cx <= motor.control_x:
            black.cx += 1
        if black.cx > motor.control_x:
            black.cx -= 1
        if black.cy <= motor.control_y:
            black.cy += 1
        if black.cy > motor.control_y:
            black.cy -= 1
        if (black.cx==motor.control_x and black.cy==motor.control_y):
            motor.duty1_center = motor.motor1_duty
            motor.duty2_center = motor.motor2_duty
            break

10.总代码:
from machine import Timer,PWM
import sensor, time, image, lcd     # 导入感光元件模块 sensor 跟踪运行时间模块 time 机器视觉模块 image
import utime                   # 导入延时模块 utime
from fpioa_manager import fm   # 从 GPIO 模块中导入 引脚注册模块 fm
from Maix import GPIO          # 从 Maix 模块中导入 模块 GPIO
import lcd                     # 导入 LCD 模块
from machine import UART

#--------------------------------------------------------------------------------------------------------------------
#注册串口
#--------------------------------------------------------------------------------------------------------------------
fm.register(6, fm.fpioa.UART2_RX)
fm.register(8, fm.fpioa.UART2_TX)
fm.register(16,fm.fpioa.GPIO1)
fm.register(14,fm.fpioa.GPIOHS0)
fm.register(13,fm.fpioa.GPIOHS1)
fm.register(12,fm.fpioa.GPIOHS2)

K_1 = GPIO(GPIO.GPIO1,GPIO.IN)
yb_uart = UART(UART.UART2, 115200, 8, 0, 0, timeout=1000, read_buf_len=4096)
#LED_blue = GPIO(GPIO.GPIOHS0,GPIO.OUT)
#LED_red = GPIO(GPIO.GPIOHS1,GPIO.OUT)
#LED_green = GPIO(GPIO.GPIOHS2,GPIO.OUT)

#--------------------------------------------------------------------------------------------------------------------
# 感光元件设置初始化
#--------------------------------------------------------------------------------------------------------------------
sensor.reset()                                              # 重置并初始化感光元件 默认设置为 摄像头频率 24M 不开启双缓冲模式
#sensor.reset(freq=24000000, dual_buff=True)                # 设置摄像头频率 24M 开启双缓冲模式 会提高帧率 但内存占用增加

sensor.set_pixformat(sensor.RGB565)                         # 设置图像格式为 RGB565 (彩色) 除此之外 还可设置格式为 GRAYSCALE 或者 YUV422
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)         #水平
sensor.set_hmirror(1)       #垂直
sensor.set_auto_exposure(1)             #自动曝光
#sensor.set_contrast(1)
#sensor.set_auto_gain(0, gain_db = 30)   #增益加强
sensor.set_auto_gain(False)

sensor.skip_frames(time = 2000)
lcd.init()


clock = time.clock()


#--------------------------------------------------------------------------------------------------------------------
# 定时器使用,定义定时器属性
#--------------------------------------------------------------------------------------------------------------------
class timer_property():
    cnt     = 0     #定时器计数值
    cnt_max = 0     #定时器计数上线
    period  = 0     #定时器周期
    freq    = 0     #定时器频率

#定时器0 配置
#定时器0 实例化类
timer0 = timer_property()
timer0.cnt_max = 9          #设定 定时器0 的计数上限为9
timer0.period = 100         #设定 定时器0 的周期为100

#定时器0 定义回调函数
def timer0_back(tim_0):
    if timer0.cnt < timer0.cnt_max:
        timer0.cnt += 1
    else:
        timer0.cnt = 0      #超出计数值上限,归零

# 定时器初始化,
tim_0 = Timer(Timer.TIMER0,Timer.CHANNEL0,  # 定时器编号 定时器0
              mode = Timer.MODE_PERIODIC,   # 定时器模式,为周期性
              unit = Timer.UNIT_MS,         # 定时器周期单位,为ms
              period = timer0.period,       # 定时器周期,单位ms
              callback = timer0_back)       # 定时器触发中断后执行的回调函数timer0_back

#定时器1 实例化类
timer1 = timer_property()
timer1.freq    = 50

# 定时器1 通道0
tim_1_ch0 = Timer(Timer.TIMER1,
                    Timer.CHANNEL0,
                    mode = Timer.MODE_PWM)   # 定时器模式,为PWM
# 定时器1 通道1
tim_1_ch1 = Timer(Timer.TIMER0,
                    Timer.CHANNEL0,
                    mode = Timer.MODE_PWM)   # 定时器模式,为周期性

#定时器使用:在while循环中,当定时器0的计数器值被重置为0的时候,执行函数


#--------------------------------------------------------------------------------------------------------------------
#定义寻找颜色类
#--------------------------------------------------------------------------------------------------------------------
class color_property():
    cx                      =  0                            # x轴中心坐标
    cy                      =  0                            # y轴中心坐标
    flag                    =  0                            # 色块标志位: 1找到 0没找到
    color                   =  0                            # 色块颜色标志位,可以用 1 来表示黑色这种
    density                 =  0                            # 色块密度比,反映色块锁定程度,值越大,锁定程度越好
    pixels_max              =  0                            # 色块像素最大值
    led_flag                =  0                            # LED标志位 方便调试用

    color_threshold         = (0, 0, 0, 0, 0, 0)            # 色块颜色阈值, 返回为LAB
    color_roi               = (0,0,320,240)                 # 色块寻找区域(感兴趣区域)
    color_x_stride          =  1                            # 色块 x轴 像素最小宽度 色块如果比较大可以调大此参数 提高寻找精确度
    color_y_stride          =  1                            # 色块 y轴 像素最小宽度
    color_pixels_threshold  =  100                          # 色块 像素个数阈值 例如调节此参数为100 则可以滤除色块像素小于100的色块
    color_area_threshold    =  100                          # 色块 被框面积阈值 例如调节此参数为100 则可以滤除色块被框面积小于100的色块
    color_merge             =  True                         # 是否合并寻找到的色块 True 则合并 False 则不合并
    color_margin            =  1                            # 色块合并间距 例如调节此参数为1 若上面选择True合并色块 且被找到的色块有多个 相距1像素 则会将这些色块合并

# 实例化类
# 黑色
black = color_property()
black.color_threshold         = (98, 57, -62, 40, 50, 127)# 线的色块颜色阈值LAB
black.color_roi               = (0,0,320,240)            # 色块寻找区域,x,y,w,h
black.color_x_stride          =  1
black.color_y_stride          =  1
black.color_pixels_threshold  =  150            # 像素个数阈值 越大查找色块越精确
black.color_area_threshold    =  150            # 被框面积阈值 越大查找色块越精确
black.color_merge             =  True
black.color_margin            =  2             # 色块合并间距 例如调节此参数为1 若上面选择True合并色块 且被找到的色块有多个 相距1像素 则会将这些色块合并

# 红色
red   = color_property()
red.color_threshold           =  (73, 2, -118, 94, -103, 99)
red.color_roi                 =  (0,0,320,240)
red.color_x_stride            =  1
red.color_y_stride            =  1
red.color_pixels_threshold    =  100
red.color_area_threshold      =  100
red.color_merge               =  True
red.color_margin              =  1

# 绿色 预留
green = color_property()

# 蓝色 预留
blue  = color_property()

# 定义寻找色块函数
def opv_find_blobs(color,led_flag):
    color.pixels_max = 0                                    # 重置 色块 最大像素数量
    color.flag       = 0                                    # 重置 色块 标志位
    color.led_flag   = 0                                    # 重置 led 标志位

    for blobs in img.find_blobs([color.color_threshold],                                # 色块颜色阈值
                                roi = color.color_roi,                                  # 色块寻找区域(感兴趣区域)
                                x_stride = color.color_x_stride,                        # 色块 x轴 像素最小宽度 色块如果比较大可以调大此参数 提高寻找速度
                                y_stride = color.color_y_stride,                        # 色块 y轴 像素最小宽度 色块如果比较大可以调大此参数 提高寻找速度
                                pixels_threshold = color.color_pixels_threshold,        # 色块 像素个数阈值 例如调节此参数为100 则可以滤除色块像素小于100的色块
                                area_threshold = color.color_area_threshold,            # 色块 被框面积阈值 例如调节此参数为100 则可以滤除色块被框面积小于100的色块
                                merge = color.color_merge,                              # 是否合并寻找到的色块 True 则合并 False 则不合并
                                margin = color.color_margin):                           # 色块合并间距 例如调节此参数为1 若上面选择True合并色块 且被找到的色块有多个 相距1像素 则会将这些色块合并
        img.draw_rectangle(blobs[0:4])                      # 圈出找到的色块
        if  color.pixels_max < blobs.pixels():               # 找到面积最大的色块
            color.pixels_max = blobs.pixels()
            color.cx = blobs.cx()                           # 将面积最大的色块的 x轴 中心坐标值 赋值给 color
            color.cy = blobs.cy()                           # 将面积最大的色块的 y轴 中心坐标值 赋值给 color
            color.flag = 1                                  # 标志画面中有找到色块
            color.density = blobs.density()                 # 将面积最大的色块的 色块密度比 赋值给 color
            color.led_flag = led_flag                       # 将控制led颜色的标志位的值 赋值给 color

    if color.flag == 1:                                     # 标记画面中被找到的最大色块的中心坐标
        img.draw_cross(color.cx,color.cy, color=127, size = 15)
        img.draw_circle(color.cx,color.cy, 15, color = 127)

# 定义打印色块参数函数
def print_blobs_property(color,name):
    print(name,"cx:",color.cx,"cy:",color.cy,"flag:",color.flag,"color:",color.color,"density:",color.density,"led_flag:",color.led_flag)



#--------------------------------------------------------------------------------------------------------------------
# 电机类定义
#--------------------------------------------------------------------------------------------------------------------

class Motor_Property():
    motor1_duty      = 0         # 电机1 占空比
    motor2_duty      = 0         # 电机2 占空比
    motor3_duty      = 0         # 电机3 占空比
    motor4_duty      = 0         # 电机4 占空比

    duty1_center   = 0      #当物体移至画面中心时,占空比中间值,即舵机的位置,
    duty2_center   = 0

    motor1_pin  = 0              # 电机1 引脚
    motor2_pin  = 0              # 电机2 引脚
    motor3_pin  = 0              # 电机3 引脚
    motor4_pin  = 0              # 电机4 引脚

    control_x   = 0            # 被控坐标 x
    control_y   = 0            # 被控坐标 y
    control_flag_x = 'x'       #打个向哪个地方转的标签
    control_flag_y = 'y'

# 实例化电机类
motor = Motor_Property()     # 实例化电机类 Motor_Property() 为 motor
motor.motor1_duty = 7.5            # 电机1的占空比 初始设置, x轴是7.5%为中心,duty范围为2-13
motor.motor2_duty = 8            # 电机2的占空比 初始设置, y轴是 8%为水平线
motor.duty1_center   = 7.5
motor.duty2_center   = 6
motor.motor1_pin  = 11       # 电机1的引脚 也就是x轴
motor.motor2_pin  = 12       # 电机2的引脚 也就是y轴
motor.control_x = 160
motor.control_y = 120                        # 被控坐标 y
control_flag_x = 'x'                   #打个向哪个地方转的标签
control_flag_y = 'y'

# 创建对象 电机1, 通道0, 定时器1控制的, 占空比
# motor1 = PWM(tim_1_ch0, freq=timer1.freq,duty=motor.motor1_duty,pin=motor.motor1_pin)
# motor2 = PWM(tim_1_ch1, freq=timer1.freq,duty=motor.motor2_duty,pin=motor.motor2_pin)

motor1 = PWM(tim_1_ch0, freq=timer1.freq,duty=motor.motor1_duty,pin=11)# 电机1, x轴
motor2 = PWM(tim_1_ch1, freq=timer1.freq,duty=motor.motor2_duty,pin=12)# 电机2, y轴

#定义电机占空比控制函数
def motor_control(motor,x,y):           #比如控制舵机也可以在这里写
    val_1 = 0
    val_2 = 0
    if x <= motor.control_x:                    # 若色块当前x坐标小于画面中心,物体在小车左边,向左走
        val_1 = (motor.control_x - x) *0.004375 # 这里算的是与中心相差距离,得出屏幕的相对距离
        control_flag_x = 'left'
        motor.motor1_duty = motor.duty1_center + val_1     #减小电机1的占空比
        #print("x_duty:",motor.motor1_duty)
        yb_uart.write(control_flag_x)

    if x > motor.control_x:                 # 若当前x坐标大于画面中心,物体在小车右边,向左走
        #val_1 = (x - motor.control_x) *0.034375
        val_1 = (x - motor.control_x) *0.0045
        control_flag_x = 'right'
        motor.motor1_duty = motor.duty1_center - val_1     #增大电机1的占空比,现在发现是反的
        #print("x_duty:",motor.motor1_duty)
        yb_uart.write(control_flag_x)

    if y <= motor.control_y:                # 若当前y坐标小于画面中心,物体在小车上边
        #val_2 = (motor.control_y - y) *0.016665
        val_2 = (motor.control_y - y) *0.008465
        control_flag_y = 'forward'
        motor.motor2_duty = motor.duty2_center - val_2
        yb_uart.write(control_flag_y)
        print("y_duty:",motor.motor2_duty)

    if y > motor.control_y:                 # 若当前y坐标大于画面中心,物体在小车下边,向后走
        val_2 = (y - motor.control_y) *0.008465
        control_flag_y = 'backward'
        yb_uart.write(control_flag_y)
        motor.motor2_duty = motor.duty2_center + val_2
        print("y_duty:",motor.motor2_duty)

    #motor.motor1_duty = int(motor.motor1_duty)  # 电机1占空比,转为int,x方向
    #motor.motor2_duty = int(motor.motor2_duty)

while(True):
    clock.tick()
    img = sensor.snapshot()
    lcd.display(img)
    #lcd.rotation(0) # Dock的屏幕有点怪怪的,就这样吧
    #lcd.mirror(True)
    opv_find_blobs(black,1)  #找线!
    motor_control(motor, black.cx, black.cy)

    while(black.cx!=motor.control_x or black.cy!=motor.control_y):  # 不在中心点
        motor1.duty(motor.motor1_duty)  # 将获取到的电机1占空比 装载,x轴
        motor2.duty(motor.motor2_duty)  # y轴
        if (motor.motor1_duty>=13 ):
            motor.motor1_duty = 13
        if (motor.motor2_duty>=8):
            motor.motor2_duty = 8
        if (motor.motor1_duty <=3):
            motor.motor1_duty = 3
        if (motor.motor2_duty<=3):
            motor.motor2_duty = 3       # 3是向上抬头

        if black.cx <= motor.control_x:
            black.cx += 1
        if black.cx > motor.control_x:
            black.cx -= 1
        if black.cy <= motor.control_y:
            black.cy += 1
        if black.cy > motor.control_y:
            black.cy -= 1
        if (black.cx==motor.control_x and black.cy==motor.control_y):
            motor.duty1_center = motor.motor1_duty
            motor.duty2_center = motor.motor2_duty
            break

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值