目录
开发平台/开发环境:
windows 10、Linux、arm cortex A9(Exynos 4412)、ubuntu20.04、zigebee通信、摄像头外设、cortex-M0;
项目模块:
摄像头模块;qt界面及语音识别模块;qt客户端模块;服务器模块;
项目描述:
qt客户端可以通过连接服务器后,通过语音识别,确定想要的功能,可以通过服务器显示摄像头内的视频内容,也可以通过服务器的串口通信去操控cortex M0的LED灯,风扇,蜂鸣器,服务器可以通过串口通信实时地获得cortex M0上的温度,湿度,光照信息,并发送给客户端,qt客户端还可以获取天气预报信息或者打开某一个应用。
具体代码:
1.串口模块:
serial.h:
serial.c:
摄像头:
camera.h:
camera.c
摄像头服务器:
camera_server.h:
camera_server.c:
服务器:
server.h
server.c
主函数
main.c
下面是QT的模块:使用的模式是:QT widgets applicantion;使用的基类是:widget
录音和设置语音文件:对应下面audio.c
audio.h
http请求百度api获取请求数据:
http.h
处理http请求数据并再次请求百度api再次返回的json:
speech.h
通过http协议获取天气 :
weather.h
界面操作:
widget.h
audio.cpp
http.cpp
main.cpp
speech.cpp
weather.cpp
widget.cpp
ui界面:
演示:
windows 10、Linux、arm cortex A9(Exynos 4412)、ubuntu20.04、zigebee通信、摄像头外设、cortex-M0;
arm cortex A9(Exynos 4412):内部使用裁剪后的Linux系统来搭建服务器。
ubuntu20.04:使用arm-linux-gcc工具编译成可以在arm架构芯片上执行的程序。
zigbee协调节点板块与A9板使用串口通信,ZigBee 模块主要实现的是数据的透传的工作,一个 ZigBee 节点接收服务器的消息无线转到ZigBee 的另外一个节点,另外一个节点把数据发送给终端设备,完成操作。同时也可以反过来,是终端设备的环境信息。我使用的CC2530 的单片机。它是一款完全兼容 8051 的内核,同时支持 IEEE 802.15.4协议的无线射频的单片机。这个项目主要是使用 ZigBee 提供的协议栈来进行开发。使用了其中的函数接口来完成项目需求的应用程序。
数据终端采集:
数据采集模块使用的是 ARM 系列的 Cortex-M0 芯片,在这个芯片的基础之上。分别外接了以下几个设备。有温湿度、光照、三轴传感器与 RFID 射频模块。还是风扇、LED、蜂鸣器、OLED 硬件。同时集成第 94 页了 RS485、CAN 总线。在这个项目中,使用到了温湿度、光照、三轴传感器获取当前的环境信息,发送到ZigBee 的节点。从 ZigBee 的节点接收命令通过风扇、LED、蜂鸣器来模拟家中的电器设备。在这个模块中使用了 ARM 开发的一些流程,如配置寄存器让硬件工作。一些总线设备的使用,如 SPI、I2C。还有中断的机制和定时器的使用,如本项目中启用了一个 32 位的定时器来做延时操作。
摄像头模块;qt界面及语音识别模块;qt客户端模块;服务器模块;
qt客户端可以通过连接服务器后,通过语音识别,确定想要的功能,可以通过服务器显示摄像头内的视频内容,也可以通过服务器的串口通信去操控cortex M0的LED灯,风扇,蜂鸣器,服务器可以通过串口通信实时地获得cortex M0上的温度,湿度,光照信息,并发送给客户端,qt客户端还可以获取天气预报信息或者打开某一个应用。
#ifndef SERIAL_H
#define SERIAL_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int serial_set(char *path);
int serial_write(int fd);
int serial_close(int fd);
int serial_ctrl(int fd,char *p);
int serial_getdata(int fd);
#endif
#include
#include
#include
#include
#include
#include
#include
#define N 36
int serial_set(char *path)
{
struct termios options;
/*
struct termios {
tcflag_t c_iflag;//输入标志
tcflag_t c_oflag;//输出标志
tcflag_t c_lflag;// 本地标志
tcflag_t c_cc[NCCS];//控制字符
};
*/
int fd = open(path,O_RDWR | O_NOCTTY | O_NDELAY);//打开串口
if(-1 == fd)
{
perror("open error");
return -1;
}
if(-1 == fcntl(fd,F_SETFL,0))
{
printf("fcntl error");
return -1;
}
cfsetispeed(&options,B115200);
cfsetospeed(&options,B115200);
options.c_cflag |= CLOCAL;
//修改控制模式,使得能够从串口中读取输入数据
options.c_cflag |= CREAD;
options.c_oflag &= ~(ONLCR | OCRNL);
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
options.c_iflag &= ~(ICRNL | INLCR);
options.c_iflag &= ~(IXON | IXOFF | IXANY);
//不使用流控制
options.c_cflag &= ~CRTSCTS;
options.c_cflag |= CS8;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
tcsetattr(fd, TCSANOW, &options); //TCSANOW更改立即发生
return fd;
}
int serial_close(int fd) //关闭串口
{
if (close(fd))
{
perror("serial close error");
return -1;
}
return 0;
}
int serial_ctrl(int fd,char *p)
{
unsigned char envbuf[36]={0,0x08,0x24,0x00};
if(strncmp(p,"light_on",8)==0)
{
//envbuf[] = {0xdd,id,24,00,命令}
//发送命令开灯
envbuf[0]=0xdd;
envbuf[4]=0x00; //开灯命令
if(write(fd,envbuf,36)<0)
{
perror("write");
return -1;
}
printf("控制:%x %x %x %x %x\n",envbuf[0],envbuf[1],envbuf[2],envbuf[3],envbuf[4]);
}
else if(strncmp(p,"light_off",9)==0)
{
//发送命令关灯
envbuf[0]=0xdd;
envbuf[4]=0x01; //关灯
if(write(fd,envbuf,36)<0)
{
perror("write");
return -1;
}
printf("控制:%x %x %x %x %x\n",envbuf[0],envbuf[1],envbuf[2],envbuf[3],envbuf[4]);
}
else if(strncmp(p,"dshi_on",9)==0)
{
//发送命令打开蜂鸣器
envbuf[0]=0xdd;
envbuf[4]=0x02;
if(write(fd,envbuf,36)<0)
{
perror("write");
return -1;
}
printf("控制:%x %x %x %x %x\n",envbuf[0],envbuf[1],envbuf[2],envbuf[3],envbuf[4]);
}
else if(strncmp(p,"dshi_off",10)==0)
{
//发送命令关闭蜂鸣器
envbuf[0]=0xdd;
envbuf[4]=0x03;
if(write(fd,envbuf,36)<0)
{
perror("write");
return -1;
}
printf("控制:%x %x %x %x %x\n",envbuf[0],envbuf[1],envbuf[2],envbuf[3],envbuf[4]);
}
else if(strncmp(p,"feng_on",7)==0)
{
printf("feng_on\n");
//发送命令打开风扇
envbuf[0]=0xdd;
envbuf[4]=0x04;
printf("控制:%x %x %x %x %x\n",envbuf[0],envbuf[1],envbuf[2],envbuf[3],envbuf[4]);
if(write(fd,envbuf,36)<0)
{
perror("write");
return -1;
}
}
else if(strncmp(p,"feng_off",8)==0)
{
//发送命令关闭风扇
envbuf[0]=0xdd;
envbuf[4]=0x08;
if(write(fd,envbuf,36)<0)
{
perror("write");
return -1;
}
printf("控制:%x %x %x %x %x\n",envbuf[0],envbuf[1],envbuf[2],envbuf[3],envbuf[4]);
}
// memset(p, 0, 32); //清空buf
return 0;
}
#ifndef _CAMERA_H
#define _CAMERA_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pwd "/dev/video0"
#define pwd2 "/dev/video1"
#define c_count 4
unsigned char *mmps[c_count];
unsigned long mmpsize[c_count];
int camera_init();
int camera_star(int fd);
//出队,采集数据
int dqbuf(int fd,int index);
//入队,归还数据
int qbuf(int fd,int index);
int camera_stop(int fd);
#endif
#include "camera.h"
int camera_init()
{
int ret;
//
v4l2_std_id std;
//
struct v4l2_format fmt;
//使用非阻塞方式打开摄像头设备
int camera_fd = open(pwd,O_RDWR,0);
if(camera_fd < 0)
{
camera_fd = open(pwd2,O_RDWR | O_NONBLOCK,0);
}
if(camera_fd < 0)
{
printf("摄像头打开失败\n");
return -1;
}
printf("成功打开摄像头\n");
//使用ioctl函数对设备的io通道进行管理
//检查当前视频设备支持的标准,使用VIDIOC_QUERYSTD
/* do{
ret = ioctl(camera_fd,VIDIOC_QUERYSTD,&std);
}while(-1 == ret && errno == EAGAIN);
switch (std)
{
case V4L2_STD_NTSC:
printf("视频标准为NTSC\n");
break;
case V4L2_STD_PAL:
printf("视频标准为PAL\n");
break;
}
*/
//设置视频捕获格式
bzero(&fmt,sizeof(fmt));
//摄像头的数据流类型,必须为V4L2_BUF_TYPE_VIDEO_CAPTURE
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 640; //必须为16的倍数
fmt.fmt.pix.height = 480; //必须为16的倍数
//视频数据存储类型YUYV 或者 RGB
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if(-1 == ioctl(camera_fd,VIDIOC_S_FMT,&fmt))
{
printf("设置视频捕获格式失败\n");
return -2;
}
//为视频捕获分配内存
struct v4l2_requestbuffers req;
bzero(&req,sizeof(req));
req.count = c_count;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if(-1 == ioctl(camera_fd,VIDIOC_REQBUFS,&req))
{
printf("分配内存出错\n");
return -3;
}
printf("分配内存成功\n");
int i;
struct v4l2_buffer buffer;
for(i=0;i ioctl(camera_fd,VIDIOC_QUERYBUF,&buffer))
{
printf("取出映射地址出错\n");
return -1;
}
//映射
mmps[i] = mmap(NULL,buffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,camera_fd,buffer.m.offset);
mmpsize[i] = buffer.length;
if((void *)-1 == mmps