一种检测有无佩戴安全帽的装置

目录

目录

一、预想功能

二、系统框架

三、硬件介绍

四、软件介绍

1、K210程序

2、CH32V307程序

串口接收配置

中断配置

语音模块函数

PWM初始化配置

接收数据进行播报

五、实际效果

识别时MaixBit开发板外接2.4寸显示屏观察识别结果

完整视频演示


一、预想功能

基于RISC-V MCU CH32V307开发板和以K210作为核心单元的MaixBit开发板所开发的装置,该装置运行时旋转,他可以通过判断是否检测到人脸,如若检测到人脸便判断是否佩戴了安全帽,通过串口发送数据到CH32V307,CH32V307通过PWM输出驱动电机停止旋转并串口发送数据包到syn6288语音模块播报检测结果。

二、系统框架

 

三、硬件介绍

 

MaixBit开发板:其以K210作为核心单元,由其进行人脸识别,在识别到人脸的基础上判断是否识别到了安全帽,并通过比较人脸与安全帽的xy坐标判断其位置是否为佩戴状态,通过结果发送相应数据给到 RISC-V MCU CH32V307开发板 。

RISC-V MCU CH32V307开发板:接收MaixBit开发板所发送过来的数据,运行时输出PWM控制电机旋转,接收到数据后输出PWM控制电机停止旋转并通过数据不同发送数据包控制syn6288语音模块播报不同识别结果。

Sipeed 2.4寸显示屏:外接MaixBit开发板,可以实时显示摄像头识别检测的结果。

l298n:电机驱动模块,接收RISC-V MCU CH32V307开发板的pwm信号来控制电机旋转的速度。

LM2596S可调降压模块:将电池电压降为5V供给CH32V307与K210使用。

SYN6288语音模块:接收由开发板发送过来的数据包,进行不同内容的语音播报。

四、软件介绍

1、K210程序

import sensor, image, lcd, time
import KPU as kpu
import gc, sys
from machine import UART
from Maix import GPIO
from fpioa_manager import fm
import utime,ustruct


input_size = (224, 224)
labels = ['1', '2']
anchors = [2.09, 1.66, 0.63, 0.56, 0.47, 0.41, 1.44, 1.12, 0.97, 0.91]

fm.register(GPIO.GPIOHS9,fm.fpioa.UART2_TX) #串口A发送
fm.register(GPIO.GPIOHS10,fm.fpioa.UART2_RX)
fm.register(GPIO.GPIOHS7,fm.fpioa.UART1_TX)
fm.register(GPIO.GPIOHS8,fm.fpioa.UART1_RX)

uart_A = UART(UART.UART2, 115200, 8, None, 1, timeout=1000, read_buf_len=4096)#配置串口A
uart_B = UART(UART.UART1, 115200, 8, 0, 1, timeout=1000, read_buf_len=4096)
data1 = 0x02
data2 = 0x03
n = 0

def lcd_show_except(e):
    import uio
    err_str = uio.StringIO()
    sys.print_exception(e, err_str)
    err_str = err_str.getvalue()
    img = image.Image(size=input_size)
    img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
    lcd.display(img)

def main(anchors, labels = None, model_addr="/sd/m.kmodel", sensor_window=input_size, lcd_rotation=0, sensor_hmirror=False, sensor_vflip=True):
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing(sensor_window)
    sensor.set_hmirror(sensor_hmirror)
    sensor.set_vflip(sensor_vflip)
    sensor.run(1)
    global n

    lcd.init(type=1)
    lcd.rotation(lcd_rotation)
    lcd.clear(lcd.WHITE)

    if not labels:
        with open('labels.txt','r') as f:
            exec(f.read())
    if not labels:
        print("no labels.txt")
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "no labels.txt", color=(255, 0, 0), scale=2)
        lcd.display(img)
        return 1
    try:
        img = image.Image("startup.jpg")
        lcd.display(img)
    except Exception:
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "loading model...", color=(255, 255, 255), scale=2)
        lcd.display(img)

    try:
        task = None
        task = kpu.load(model_addr)
        kpu.init_yolo2(task, 0.8, 0.6, 5, anchors) # threshold:[0,1], nms_value: [0, 1]
        while(True):
            img = sensor.snapshot()
            t = time.ticks_ms()
            objects = kpu.run_yolo2(task, img)
            t = time.ticks_ms() - t
            uart_A.write(chr(data1))
            #uart_B.write(chr(data2))
            if objects:    #识别到目标
              for obj in objects:
               pos = obj.rect()
               a = pos[1]   #定义目标坐标
               if obj.classid()==1:
                 if objects:
                  for obj in objects:
                   pos = obj.rect()
                   b = pos[1]
                   if obj.classid() == 1:
                    n =n+1  #计数识别到人脸的次数
                    if n ==8:
                     uart_A.write(chr(obj.classid())) #发送目标代号
                     n=0
                   else:
                    if a-b<35:  #比较坐标位置
                     n=0
                     uart_A.write(chr(data2))
               img.draw_rectangle(pos)
               img.draw_string(pos[0], pos[1], "%s : %.2f" %(labels[obj.classid()], obj.value()), scale=2, color=(255, 0, 0))
            img.draw_string(0, 200, "t:%dms" %(t), scale=2, color=(255, 0, 0))
            lcd.display(img)
    except Exception as e:
        raise e
    finally:
        if not task is None:
            kpu.deinit(task)


