全国第九届光电竞赛智能垃圾分拣小车(全部思路分享,代码分享)基于stm32与openmv

前言

从今年3月份开始得知要参加光电比赛,对于一个新手小白来说,确实有些紧张与压力。但万事开头难,不会咱们就去做,大不了从头开始,总比停滞不前好多了吧。最终在我与我小组不断的努力中,获得了省赛一等奖与国赛三等奖的不错成绩。在此,我将分享我制作过程中的点点滴滴,希望阅读到我的作品的各位伙伴们能有所收获。

购买物品

此次设计的光电垃圾分拣小车,在最开始时,我们并不知道垃圾是定点放置,起初我们都以为垃圾是随机分布的,于是开始的设计是通过超声波进行寻找物体。后来到比赛时才发现别的小组用的是定点寻物,唉,就比他们慢了很多,但无所谓了。

小车底盘购买

小车我们用的是众灵科技的C6小车,电机是减速370电机,直接用总线连接用PWM控制,很方便。

摄像头购买

摄像头采用的是星瞳科技的openmv7plus。这个摄像头是开源的,可以进行串口通信。

超声波购买

超声波采用的是SR超声波模块,开始买了一个,最后比赛时用了四个。

机械臂购买

机械臂也是在众灵购买的,用的是A款大夹子,我们对夹子进行了自主的改装,使得它可以进行抓取电池等小物品,也可以抓取瓶子等大物体。

设计思路

总体设计思路如下:
先通过超声波模块进行寻找物体,直到在物体面前18厘米处停下来。通过串口发送信息到摄像头,摄像头会进行神经网络识别,识别具体是什么物体。当识别完毕后,会发送串口信息到stm32控制其进行抓取物体,抓取成功后会在此发送信息到摄像头,接收到串口信息后,摄像头会根据开始识别的物体信息,寻找对应的色块,将色块的坐标信息发送给stm32,控制stm32进行小车的运动。当小车运动到色域足够大时,会发送信息到stm32控制小车放下物体。

代码分享

此代码全部为我自己亲手所写的内容。一个人写了将近1000行的摄像头代码。从0到1。我这次是真的体会到了。

stm32串口通信

串口是核心,只要是学32,串口必须掌握!!!
串口初始化:

void tb_usart_init(void) {
	tb_usart1_init(115200);
	uart1_open();
	
	tb_usart2_init(115200);
	uart2_open();
	
	tb_usart3_init(115200);
	uart3_open();
	
	tb_interrupt_open();
	return;
}

串口优先级:

void tb_usart1_init(u32 rate) {  
    GPIO_InitTypeDef GPIO_InitStructure;  
    USART_InitTypeDef USART_InitStructure; 
	USART_ClockInitTypeDef USART_ClockInitStructure; 	
    NVIC_InitTypeDef NVIC_InitStructure;  
  
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);  
    USART_DeInit(USART1);  
    /* Configure USART Tx as alternate function push-pull */  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
      
    /* Configure USART Rx as input floating */  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
  
    USART_InitStructure.USART_BaudRate = rate;  
    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_ClockInitStructure.USART_Clock = USART_Clock_Disable;  
    USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;  
    USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;  
    USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;  
    USART_ClockInit(USART1, &USART_ClockInitStructure);  
	USART_Init(USART1, &USART_InitStructure );   
  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure); 
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	
//	USART_ITConfig(USART1, USART_IT_PE, ENABLE);
//	USART_ITConfig(USART1, USART_IT_ERR, ENABLE);

	USART_Cmd(USART1, ENABLE);  
}  

串口中断函数:

int USART1_IRQHandler(void) {
	u8 sbuf_bak;
	static u16 buf_index = 0;

	if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET) {
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);		
		sbuf_bak = USART_ReceiveData(USART1); 
		//uart1_send_byte(sbuf_bak);
		if(uart1_get_ok)return 0;
		if(sbuf_bak == '<') {
			uart1_mode = 4;
			buf_index = 0;
		}else if(uart1_mode == 0) {
			if(sbuf_bak == '$') {			//命令模式 $XXX!
				uart1_mode = 1;
			} else if(sbuf_bak == '#') {	//单舵机模式	#000P1500T1000! 类似这种命令
				uart1_mode = 2;
			} else if(sbuf_bak == '{') {	//多舵机模式	{#000P1500T1000!#001P1500T1000!} 多个单舵机命令用大括号括起来
				uart1_mode = 3;
			} else if(sbuf_bak == '<') {	//保存动作组模式	<G0000#000P1500T1000!#001P1500T1000!B000!> 用尖括号括起来 带有组序号
				uart1_mode = 4;
			} 
			buf_index = 0;
		}
		
		uart_receive_buf[buf_index++] = sbuf_bak;
				
		if((uart1_mode == 4) && (sbuf_bak == '>')){
			uart_receive_buf[buf_index] = '\0';
			uart1_get_ok = 1;
		} else if((uart1_mode == 1) && (sbuf_bak == '!')){
			uart_receive_buf[buf_index] = '\0';
			uart1_get_ok = 1;
		} else if((uart1_mode == 2) && (sbuf_bak == '!')){
			uart_receive_buf[buf_index] = '\0';
			uart1_get_ok = 1;
		} else if((uart1_mode == 3) && (sbuf_bak == '}')){
			uart_receive_buf[buf_index] = '\0';
			uart1_get_ok = 1;
		}    

		if(buf_index >= UART_BUF_SIZE)buf_index = 0;

	}
	
	//发送中断 用前在初始化的时候请打开
	//if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {   
		//USART_SendData(USARTy, TxBuffer1[TxCounter1++]);
	//}   
	return 0;
}

stm32超声波模块编写

超声波有四个:
初始化:

void setup_csb() {
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA, ENABLE);  
	
	//初始化超声波IO口 Trig PB0  Echo PA2
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_Init(GPIOB, &GPIO_InitStructure); 	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
	GPIO_Init(GPIOA, &GPIO_InitStructure); 	
	
	//初始化超声波定时器
	TIM3_Int_Init(30000, 71);
}

编写条件:

void csb_Delay_Us(uint16_t time)  //延时函数
{ 
	uint16_t i,j;
	for(i=0;i<time;i++)
  		for(j=0;j<9;j++);
}
/*************************************************************
函数名称:get_csb_value()
功能介绍:采集超声波数据
函数参数:无
返回值:  采集的数据  
*************************************************************/
u16 get_csb_value(void) {
	u16 csb_t;
	Trig(1);
	csb_Delay_Us(20);
	Trig(0);
	while(Echo() == 0);      //等待接收口高电平输出
	TIM_SetCounter(TIM3,0);//清除计数
	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
	while(Echo() == 1);
	TIM_Cmd(TIM3, DISABLE);  //使能TIMx外设      
	csb_t = TIM_GetCounter(TIM3);//获取时间,分辨率为1US
	//340m/s = 0.017cm/us
	if(csb_t < 25000) {
//		sprintf((char *)cmd_return, "csb_time=%d\r\n", (int)(csb_t*0.17));
//		uart1_send_str(cmd_return);
		csb_t = csb_t*0.017;
		return csb_t;
	}
	return 0;
}

进行判断:

void zhuixun(void) {
	static u32 systick_ms_bak = 0;
	
	int adc_csb;
	if(group_do_ok == 0)return;

	//每20ms计算一次
	while(1){
//				loop_sensor();	
			get_csb_value();
		 get_adc_csb_middle();
	if(millis() - systick_ms_bak > 50) {
		systick_ms_bak = millis();
		adc_csb = get_adc_csb_middle();//获取a0的ad值,计算出距离
// 		sprintf((char *)uart_receive_buf, "adc_csb = %d\r\n", adc_csb);
// 		uart1_send_str(uart_receive_buf);
		if(adc_csb >100)
		{
			car_set(850,-850);
		}
//		if(adc_csb < 20) {//距离10cm左右就夹取
//			car_set(0,0);
//			beep_on_times(1, 100);
//			parse_cmd((u8 *)"$DGT:1-8,1!");
//			break ;
//		} 
			if((adc_csb > 19.5) && (adc_csb <95)) {
			car_set (400,400);}
	
	if(adc_csb<18){
	car_set (-300,-300);
	}
			if((adc_csb > 18)&&(adc_csb < 19.5)) {//距离10cm左右就夹取
			car_set(0,0);
			
	//		beep_on_times(1, 100);
				bianliang=1;

			break ;
}
		} 
			//tb_usart1_send_str("0xaa 0x01 0xbb");
		
			
	}
	//parse_cmd((u8 *)"$DGT:6-8,1!");
}

