STM32 + OPENMV 实现二维云台追踪小球

视频链接:Openmv+stm32 云台视觉追踪_哔哩哔哩_bilibili

二维云台是淘宝上买的,用的是数字舵机,精度还可以,主控为STM32F103C8T6,单片机与openmv之间使用串口通信,通信格式采用json字符串。

程序逻辑很简单,openmv识别色块,持续发送小球的相对于以画面中心为原点的坐标系的坐标,由stm32进行pid控制,使小球保持在画面中心。

由于程序非常简单,所以pid直接放在空闲中断里进行。

舵机部分:

#include "servo.h"
#include "tim.h"

double roll_deg = 0,pitch_deg = 0;

void roll_angle(double deg)	//-135~135 -- 500~2500
{
	double temp = ((deg-(-135.0))/270.0)*2000 + 500;
	__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,temp);
}

void pitch_angle(double deg)	//-90~90 -- 500~2500
{
	double temp = ((deg-(-90.0))/180.0)*2000 + 500;
	__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,temp);
}

PID部分: 

#include "PID.h"
#include "usart.h"
#include "servo.h"

extern double roll_deg,pitch_deg;
extern int pos_x,pos_y;

double p_roll = 0.03;
double d_roll = 0.11;

double p_pitch = 0.03;
double d_pitch = 0.07;

double error_roll[2]; //0-->before,1-->current
double error_pitch[2];

void pid_calc(void)
{
	error_roll[1] = pos_x;
	error_pitch[1] = pos_y;
	
	roll_deg = roll_deg - (error_roll[1]*p_roll + (error_roll[1] - error_roll[0])*d_roll);
	pitch_deg = pitch_deg - (error_pitch[1]*p_pitch + (error_pitch[1] - error_pitch[0])*d_pitch);
	
	Limit(&roll_deg, 135, -135);
	Limit(&pitch_deg, 90, -90);
	if(pos_x == 1000 && pos_y == 1000)
	{
		roll_deg = 0;
		pitch_deg = 0;
	}
	
	roll_angle(roll_deg);
	pitch_angle(pitch_deg);
	
	error_roll[0] = error_roll[1];
	error_pitch[0] = error_pitch[1];
}

void Limit(double *val, double max, double min)
{
	if(*val < min) *val = min;
	if(*val > max) *val = max;
}


主程序(空闲中断):

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart->Instance == USART1)
	{
		Jansson1_Analysis((char*)data);
		memset(data, 0, 100);
		USART2_Printf("x:%d,y:%d\n",pos_x,pos_y);
		
		pid_calc();
	}
}

Openmv部分:

import sensor
from machine import UART
import json
import display
import image

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)     #320x240
sensor.skip_frames()
sensor.set_auto_whitebal(False)
sensor.set_hmirror(True)
sensor.set_vflip(True)
sensor.set_transpose(False)

uart = UART(1,115200)
pos_x = 0
pos_y = 0
green_thresholds = (0, 96, -42, -9, -8, 37)
cnt = 0

def find_Max(blobs):       
    max_size = 0
    for blob in blobs:
        if blob.w()*blob.h() > max_size:
            max_blob = blob
            max_size = blob.w()*blob.h()
            return max_blob

lcd = display.SPIDisplay()

while True:

    img = sensor.snapshot()

    blobs = img.find_blobs([green_thresholds],pixels_threshold=3000)
    if blobs: #必须加if,如果find_blobs返回none则会出错
        blob = find_Max(blobs)
        pos_x = blob.cx() - 160    //转换为画面中心为原点的坐标
        pos_y = 120 - blob.cy()
        img.draw_rectangle(blob.rect())
    else:
        cnt += 1
        if cnt > 10:
            pos_x = 0
            pos_y = 0
            cnt = 0
    lcd.write(img,hint=image.ROTATE_180)
    str = {"pos_x":pos_x,"pos_y":pos_y}
    uart.write(json.dumps(str))

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值