AIoT应用创新大赛-基于TencentOS Tiny AIoT NXP自动摄像仪

2022-03-16 10:51:42 浏览数 (1)

视频内容

TencentOS tiny AIoT NXP自动摄像仪.pptx

一、概述

TencentOS tiny联合NXP推出的RT1062开发板让人眼前一亮,能够实现众多的强大功能,但是我只能选取一瓢来实现本次比赛的作品。看到摄像头的功能,和较大的内存以及强大算力,我最先想到的是可以自动抓拍人们经过某个区域时照片,这样我不用一直开着摄像机,省电又可以延长摄像头的寿命。特别在许多无人区更需要这样的一台简单又实用的设备,且也不需要长期监控的,又能够节约能源。例如我们出差时,家里长时间没人,又担心有人一盯上家里的财物,而经常在门口转悠,这个时候就可以通过检测是否有人启动摄像头,并通过腾讯云平台传递信息到手机中提醒有人在门口长时间逗留。

二、系统设计

系统开发与组成系统开发与组成

通过以上系统图,我们可以清晰的看到,主要有四大部分:腾讯云平台、LVGL、摄像头OV5640(也可以用OV7225),人体红外检测。通过TencentOS tiny 的四个任务来分别实现,其中LVGL和摄像头任务是通过定时器和信号量实现LCD屏使用的切换。

三、硬件设计

硬件框架结构硬件框架结构

1、开发板:EVB_AIoT RT1062

EVB_AIoT是腾讯物联网操作系统TencentOS tiny 团队联合恩智浦半导体、厚德物联网设计的一款高性能AIoT评估板,用于TencentOS tiny 基础内核和AIoT应用功能体验和评估。 开发板如下图所示:

开发板开发板

开发板特性

a、内置TencentOS Tiny开源物联网操作系统,NXP RT1062跨界处理器,最高主频528M

b、1M RAM 16M SDRAM 64MB qspi flash 128MB spi flash

c、板载Type-C接口CMSIS DAP仿真器

d、板载PCIE接口,可扩展4G类物联网模组

f、板载物联网俱乐部WAN Interface接口,可支持NB-IoT、WiFi、4G cat1、LoRa等模组

g、载物联网俱乐部E53 Interface接口,可扩展全系E53传感器;

h、板载标准24P DVP摄像头接口,可支持最高500万像素摄像头;

i、板载RGB显示接口,可转换HDMI输出;

j、板载高性能音频解码芯片,可做语音识别测试;

k、预留SD卡、用户按键、SPI Flash

2、E53扩展板:人体红外和智慧路灯

E53人体红外扩展板E53人体红外扩展板
E53人体红外功能参数E53人体红外功能参数
E53智慧路灯E53智慧路灯
E53智慧路灯功能参数E53智慧路灯功能参数

3、WLAN模组:ESP8266(烧录有腾讯云固件)

WIFI模组WIFI模组

4、摄像头:OV5640

5、RGB显示屏:微雪的4.3寸 800*480分辨率

6、硬件集成:如图硬件搭建,主要由一个LCD屏,两个E53模块,一个WIFI模组。其中两个E53是的取电如图所示取的是5V电。然后控制灯的引脚连接到传感器的输出信号引脚,同时连接到KEY2引脚,因为其他引脚有虚焊的情况。

硬件搭建完成硬件搭建完成

四、软件设计

软件开发(左)与运行流程(右)软件开发(左)与运行流程(右)

1、使用GUI Guider设计LVGL开机画面

使用以下工具开发GUI.

LVGL生成器LVGL生成器

页面很好编辑,瞬间让开发板显得大气了许多了。后期还可以实现更多的GUI功能。

我编辑的开机页面我编辑的开机页面
代码语言:javascript复制
void lvgl_AppTask(void *arg)
{
    uint32_t  count=0;
	#define CA_TASK_SIZE 2048
	k_task_t ca_app_task;
	k_stack_t ca_app_task_stack[CA_TASK_SIZE];

	k_err_t err3;
	k_err_t timer_err;
	int flag=2;
	lvgl_GUI_init();
	PRINTF("TencentOS tiny LVGL GUI task start...rn");
	lvgl_GUI_init();
	 setup_ui(&guider_ui);
	 events_init(&guider_ui);

    for (;;)
    {

        while (!s_lvglTaskPending)
        {
        	 tos_task_delay(1);
        }
        s_lvglTaskPending = false;
        lv_task_handler();
       // PRINTF("littlevgl bare metal widgets demorn");
        tos_task_delay(5);
        if(lv_stop_flag==1)
        {
        	lv_stop_flag=0;

       	 PRINTF("timer start flagrn");
       	err3= tos_sem_post(&lv_camera_sem);
       	if (err3 != K_ERR_NONE)
       	   printf("sem pend fail! code : %d rn",err3);

        	 while(1)
        	          {
        	        	  tos_task_delay(1000);
        	        	  printf("stop lv to showrn");
        	          }

        }

    }
}