openmv核心代码

神经网络采用官网教程进行操作。

串口通信

import sensor, image, time, os, tf
from pyb import UART
import json
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)
net = "trained.tflite"
labels = [line.rstrip('\n') for line in open("labels.txt")]
clock = time.clock()
uart = UART(3, 115200,timeout_char=1000)
uart.init(115200, bits=8, parity=None, stop=1)
while(True):
    bool_flag_1=False
    if uart.any():
        buff = [range(1000)]
        buff = uart.readline().decode()

进行判断并且分级操作

img = sensor.snapshot()
            for obj in tf.classify(net, img, min_scale=1.0, scale_mul=0.8, x_overlap=0.5, y_overlap=0.5):
                bool_flag_2=False
                print("**********\nPredictions at [x=%d,y=%d,w=%d,h=%d]" % obj.rect())
                img.draw_rectangle(obj.rect())
                predictions_list = list(zip(labels, obj.output()))
                if bool_flag_1==True:
                    bool_flag_1=False
                    break
                for i in range(len(predictions_list)):
                    print("%s = %f" % (predictions_list[i][0], predictions_list[i][1]))
                    nums = [predictions_list[0][1],predictions_list[1][1],predictions_list[2][1],predictions_list[3][1],predictions_list[4][1]]
                    max_num = 0
                    for j in nums:
                        max_num = j if j >= max_num else max_num
                    if bool_flag_2==True:
                        bool_flag_1=True
                        bool_flag_2=False
                        break
                    if predictions_list[i][1]>=max_num:
                        data = i
                        if data==00:
                            sensor.reset()
                            sensor.set_pixformat(sensor.RGB565)
                            sensor.set_framesize(sensor.QQVGA)
                            sensor.skip_frames(10)
                            sensor.set_auto_whitebal(False)
                            clock = time.clock()
                            black_rhreshold =(6, 63, -64, 14, -50, 31)
                            red_rhreshold = (17, 47, 3, 96, -94, 69)
                            size_threshold = 5000
                            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
                            while(True):
                                clock.tick()
                                img = sensor.snapshot()
                                blobs = img.find_blobs([red_rhreshold])
                                if blobs:
                                    max_blob = find_max(blobs)
                                    img.draw_cross(max_blob.cx(),max_blob.cy())
                                    img.draw_rectangle(max_blob.rect())
                                    W=max_blob.w()
                                    H=max_blob.h()
                                    S=int(W*H)
                                    X=int(max_blob.cx()-img.width()/2)
                                    Y=int(max_blob.cy()-img.height()/2)
                                    print("x轴偏移坐标:",X)
                                    print("Y轴偏移坐标:",Y)
                                    print("S面积",S)
                                    if 10<X and (S<10000 and S>8000):
                                        b_output = 300
                                        a_output = 50
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1750)+'T0000!'
                                        qi = '#007P'+str(1250)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if -10>X and (S<10000 and S>8000):
                                        b_output = 300
                                        a_output = -50
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1750)+'T0000!'
                                        qi = '#007P'+str(1250)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if (10>X and X>-10) and (S<10000 and S>8000):
                                        b_output = 300
                                        a_output = 0
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1750)+'T0000!'
                                        qi = '#007P'+str(1250)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if 10<X and (S<8000 and S>5000):
                                        b_output = 300
                                        a_output = 100
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1800)+'T0000!'
                                        qi = '#007P'+str(1200)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if -10>X and (S<8000 and S>5000):
                                        b_output = 300
                                        a_output = -100
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1800)+'T0000!'
                                        qi = '#007P'+str(1200)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if (10>X and X>-10) and (S<8000 and S>5000):
                                        b_output = 300
                                        a_output = 0
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1800)+'T0000!'
                                        qi = '#007P'+str(1200)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if 10<X and (S<5000 and S>3000):
                                        b_output = 300
                                        a_output = 200
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1900)+'T0000!'
                                        qi = '#007P'+str(1100)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if -10>X and (S<5000 and S>3000):
                                        b_output = 300
                                        a_output = -200
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1900)+'T0000!'
                                        qi = '#007P'+str(1100)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if (10>X and X>-10) and (S<5000 and S>3000):
                                        b_output = 300
                                        a_output = 0
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1900)+'T0000!'
                                        qi = '#007P'+str(1100)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if 10<X and (S<3000 and S>0):
                                        b_output = 300
                                        a_output = 300
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(2000)+'T0000!'
                                        qi = '#007P'+str(1000)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if -10>X and (S<3000 and S>0):
                                        b_output = 300
                                        a_output = -300
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(2000)+'T0000!'
                                        qi = '#007P'+str(1000)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if (10>X and X>-10) and (S<3000 and S>0):
                                        b_output = 300
                                        a_output = 0
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(2000)+'T0000!'
                                        qi = '#007P'+str(1000)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if -10>X and (S>10000):
                                        b_output = 300
                                        a_output = 100
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1250)+'T0000!'
                                        qi = '#007P'+str(1750)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if 10>X and (S>10000):
                                        b_output = 300
                                        a_output = -100
                                        qian = '{#002P'+str (int(1500+a_output))+'T0000!'
                                        liu = '#006P'+str(1250)+'T0000!'
                                        qi = '#007P'+str(1750)+'T0000!}'
                                        data = bytearray(qian+liu+qi)
                                        uart.write(data)
                                    if  -10<X<10 and S>10000:
                                        data = bytearray('{#006P1500T0000!#007P1500T0000!#002P1500T0000!}')
                                        dataxia = bytearray('$XIA!')
                                        uart.write(data)
                                        time.sleep_ms(500)
                                        uart.write(dataxia)
                                        bool_flag_2=True
                                        break
                                else:
                                    data = bytearray('{#006P2300T0000!#007P2300T0000!#002P1500T0000!}')
                                    uart.write(data)

