stm32智能颜色送餐小车(openmv二维码识别+颜色识别+oled显示)

大家好啊,我是情谊,今天我们来介绍一下我最近设计的stm32产品,我们在今年七月份的时候参加了光电设计大赛,我们小队使用的就是stm32的智能送餐小车,虽然止步于省赛,但是还是一次成长的经验吧,那么我也来分享一下我们小队这次的产品设计,希望里面的一些模块可以给你们一点的参考建议。

我先说说我的博客文章的设计吧,我准备的是以模块的方式展示代码,但是文章的最后我会附带我们小队设计的stm32小车的完整代码

接下来我再说说我的小车实现的功能:

1二维码识别,使用openmv扫描对应颜色的二维码后,oled屏幕上显示对应的菜品名称,并且小车识别追踪该颜色物体

2压力传感器感知物体重量,当压力传感器的重量超过一定值后小车才会运动,注意!这个功能和上面的二维码识别并不冲突,上面扫码后openmv只能识别到该颜色,但是小车却不能动,只有压力传感器有示数才会运动

3APP点单,我们小组是使用ESP8266wifi模块制作了一个APP来模拟点单

4温度传感器时刻感知环境温度,这个模块的功能其实就是在送餐途中进行保温使用的

5蜂鸣器播报,客户下单后蜂鸣器会进行鸣叫

6红外光管避障,我们小组并未在避障方面进行过多的功能,所以只有简单的避障功能:小车识别到前方有物体,然后停下来,等到前方没有物体后继续运动

以上就是我的产品的全部功能了

注意注意!!!

我文章末尾上传的代码只有功能1和功能2和功能6的代码,功能3我只能负责给你们说说怎么做,如果实在需要代码,请联系我,这部分代码不是免费的,功能4和功能5的代码不在我的电脑上,所以我就不进行讲解了。

器件端

首先声明一下

本次实验的芯片是基于stm32c8t6

本次实验使用的openmv型号为openmvH7

OpenMV开发环境搭建

OpenMV IDE是用于OpenMV Cam的集成开发环境,具有强大的文本编辑器,调试终端和带有直方图显示的帧缓冲区查看器。

官方下载链接:Download -- OpenMV,截至本文写作时间,最新版本为v4.2.1。

本次实验接口为串口三

代码端

openmv

cs 复制代码
import sensor, image, time
from pyb import UART
from pyb import LED

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)

# 初始化LED灯
led_red = LED(1)
led_green = LED(2)
led_blue = LED(3)

# 初始化UART
uart = UART(3, 9600)

clock = time.clock()

last_qr_color = None

while True:
    clock.tick()
    img = sensor.snapshot()

    # 寻找二维码
    qr_codes = img.find_qrcodes()

    if qr_codes:
        # 获取第一个二维码的颜色信息
        qr_color = qr_codes[0].payload()
        last_qr_color = qr_color
        blobs = None

        if qr_color == "green":
            # 绿色物体识别
            green_threshold = (0, 100, -12, 11, -108, 34)
            blobs = img.find_blobs([green_threshold], pixels_threshold=100, area_threshold=100, merge=True)
            led_green.on()
            led_red.off()
            led_blue.off()

        elif qr_color == "red":
            # 红色物体识别
            red_threshold = (0, 80, 30, 127, 30, 127)
            blobs = img.find_blobs([red_threshold], pixels_threshold=100, area_threshold=100, merge=True)
            led_green.off()
            led_red.on()
            led_blue.off()

        else:
            # 其他颜色处理
            blobs = None
            led_green.off()
            led_red.off()
            led_blue.off()

    else:
        # 如果没有检测到二维码,则继续识别上次记录的颜色
        qr_color = last_qr_color
        blobs = None

        if qr_color == "green":
            # 绿色物体识别
            green_threshold = (30, 100, -64, -8, -32, 32)
            blobs = img.find_blobs([green_threshold], pixels_threshold=100, area_threshold=100, merge=True)
            led_green.on()
            led_red.off()
            led_blue.off()

        elif qr_color == "red":
            # 红色物体识别
            red_threshold = (0, 80, 30, 127, 30, 127)
            blobs = img.find_blobs([red_threshold], pixels_threshold=100, area_threshold=100, merge=True)
            led_green.off()
            led_red.on()
            led_blue.off()

        else:
            # 其他颜色处理
            blobs = None
            led_green.off()
            led_red.off()
            led_blue.off()

    if blobs:
        for blob in blobs:
            img.draw_rectangle(blob.rect())
            img.draw_cross(blob.cx(), blob.cy())
            area = blob.w() * blob.h()
            # 根据颜色修改 area & 0xff 的值
            if qr_color == "green":
                area_low_byte = 0x02
            elif qr_color == "red":
                area_low_byte = 0x01
            data_packet = bytearray([0xb3, 0xb3, blob.cx(), blob.cy(), area >> 8, area_low_byte, 0x5b])
            uart.write(data_packet)
            print("颜色: %s x:%d y:%d 面积:%d" % (qr_color, blob.cx(), blob.cy(), area))

    print(clock.fps())