以上为LVGL任务代码,以下为摄像头任务,摄像头实现关闭和启动,同时保护摄像头,解决摄像头发烫的问题,当摄像头不使用时要把PWDN引脚置1,如果启动则置0.

代码语言:javascript复制

int lv_flag=0;
static void APP_CSI_RGB565(void)
{
	k_err_t err;
	uint32_t cameraReceivedFrameAddr;
	int flag=0;
	/* Set the pins for CSI reset and power down. */
	  gpio_pin_config_t pinConfig = {
		  kGPIO_DigitalOutput,
		  1,
		  kGPIO_NoIntmode,
	  };
	  gpio_pin_config_t enpinConfig = {
	  		  kGPIO_DigitalOutput,
	  		  0,
	  		  kGPIO_NoIntmode,
	  	  };

while(1)
{

    CAMERA_RECEIVER_Start(&cameraReceiver);

    /* Wait to get the full frame buffer to show. */
    while (kStatus_Success != CAMERA_RECEIVER_GetFullBuffer(&cameraReceiver, &cameraReceivedFrameAddr))
    {
    	 tos_task_delay(1);
    }

    s_newFrameShown = false;
    g_dc.ops->setFrameBuffer(&g_dc, 0, (void *)cameraReceivedFrameAddr);

    /* For the DBI interface display, application must wait for the first
     * frame buffer sent to the panel.
     */
    if ((g_dc.ops->getProperty(&g_dc) & kDC_FB_ReserveFrameBuffer) == 0)
    {
        while (s_newFrameShown == false)
        {
        	 tos_task_delay(1);
        }
    }

    s_newFrameShown = true;

    g_dc.ops->enableLayer(&g_dc, 0);
   // GPIO_PinWrite(BOARD_CAMERA_PWDN_GPIO, BOARD_CAMERA_PWDN_PIN,1u);//停止接收数据后要关闭电源,否则摄像头会一直发烫

    while (1)
    {

    	//不启动摄像机
		if(camera_flag==0)
		{
		 GPIO_PinInit(BOARD_CAMERA_PWDN_GPIO, BOARD_CAMERA_PWDN_PIN, &pinConfig);
		 //GPIO_PinWrite(BOARD_CAMERA_PWDN_GPIO, BOARD_CAMERA_PWDN_PIN,1u);//停止接收数据后要关闭电源,否则摄像头会一直发烫
		 CAMERA_RECEIVER_Stop(&cameraReceiver);
		 flag=1;
		 tos_task_delay(1000);
		 lv_flag=1;
		 while(1)
		 {
			 tos_task_delay(100);
			 if(camera_flag==1&&flag==1)
			 		{
			 			 flag=0;
			 			 GPIO_PinInit(BOARD_CAMERA_PWDN_GPIO, BOARD_CAMERA_PWDN_PIN, &enpinConfig);//启动摄像机
			 			 //GPIO_PinWrite(BOARD_CAMERA_PWDN_GPIO, BOARD_CAMERA_PWDN_PIN,0u);//打开电源才能初始化程序
			 			 CAMERA_RECEIVER_Start(&cameraReceiver);
			 			 tos_task_delay(1000);
			 			 lv_flag=0;
			 			 break;
			 		}
		 }
		}

        /* Wait to get the full frame buffer to show. */
        while (kStatus_Success != CAMERA_RECEIVER_GetFullBuffer(&cameraReceiver, &cameraReceivedFrameAddr))
        {
        	 tos_task_delay(1);
        }

        /* Wait for the previous frame buffer is shown. */
        while (s_newFrameShown == false)
        {
        	tos_task_delay(1);
        }
        tos_task_delay(1);
        g_dc.ops->setFrameBuffer(&g_dc, 0, (void *)cameraReceivedFrameAddr);


       // tos_task_delay(1);
    }
 }
}
void start_camera_task(void *arg)
{
		k_err_t err;
		gpio_pin_config_t pinConfig = 
		{
				  kGPIO_DigitalOutput,
				  1,
				  kGPIO_NoIntmode,
		 };
		GPIO_PinInit(BOARD_CAMERA_PWDN_GPIO, BOARD_CAMERA_PWDN_PIN, &pinConfig);//
	    PRINTF("CSI RGB565 example start...rn");
	    err=tos_sem_pend(&lv_camera_sem, TOS_TIME_FOREVER);
		if (err == K_ERR_NONE)
			printf("sem pend successrn");
	    APP_InitCamera();

	    APP_InitDisplay();

	    APP_CSI_RGB565();
	    for(;;)
	    {
	     tos_task_delay(2000);
	    }

}

