一、概述
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扩展板:人体红外和智慧路灯
3、WLAN模组:ESP8266(烧录有腾讯云固件)
4、摄像头:OV5640
5、RGB显示屏:微雪的4.3寸 800*480分辨率
6、硬件集成:如图硬件搭建,主要由一个LCD屏,两个E53模块,一个WIFI模组。其中两个E53是的取电如图所示取的是5V电。然后控制灯的引脚连接到传感器的输出信号引脚,同时连接到KEY2引脚,因为其他引脚有虚焊的情况。
四、软件设计
1、使用GUI Guider设计LVGL开机画面
使用以下工具开发GUI.
页面很好编辑,瞬间让开发板显得大气了许多了。后期还可以实现更多的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