代码讲解:上面的openmv端代码可以识别信息为"红色"二维码与"绿色"二维码,下面为你们粘贴了二维码图,识别到一个二维码后,openmv转变为识别对应颜色,向单片机发送4个数据,但是有用的只有三个数据,你们可以根据需要删除不需要数据。

红色二维码

绿色二维码

大家可以使用上面的二维码进行实验,也可以修改二维码和openmv识别信息

接下来在stm32端接受openmv发送的信息

Serial.c

复制代码
#include "stm32f10x.h"                  
#include <stdio.h>
#include <stdarg.h>

int openmv[7];
int16_t Num;          
int16_t theta;          
int16_t rho;
int16_t yanse;
int i;


void Usart3_Init(uint32_t Bound)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	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_InitTypeDef USART_InitStructure;
	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_Tx | USART_Mode_Rx;
	USART_Init(USART3,&USART_InitStructure);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
	USART_Cmd(USART3,ENABLE);
}

void Openmv_Data(void)
{
    Num=openmv[2];
    rho=openmv[3];
	theta =openmv[4];
	yanse = openmv[5];
}
 
void Openmv_Receive_Data(int16_t data)
{
	static u8 state = 0;
	if(state==0&&data==0xb3)
	{
		state=1;
		openmv[0]=data;
	}
	else if(state==1&&data==0xb3)
	{
		state=2;
		openmv[1]=data;
	}
	else if(state==2)
	{
		state=3;
		openmv[2]=data;
	}
	else if(state==3)
	{
		state = 4;
		openmv[3]=data;
	}
  else if(state==4)
	{
		state = 5;
		openmv[4]=data;
	} 
	 else if(state==5)
	{
		state = 6;
		openmv[5]=data;
	} 
	else if(state==6)		
	{
        if(data == 0x5B)
        {
            state = 0;
            openmv[6]=data;
            Openmv_Data();
        }
        else if(data != 0x5B)
        {
            state = 0;
            for(i=0;i<7;i++)
            {
                openmv[i]=0x00;
            }           
        }
	}    
	else
		{
			state = 0;
            for(i=0;i<7;i++)
            {
                openmv[i]=0x00;
            }
		}
}


void USART_SendByte(USART_TypeDef* USARTx, char  str)
{
 
		USART_SendData(USARTx, str);
 
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 
	
 
}



void USART3_IRQHandler(void)                	
	{
	u8 com_data;
#if SYSTEM_SUPPORT_OS 		
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) 
		{
			USART_ClearFlag(USART3,USART_FLAG_RXNE);
      com_data = USART3->DR;
			Openmv_Receive_Data(com_data);    
			Openmv_Data();		                	
 		
     } 
#if SYSTEM_SUPPORT_OS 	
	OSIntExit();  											 