代码太多,核心代码我已经在此列出。总之我相信各位大佬肯定可以看懂吧。欢迎各位大佬评论留言。

源码

最后我将stm32与openmv完整代码发到这里,有需要的可以下载。谢谢
代码下载

版权声明:本文为CSDN博主「C饭王」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45253310/article/details/119208371

C饭王

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

Keil MDK5 STM32F103C8T6开发环境配置

Windows下使用Keil MDK5进行stm32f103c8t6的开发和编译, 配合ST-LINK工具进行烧录, 使用原生(非HAL)的方式. 所需硬件 stm32f103系列开发板 stm32f103c8t6核心板 参数 ARM 32-b

基于STM32的室内环境监测系统

设计简介: 本设计是基于单片机的室内环境监测器,主要实现以下功能: 可实现LCD1602显示环境数据实时监测一氧化碳、甲烷、烟雾值空气质量大于各自限值报警,并通过TTS报警 标签&#x

Arduino与Proteus仿真实例-DHT11温度湿度传感器驱动仿真

DHT11温度湿度传感器驱动仿真 DHT11 是一款基本的超低成本数字温度和湿度传感器。 它使用电容式湿度传感器和热敏电阻来测量周围的空气,并在数据引脚上吐出数字信号(不需要模拟输入引脚)。 它使用起来相当简单,但需要仔细定时来抓取数据。

基于stm32f407的示波器

一.设计要求 二.整体思路 硬件部分主要负责电压的缩放以及垂直灵敏度的控制,因为stm32的大部分引脚最高输入电压为3.3v,而要求的电压需要50v,需要进行电压缩放。 软件部分主要负责方波的实现&#x