全国第九届光电竞赛智能垃圾分拣小车(全部思路分享,代码分享)基于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饭王

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

暂无评论

发表评论

相关推荐

基于STM32的指纹密码锁

设计简介: 本设计是基于单片机的指纹密码锁,主要实现以下功能: 矩阵按键输入密码,并通过按键显示*号可通过按键或手机开门密码可通过按键进行开门可通过蓝牙模块连接手机进行开门可通过指纹进

定时器触发STM32 ADC的采样转换示例

开发板:STM32F446 Nucleo开发板IDE:  keil MDK初始化配置工具:stm32cubeMx例程内容:通过定时器触发ADC规则通道及注入通道的模数转换工作。下面基于STM32CubeMx进行些必要