人体红外检测函数:里面红外传感器的输出信号引脚来实现读取人体红外的信号,有人靠近输出高电平,否则输出低电平。

代码语言:javascript复制
void EXAMPLE_GPIO4_IRQHandler(void)
{
    /* clear the interrupt status */
    GPIO_PortClearInterruptFlags(EXAMPLE_SW1_GPIO, 1U << EXAMPLE_SW1_GPIO_PIN);
    /* Change state of switch. */
    g_InputSignal1 = true;
    SDK_ISR_EXIT_BARRIER;
}
void EXAMPLE_GPIO2_IRQHandler(void)
{
    /* clear the interrupt status */
    GPIO_PortClearInterruptFlags(EXAMPLE_SW2_GPIO, 1U << EXAMPLE_SW2_GPIO_PIN);
    /* Change state of switch. */
    g_InputSignal2 = true;

    SDK_ISR_EXIT_BARRIER;
}
void EXAMPLE_GPIO2_30_IRQHandler(void)
{
    /* clear the interrupt status */
    GPIO_PortClearInterruptFlags(EXAMPLE_MAN_GPIO, 1U << EXAMPLE_MAN_GPIO_PIN);
    /* Change state of switch. */
    g_InputSignal3 = true;
    SDK_ISR_EXIT_BARRIER;
}
void led_key_inf_task(void *arg)
{
	gpio_pin_config_t CameraEnable_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode,};
	gpio_pin_config_t LED_RST_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode,};
	gpio_pin_config_t KEY_RST_config = {kGPIO_DigitalInput,kGPIO_IntRisingEdge,};
	gpio_pin_config_t dispinConfig = {kGPIO_DigitalOutput, 1, kGPIO_NoIntmode,};
	gpio_pin_config_t sw_config = {kGPIO_DigitalInput,0,kGPIO_IntRisingEdge,};
	gpio_pin_config_t Man_config = {kGPIO_DigitalInput,0,kGPIO_IntRisingEdge,};
	int flag=0;
	GPIO_PinInit(GPIO3, 2U, &LED_RST_config);//配置LED

	GPIO_PinInit(GPIO4, 20U, &KEY_RST_config);//配置按键key1
	GPIO_PinInit(GPIO1, 11U,  &KEY_RST_config);//配置按键key2
	GPIO_PinInit(GPIO2, 30U,  &Man_config);//配置按键key2

	/* Init input switch GPIO. */
	EnableIRQ(EXAMPLE_SW1_IRQ);
	EnableIRQ(EXAMPLE_SW2_IRQ);
	EnableIRQ(EXAMPLE_MAN_IRQ);

	GPIO_PinInit(EXAMPLE_SW1_GPIO, EXAMPLE_SW1_GPIO_PIN, &sw_config);
	GPIO_PinInit(EXAMPLE_SW2_GPIO, EXAMPLE_SW2_GPIO_PIN, &sw_config);
	GPIO_PinInit(EXAMPLE_MAN_GPIO, EXAMPLE_MAN_GPIO_PIN, &Man_config);

	/* Enable GPIO pin interrupt */
	GPIO_PortEnableInterrupts(EXAMPLE_SW1_GPIO, 1U << EXAMPLE_SW1_GPIO_PIN);
	GPIO_PortEnableInterrupts(EXAMPLE_SW2_GPIO, 1U << EXAMPLE_SW2_GPIO_PIN);
	GPIO_PortEnableInterrupts(EXAMPLE_MAN_GPIO, 1U << EXAMPLE_MAN_GPIO_PIN);

	for(;;)
	{

		if (g_InputSignal1)
		{
			tos_task_delay(20);
			if (1 == GPIO_PinRead(EXAMPLE_SW1_GPIO, EXAMPLE_SW1_GPIO_PIN))
			{
				PRINTF("%s is turned on.rn", EXAMPLE_SW1_NAME);

				 GPIO_PinWrite(GPIO3, 2u, 1u);//BLUE LED ON
				 GPIO_PinWrite(GPIO2, 31u, 0u);//E53_SC1 LED ON
                 lv_board_flag=1;
			}

			/* Reset state of switch. */
			g_InputSignal1 = false;
		}
		if (g_InputSignal2)
				{
			tos_task_delay(20);

				if (1 == GPIO_PinRead(EXAMPLE_SW2_GPIO, EXAMPLE_SW2_GPIO_PIN))
				{
					flag=~flag;

					if(flag)
					{
					PRINTF("%s is turned on.rn", EXAMPLE_SW2_NAME);
					GPIO_PinWrite(GPIO3, 2u, 1u);//BLUE LED ON
					 GPIO_PinWrite(GPIO2, 30u, 1u);//E53_SC1 LED ON
					GPIO_PinWrite(GPIO2, 31u, 1u);//E53_SC1 LED ON
					camera_flag=1;
					infrared_flag=1;
					}
					else
					{
					PRINTF("%s is turned off.rn", EXAMPLE_SW2_NAME);
					GPIO_PinWrite(GPIO3, 2u, 0u);//BLUE LED OFF
					 GPIO_PinWrite(GPIO2, 30u, 0u);//E53_SC1 LED ON
					GPIO_PinWrite(GPIO2, 31u, 0u);//E53_SC1 LED ON

					camera_flag=0;
					infrared_flag=0;
					}

					//GPIO_PinWrite(GPIO7, 31u, 1u);//E53_SC1 LED ON
					//GPIO_PinWrite(GPIO3, 2u, 0u);//BLUE LED ON
				}

					/* Reset state of switch. */
					g_InputSignal2 = false;
				}

		  tos_task_delay(100);

	}
	if (g_InputSignal2)
		{
	     	 tos_task_delay(20);
			if (1 == GPIO_PinRead(EXAMPLE_MAN_GPIO, EXAMPLE_MAN_GPIO_PIN))
			{
				PRINTF("%s is turned off.rn", EXAMPLE_MAN_NAME);
				flag=~flag;
				if(flag)
				{
				camera_flag=0;
				}
				else camera_flag=1;
			}
		}
}