if __name__ == "__main__":
    try:
        # main(anchors = anchors, labels=labels, model_addr=0x300000, lcd_rotation=0)
        main(anchors = anchors, labels=labels, model_addr="/sd/model-24873.kmodel")
    except Exception as e:
        sys.print_exception(e)
        lcd_show_except(e)
    finally:
        gc.collect()

2、CH32V307程序

串口接收配置

void USART2_Printf_Init(uint32_t baudrate)
{

  GPIO_InitTypeDef  GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;


  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能串口2时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟


  USART_DeInit(USART2);


  /* USART2 TX-->A.2   RX-->A.3 */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;              //设置PA2为复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //设置PA3为浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  USART_InitStructure.USART_BaudRate = baudrate;                 //设置串口波特率
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //字长为8位数据格式
  USART_InitStructure.USART_StopBits = USART_StopBits_1;       //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(USART2, &USART_InitStructure);                    //初始化串口


  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;      //抢占优先级为1
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;           //子优先级为1
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //IRQ通道使能
  NVIC_Init(&NVIC_InitStructure);                              //中断优先级初始化


  USART_Cmd(USART2, ENABLE);                                   //使能串口
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);               //开启中断

}

中断配置

u16  a;
void USART2_IRQHandler(void)
{
//    static  u16 a;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //中断产生
    {
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);      //清除中断标志
        a = USART_ReceiveData(USART2);                 //接收数据
    }
}

语音模块函数

void SYN6288(USART_TypeDef * pUSARTx,char * str)
{
        char * p = str;
        int len = 0,check=0xFD,k;

        while( *p++ != 0 )
        {
                len++;
        }

        len+=3;

        USART3_SendByte(USART3,0xFD);   //发送帧头
        USART3_SendByte(USART3,len >>8);
        USART3_SendByte(USART3,len);
        check  = check ^ (len>>8) ^ (len);

        USART3_SendByte(USART3,0x01);
        USART3_SendByte(USART3,0x01);
        check = check ^ 0x01 ^ 0x01;

        for( k = 0; k < len-3; k++ )
        {
                USART3_SendByte(USART3,*str);
                check ^= ( *str );
                str++;
        }
        USART3_SendByte(USART3,check);  //发送数据包
        Delay_Ms(150*len);

}

PWM初始化配置

void xuanzhuan(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;//定义三个结构体

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//开启相关时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 //A1 GPIO初始化
    TIM_TimeBaseStructure.TIM_Period = 199;
    TIM_TimeBaseStructure.TIM_Prescaler =4199;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    // 定时器初始化
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);
   // TIM_OC3Init(TIM2, &TIM_OCInitStructure);
   // TIM_OC4Init(TIM2, &TIM_OCInitStructure);
    //定时器通道初始化
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
   // TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
   // TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);
    //预装值初始化
    TIM_Cmd(TIM2, ENABLE);
    //打开定时器
}

接收数据进行播报

  if(a == 01)
  {
    TIM_SetCompare1(TIM2,199);
    TIM_SetCompare2(TIM2,199);
    SYN6288(USART3,"未佩戴安全帽");
  }
  if(a == 03)
  {
    TIM_SetCompare1(TIM2,199);
    TIM_SetCompare2(TIM2,199);
    SYN6288_Speech(USART3,"已佩戴安全帽");
   }

五、实际效果

识别时MaixBit开发板外接2.4寸显示屏观察识别结果

未识别到安全帽

识别到安全帽

完整视频演示

一种检测有无佩戴安全帽的装置

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值