OpenMv通信,循迹小车

该博客介绍了如何使用OpenMV摄像头通过串口发送偏移角度和位移数据到单片机,单片机接收到数据后进行解码并显示。OpenMV端程序通过灰度阈值处理图像,获取直线回归信息,并将负值加100以适应传输,然后利用sscanf函数在单片机端解码并转换回原始数据。单片机端使用STM32的USART3进行初始化配置,设置中断处理接收数据,并对超出100的值进行负值转换。
摘要由CSDN通过智能技术生成

        openmv串口三通过发送偏移角度及偏移位移单片机通过串口三接收并解码并发送到串口一到电脑端查看。

        将负值加一百以更方便发送,单片机接收端通过检测值是否大于一百从而处理数据,关键的一点是sscanf函数的使用。大家如果不清楚的话可以去网上找找资料。

openmv端程序:

THRESHOLD = (0, 19, -112, 65, -87, 79) # Grayscale threshold for dark things...
import sensor, image, time, ustruct
from pyb import LED,UART
import pyb

LED(1).on()
LED(2).on()
LED(3).on()

sensor.reset()
sensor.set_vflip(True)#打开摄像头垂直翻转模式
sensor.set_hmirror(True)#水平镜像模式
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQQVGA) # 80x60 (4,800 pixels) - O(N^2) max = 2,3040,000.
sensor.skip_frames(time = 2000)     # 跳过2帧
clock = time.clock()                # to process a frame sometimes.

uart = UART(3,115200)   #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters

while(True):
    clock.tick()
    img = sensor.snapshot().binary([THRESHOLD])
    line = img.get_regression([(100,100)], robust = True)
    if (line):
        rho = abs(line.rho())-img.width()/2
        if line.theta()>90:
            theta = line.theta()-180
        else:
            theta = line.theta()
        img.draw_line(line.line(), color = 127)
        if(theta < 0):
            theta = abs(theta) + 100
        theta = str(round(theta))
        if(rho < 0):
            rho = abs(rho) + 100
        rho = str(round(rho))
        uart.write("[")
        uart.write(theta)
        uart.write(",")
        uart.write(rho)
        uart.write("]")
        print(theta,rho)  #theta偏移角度 rho偏移位移
        time.sleep_ms(50)

单片机端解码程序:

#include "openmv.h"

void clear_RxBuffer(u8 *buffer);

void USART3_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE );
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  
	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART3, &USART_InitStructure);
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断
	USART_Cmd(USART3, ENABLE);                    //使能串口 
}

int theta, rho;

void USART3_IRQHandler(void) 
{
	char a;
	uint8_t com_data; //接收一个字节数据的临时变量
	static uint8_t RxCounter1=0;//数据缓冲区的索引
    static uint8_t RxBuffer1[10]={0};//存放数据的接收缓存区

	if( USART_GetITStatus(USART3 ,USART_IT_RXNE) != RESET)  	   //接收中断  
	{
		USART_ClearITPendingBit(USART3 ,USART_IT_RXNE);   //清除中断标志
		com_data = USART_ReceiveData(USART3);
		if(com_data == ']')
		{
			if(RxBuffer1[0] == '[')
			{
				sscanf((const char*)RxBuffer1, "%c%d,%d", &a, &theta, &rho);
				if(theta > 100)
				{
					theta = -(theta - 100);
				}
				if(rho > 100)
				{
					rho = -(rho - 100);
				}
				printf("rheta:%d,  rho:%d\n", theta, rho);
				clear_RxBuffer(RxBuffer1);
			}
			RxCounter1 = 0;
		}
		else
		{
			RxBuffer1[RxCounter1 ++] = com_data;
		}
		if(RxCounter1 > 10)
		{
			RxCounter1 = 0;
			clear_RxBuffer(RxBuffer1);
		}
	}
	
}

void clear_RxBuffer(u8 *buffer)
{
	u8 i;
	for(i = 0; i < 10; i ++)
	{
		buffer[i] = '\0';
	}
}

  • 0
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chuqing16

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值