El programa de persecución de bolas pequeñas K210 se comunica con la placa del sistema mínima STM32 (autoaprendizaje)

Primero aprendí OPENMV y luego lo extendí a K210. (Principalmente porque no he comprado una pantalla para OPENMV, pero K210 la tiene). En el sitio web oficial de OPENMV, hay funciones relacionadas con la persecución de bolas pequeñas, pero se depura con una microcomputadora de un solo chip OPENMV. El código fuente relevante encontrado en Internet encontró que la velocidad de fotogramas era muy lenta después de cargarlo en OPENMV.

El requisito de la formación escolar es hacer un coche de equilibrio que pueda perseguir un objeto determinado. El mecanismo de mi coche está controlado por STM32F1Z8T6, y K210 reconoce y transmite datos en tiempo real.

1. Mediante la función img.draw_rectangle(b[0:4]), puede obtener las coordenadas del eje X del punto central en el marco rectangular del objetivo dibujado y el tamaño del marco rectangular SIZE. El primero de estos dos datos se puede usar para juzgar el anillo de dirección, y el último se puede usar para juzgar hacia adelante y hacia atrás.

          x_pos = b[5]#
          Tamaño de la posición central = b.area()

A través de pruebas experimentales, obtuve X: rango 2~320, TAMAÑO: 2000~15000 

2. Sin embargo, K210 envía una cadena a 32 y la cantidad de dígitos en la cadena es incierta, lo que da como resultado que la longitud de la matriz almacenada por 32 para la cadena recibida sea incierta y los datos no se puedan convertir normalmente.

Para comodidad de uso, lo modificamos en la función de envío de K210.

Coaccionar cadenas X y SIZE a números de dígitos fijos (en el entorno PYthon)

          X = '%03d' % x_pos
          S = '%05d' % Tamaño

Y configure el encabezado del marco enviado y la cola del marco en los datos finales enviados DATOS

 DATOS = 'x' + X + S + 's'

La situación anterior es cuando el K210 've' el objetivo.

3, ¿Qué pasa si no se encuentra el objetivo?

lo hago así:

Déle directamente X = valor objetivo; TAMAÑO = valor objetivo; envíelo a 32 y realice el cálculo PID respectivamente

En el programa PID, X es el valor medido del anillo de dirección TAMAÑO es el valor medido del anillo de seguimiento;

Cuando el valor medido = el valor esperado, el PID es equivalente a ser igual todo el tiempo (mi comprensión sesgada es no calcular)

En este punto, solo quedan el anillo vertical y el anillo de velocidad.

4. Volviendo a la pregunta anterior, ¿de qué sirve usar la pantalla del K210?

Para una depuración mejor y más conveniente, mostramos directamente los datos de X y TAMAÑO en la pantalla LCD.

          img.draw_string(2,2, ("X:%03d" %(b[5])), color=(255,255,255), escala=2)
          img.draw_string(2,25, ("S:%04d" % (b.área())), color=(255,255,255), escala=2)

De esta forma será mucho más cómodo ajustar la P en el PID del lazo de dirección y el lazo de persecución.

Pon el código fuente arriba: (para K210 con pantalla)

import sensor, lcd, time
import sensor, time
from machine import UART,Timer
from fpioa_manager import fm
from Maix import GPIO
from fpioa_manager import fm
fm.register(12, fm.fpioa.GPIO0)
LED_B = GPIO(GPIO.GPIO0, GPIO.OUT) #构建LED对象
LED_B.value(0) #点亮LED
#摄像头初始化
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1) #后置模式,所见即所得
sensor.run(1)
sensor.skip_frames(30)
from machine import UART,Timer
from fpioa_manager import fm

#映射串口引脚
fm.register(7 , fm.fpioa.UART1_RX, force=True)
fm.register(30, fm.fpioa.UART1_TX, force=True)

#初始化串口
uart = UART(UART.UART1, 115200, read_buf_len=4096)
#lcd初始化
lcd.init()

clock=time.clock()


color_threshold = (23, 100, 31, 51, 6, 43)
size_threshold = 2000
max_Size = 10
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

LED_B.value(0) #点亮LED
while(1):
    clock.tick()
    img = sensor.snapshot()
    blobs = img.find_blobs([color_threshold],area_threshold=50,pixels_threshold=50)
    if blobs:
      #for b in blobs:
          b = find_max(blobs)
          img.draw_rectangle(b[0:4])  # circle
          img.draw_cross(b[5], b[6], color=(0, 0, 255))
          x_pos = b[5]#中心位置
          Size = b.area()
          X = '%03d' % x_pos
          S  = '%05d' % Size
          DATA = 'x' + X + S + 's'
          img.draw_string(2,2, ("X:%03d" %(b[5])), color=(255,255,255), scale=2)
          img.draw_string(2,25, ("S:%04d" %(b.area())), color=(255,255,255), scale=2)
          uart.write(DATA)
          print(DATA)
    else
          uart.write('x')
          uart.write('1')
          uart.write('6')
          uart.write('0')
          uart.write('0')
          uart.write('2')
          uart.write('0')
          uart.write('0')
          uart.write('0')
          uart.write('s')
          img.draw_string(2,2, ("X:%03d" %(160)), color=(255,255,255), scale=2)
          img.draw_string(2,25, ("S:%04d" %(2000)), color=(255,255,255), scale=2)
    lcd.display(img)     #LCD显示图片

En la función anterior, encontraremos que se define una función: find max

¿Por qué definir esta función?

Porque cuando pidamos encontrar el bloque de color de destino más grande, enmárquelo. De lo contrario, habrá muchos puntos de destino pequeños. Múltiples rectángulos de destino causarán saltos inusuales en el valor enviado por el terminal de puerto serie.

Lo siguiente es para OPENMV sin pantalla:

Hay algunas diferencias entre OPENMV y K210 en que:

(1) Configuración del puerto serie El puerto serie de OPENMV es fijo y no requiere asignación de pines, pero K210 sí.

(2) En OPENMV, el bloque de color más grande se puede determinar directamente a través de Bolb[], y no es necesario establecer la función de búsqueda máxima.

OPENMV se modifica en el programa de rutina en el sitio web oficial (garantice la velocidad de fotogramas, no deje que se quede atascado así)

uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1, timeout_char=1000) # 使用给定参数初始化

# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are
# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the
# camera resolution. "merge=True" merges all overlapping blobs in the image.

while(True):
    clock.tick()
    img = sensor.snapshot()
    for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):
        # These values depend on the blob not being circular - otherwise they will be shaky.
        if blob.elongation() > 0.5:
            img.draw_edges(blob.min_corners(), color=(255,0,0))
            img.draw_line(blob.major_axis_line(), color=(0,255,0))
            img.draw_line(blob.minor_axis_line(), color=(0,0,255))
        # These values are stable all the time.
        #画框
        img.draw_rectangle(blob.rect())
        #画十字
        img.draw_cross(blob.cx(), blob.cy())
        # Note - the blob rotation is unique to 0-180 only.
        #特征点识别
        img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
        #返回x轴中心点位置,blob.cx() 返回色块的外框的中心x坐标(int),也可以通过blob[5]来获取
        x = blob[5]
        #blob.area() 返回色块的外框的面积。应该等于(w * h)
        s = blob.area()
        #发送数据
        #data = bytearray([0x11,x,s,0x00])
        X = '%03d'%(x)
        S = '%05d'%(s)
        data = 'x' + X  + S+ 's'
        #串口发送
        uart.write(data)
   # print(clock.fps())
        print(data)

Supongo que te gusta

Origin blog.csdn.net/qq_60043905/article/details/125655140
Recomendado
Clasificación