#endif
} 

上面由于代码注释出现乱码问题,所以笔者还是建议从下方的链接处查看

Serial.h

复制代码
#ifndef __SERIAL_H
#define __SERIAL_H

#include <stdio.h>
#include "sys.h"
#include "stm32f10x.h"                  




void Usart3_Init(uint32_t Bound);
#endif

main.c

cs 复制代码
#include "stm32f10x.h"                 
#include "delay.h"
#include "OLED.h"
#include "Serial.h"
#include "sys.h"              
#include "stdio.h"
#include "HX711.h"
#include "encoder.h"
extern int16_t Num;     //x     
extern int16_t theta;     //size     
extern int16_t rho;				//y
extern int16_t yanse;	

static int16_t img_width=160;     //cx
static int16_t img_high=120;      //cy
static int16_t img_size=1000;      //size
//50 32 32055
static uint8_t KeyNum;
void OLED_SHOW(void)
{  
	if (yanse == 0x01)
		option = 1;
	if (yanse == 0x02)
		option = 2;
	 
	 	OLED_Refresh_Gram(); 

    if (option == 1)
    {

		OLED_ShowChinese(0,0,4,16,1); 
		OLED_ShowChinese(16,0,5,16,1); 
		OLED_ShowChinese(32,0,6,16,1); 
    }
    else if (option == 2)
    {
		OLED_ShowChinese(0,0,7,16,1); 
		OLED_ShowChinese(16,0,8,16,1); 
		OLED_ShowChinese(32,0,9,16,1); 

    }
	
}

int main(void)
{
	
	
	delay_init(72);         
	LED_Init();                    
	LED=0; 
    0KEY_Init();
	Usart3_Init(9600);          
	OLED_Init();
	KeyNum = Key_GetNum();
	while (1)
	 {
			Led_Flash(50);
			OLED_SHOW();
		
    }
}

oled端的代码我就不在进行书写,大家可以参照我的另一篇文章里讲解了https://mp.csdn.net/mp_blog/creation/editor/141165560

好了,以上就是openmv二维码识别+颜色识别+oled显示的全部代码了,如果有什么问题,欢迎各位在评论区留言,本人看到一定会回消息的,还有一个问题,代码本身是由程序中截取出来的所以可能会出现部分代码出现错误,所以还是建议根据下方提供的链接查源代码,明天我会更新stm32智能颜色送餐小车(红外光管避障)如果本文章对你有用的话,请给一个小小的赞呗,你的赞就是对我的最大的鼓励!谢谢大家!

代码链接处:链接:链接: https://pan.baidu.com/s/1buk_I9_bZ_rIou1iW9v1jA?pwd=2180 提取码: 2180

最后一个需要注意以下,本代码中的pid参数我全部都置零了,请根据自己的小车进行调节!

mmexport1723541008067

相关推荐
电子科技圈3 分钟前
芯科科技出展CES 2026并展出如何加速互联智能的未来
科技·嵌入式硬件·mcu·物联网·iot
点灯小铭5 小时前
基于单片机的多路热电偶温度监测与报警器
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
tianyue10010 小时前
STM32G431 ADC 多个channel 采集
stm32·单片机·嵌入式硬件
longson.11 小时前
怎样避免空间碎片而且高效的分配空间
嵌入式硬件·缓存
清风66666611 小时前
基于单片机的水泵效率温差法测量与报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
焦糖码奇朵、12 小时前
课设:基于Arduino的无线LED开关控制系统
嵌入式硬件·物联网·arduino·信息与通信·信号处理
z203483152012 小时前
定时器练习报告
单片机·嵌入式硬件
zk0012 小时前
内容分类目录
单片机·嵌入式硬件
安生生申13 小时前
STM32 ESP8266连接ONENET
c语言·stm32·单片机·嵌入式硬件·esp8266
广药门徒13 小时前
电子器件烧毁的底层逻辑与避坑指南
单片机·嵌入式硬件