2、连接腾讯云平台:

只要显示就说明联网成功了,可以通过云端下发控制指令。

显示在线显示在线
查看云端数据是否正确查看云端数据是否正确

下发指令正确:

串口查看信息串口查看信息

3、腾讯连连小程序:

小程序操作节目小程序操作节目

公众号配置:

数据开发页面数据开发页面

五、总结

自动摄像仪,很普通的设备,但是很实用,本次使用的人外传感器来启动拍照功能,成功率很高。后期也可以使用机人脸识别来识别。应用场景很多,可以实现远程安防的功能。而我本人想用在家里,把摄像头延伸到门外和红外检测,这样当识别到时就可以在家里查看陌生人。又可以在手机端接收到信息。

本次作品给大家提供一个思路,就可以做一些小的实用的看起来又性价比的作品,相比那些功能强大,让用不起的感觉的作品要好得多。这个开发板的最大优点就是功能强大,运算速度高,内存容量大,可以让你随心所欲实现各种想法而不会因为受太多限制而苦恼。对于软件开发来讲,开始我是选择KEIL的,最后直接放弃选择NXP的MCUXpresso IDE,可以随意跳转查找变量,SDK里面又有许多demo可以参考,移植TencentOS tiny内核和组件时也很方便,直接添加头文件路径即可,开发效率大大提高,虽然编译和下载速度慢些,但是毕竟代码量那么大,还要显示GUI那么多图片,真的难为它了,总之越用越喜欢。

代码链接:https://gitee.com/flytianya2010/evb_-aio-t-tencent-os-tiny-nxp/tree/master

摄像仪全貌摄像仪全貌

0 人点赞