在线时间234 小时
UID3301905
注册时间2017-1-8
NXP金币134
TA的每日心情 | 开心 2018-4-20 15:04 |
---|
签到天数: 8 天 [LV.3]偶尔看看II
金牌会员
- 积分
- 2975
- 最后登录
- 2023-7-24
|
项目概要:此系统功能有网络摄像头图像传输,温湿度数据采集,光照强度数据采集,大气压数据采集,网络摄像头图像远程监控,手机浏览器网页读取显示等功能,系统分为四个部分,第一部分为基于IMX8嵌入式系统的主服务器,
负责功能为:-摄像头图像采集与UDP发送
-基于TCP的HTML网页界面搭建
-USBHID主机接收
第二部分为基于单片机MCU核心板的采集模块,负责功能为
-DHT11温湿度采集
-光照强度模拟信号AD采集
-大气压数字信号读取
-USBHID从机发送,发送目标为第一部分的IMX8嵌入式系统
第三部分为基于x86电脑的QT上位机,负责功能为
-接收第一部分IMX8嵌入式系统的网络摄像头数据,协议为UDP
-接收第一部分IMX8嵌入式系统的温湿度,光照强度,大气压数据并显示,协议同样为UDP
第四部分为手机或x86电脑,使用浏览器访问第一部分IMX8嵌入式系统搭建的TCP-HTML网页界面并显示
系统要点如下:
-网络摄像头数据传输采用协议为UDP而非TCP,提高传输效率,不过可手动切换为TCP模式,使用UDP模式,由于x86PC端IP是固定的,因此UDP发送端报文只需要配置协商好的端口号,然后接收端打开该端口号的接收就可以进行大流量数据传输
-HTML网页服务器只能采用TCP方式传输,无法使用UDP
-USB通信协议为Custom HID,简化IMX8嵌入式系统部分编程复杂度,提高项目可实施性
-IMX8嵌入式系统上有片内M4核,但是普适性不高,采用普适性更高的片外MCU+USB通信
系统框图如下:
运行效果,QT上位机界面部分:
手机浏览器网页:
实物连接图拍照:
如图所示,IMX8嵌入式系统开发板既可以连接网线也可以通过无线WIFI进行通信。
IMX8嵌入式系统代码,基于Unix系统编程,使用发行版系统为Debian10。
UDP发送图片文件帧到x86PC:
- int UDP_Send_Picture(socklen_t socket_send , struct sockaddr_in addr , char* filename)
- {
- struct Package
- {
- int length;
- char data[UDP_FRAME_LEN];
- int fin;
- }picture;
- socklen_t addr_len = sizeof(struct sockaddr_in);
- FILE *fp;
- fp = fopen(filename, "rb+");
- printf("fp = %d\n",fp);
- fseek(fp, 0, SEEK_END);
- int fend = ftell(fp);
- fseek(fp, 0, 0);
- int sendbytes;
- printf("fend = %d\n",fend);
- while(fend > 0)
- {
- memset(picture.data, 0, sizeof(picture.data));
- fread(picture.data, UDP_FRAME_LEN, 1, fp);
- if(fend >= UDP_FRAME_LEN)
- {
- picture.length = UDP_FRAME_LEN;
- picture.fin = 0;
- }
- else
- {
- picture.length = fend;
- picture.fin = 1;
- }
- //printf("sendbytes = %d \n",sendbytes);
- sendbytes = sendto(socket_send, (char *)&picture, sizeof(struct Package), 0, (struct sockaddr*)&addr,addr_len);
- if(sendbytes == -1)
- {
- printf("Send Picture Failed!d\n");
- return -1;
- }
- else
- {
- fend -= UDP_FRAME_LEN;
- }
- }
- fclose(fp);
- return 0;
- }
复制代码
建立UDP发送套接字:
- int UDP_Send_Found(socklen_t* socket_found , struct sockaddr_in *addr , char* ip , int port)
- {
- *socket_found = socket(AF_INET, SOCK_DGRAM, 0);
- if(*socket_found == (~0))
- {
- printf("Create udp send socket failed!\n");
- return -1;
- }
- addr->sin_family = AF_INET;
- addr->sin_addr.s_addr = inet_addr(ip);
- addr->sin_port = htons(port);
- memset(addr->sin_zero, 0, 8);
- return 0;
- }
复制代码
抓取V4L2 USB摄像头图像帧并保存在缓存中:
- typedef struct
- {
- void *start;
- unsigned int length;
- } buffer;
复制代码- int V4l2_Grab()
- {
- unsigned int n_buffers;
- buffers = (buffer* )malloc(req.count*sizeof(*buffers));
- if (buffers == NULL)
- {
- printf ("Out of memory\n");
- return 0;
- }
- for (n_buffers = 0; n_buffers < req.count; n_buffers++)
- {
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = n_buffers;
- //query buffers
- if (ioctl (fd_video,VIDIOC_QUERYBUF, &buf) == -1)
- {
- printf("query buffer error\n");
- return(0);
- }
- buffers[n_buffers].length = buf.length;
- buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED,
- fd_video, buf.m.offset);
- if (buffers[n_buffers].start == MAP_FAILED)
- {
- printf("buffer map error\n");
- return 0;
- }
- }
- for (n_buffers = 0; n_buffers < req.count; n_buffers++)
- {
- buf.index = n_buffers;
- ioctl(fd_video, VIDIOC_QBUF, &buf);
- }
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- ioctl (fd_video, VIDIOC_STREAMON, &type);
- ioctl(fd_video, VIDIOC_DQBUF, &buf);
- // printf("grab yuyv OK!\n");
- return 1;
- }
复制代码- int Yuyv_2_RGB888(buffer* input_buffers,unsigned char *output_buffer)
- {
- int i,j,r1,g1,b1,r2,g2,b2;
- unsigned char y1,y2,u,v;
- unsigned char *pointer;
- pointer =(unsigned char*)input_buffers[0].start;
- for(i=0;i<IMAGEHEIGHT;i++)
- {
- for(j=0;j<IMAGEWIDTH/2;j++)
- {
- y1 = *( pointer + (i*IMAGEWIDTH/2+j)*4);
- u = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);
- y2 = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 2);
- v = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);
- r1 = y1 + 1.042*(v-128);
- g1 = y1 - 0.34414*(u-128) - 0.71414*(v-128);
- b1 = y1 + 1.772*(u-128);
- r2 = y2 + 1.042*(v-128);
- g2 = y2 - 0.34414*(u-128) - 0.71414*(v-128);
- b2 = y2 + 1.772*(u-128);
- if(r1>255)
- r1 = 255;
- else if(r1<0)
- r1 = 0;
- if(b1>255)
- b1 = 255;
- else if(b1<0)
- b1 = 0;
- if(g1>255)
- g1 = 255;
- else if(g1<0)
- g1 = 0;
- if(r2>255)
- r2 = 255;
- else if(r2<0)
- r2 = 0;
- if(b2>255)
- b2 = 255;
- else if(b2<0)
- b2 = 0;
- if(g2>255)
- g2 = 255;
- else if(g2<0)
- g2 = 0;
- *(output_buffer + (i*IMAGEWIDTH/2+j)*6 ) = (unsigned char)r1;
- *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 1) = (unsigned char)g1;
- *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 2) = (unsigned char)b1;
- *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 3) = (unsigned char)r2;
- *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 4) = (unsigned char)g2;
- *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 5) = (unsigned char)b2;
- }
- }
- // printf("change to RGB OK! \n");
- free(input_buffers);
- return 0;
- }
复制代码
主循环处理:
- while(1)
- {
- V4l2_Grab();
- if(buffers != NULL)
- {
- Yuyv_2_RGB888(buffers,frame_buffer_video);
- Encode_Jpeg(frame_buffer_video , 640 , 480 , (char*)"/home/proj/1.jpg");
- UDP_Send_Picture(socklen_udp_camera_send,sockaddr_udp_camera_send,(char*)"/home/proj/1.jpg");
- }
- }
复制代码
建立HID枚举主设备并枚举特定VID/PID从设备(HID单片机):
- handle = hid_open(2020, 2020, NULL);
- if (!handle)
- {
- printf("unable to open hidraw device\n");
- return -1;
- }
-
- hid_set_nonblocking(handle, 1);
- printf("open hidraw device\n");
复制代码
USBHID接收并通过UDP发送,使用单独线程进行:
- pthread_t tid_udp_send;
- pthread_create(&tid_udp_send , NULL , Thread_UDP_Send , (void*)&t2a);
复制代码- void * Thread_UDP_Send(void *arg)
- {
- thread2_args t2a = *(thread2_args*)arg;
- int res , sendbytes;
- socklen_t addr_len = sizeof(struct sockaddr_in);
- uint8_t buf_usb_recv[64];
- uint8_t buf_udp_send[UDP_FRAME_LEN];
- while(1)
- {
- res = hid_read(handle, buf_usb_recv, 64);
- if(res > 0)
- {
- printf("res = %d buf[2] = %d buf[3] = %d buf[4] = %d buf[5] = %d\n",res ,
- buf_usb_recv[2] , buf_usb_recv[3] , buf_usb_recv[4] , buf_usb_recv[5]);
- buf_udp_send[0] = 0x12;
- buf_udp_send[1] = 0x23;
- buf_udp_send[2] = 0x34;
- buf_udp_send[3] = 0x45;
- buf_udp_send[4] = buf_usb_recv[2];
- dht11_temp = buf_usb_recv[2];
- buf_udp_send[5] = buf_usb_recv[3];
- dht11_humi = buf_usb_recv[3];
- buf_udp_send[6] = buf_usb_recv[4];
- buf_udp_send[7] = buf_usb_recv[5];
- adc_value = (buf_usb_recv[4] << 8) | buf_usb_recv[5];
- sendbytes = sendto(t2a.fd, buf_udp_send, UDP_FRAME_LEN , 0, (struct sockaddr*)&t2a.addr , addr_len);
- }
- }
- }
复制代码
TCP-HTML网页的接收和发送采用两个单独线程进行:- pthread_t tid_tcp_web_recv;
- pthread_create(&tid_tcp_web_recv , NULL , Thread_TCP_Web_Recv , NULL);
- pthread_create(&id_tcp_send , NULL , Thread_TCP_Web_Send , NULL);
复制代码
TCP发送线程:
- void * Thread_TCP_Web_Send(void *arg)
- {
- int len,j;
- float cpu_temp;
- while(1)
- {
- if(flag_keep_alive && flag_post_once)
- {
- flag_post_once = 0;
- if(flag_get)
- printf("收到客户端GET请求,服务器可进行一次POST操作\n");
- else if(flag_post)
- printf("收到客户端POST回应,服务器可进行一次POST操作\n");
- File_Read_All_Text((char*)HTML_FILE);
- len_buf_html=File_Read_Length((char*)HTML_FILE);
- printf("\n\nHTML文件长度:len_buf_html=%d\n\n",len_buf_html);
- //cpu_temp = Get_CPU_Temp();
- cpu_temp = 37.7;
- printf("\n\nCPU温度:%f\n\n",cpu_temp);
- buf_html[143]=(int)(cpu_temp) / 10 % 10 + '0',
- buf_html[144]=(int)(cpu_temp) % 10 + '0',
- buf_html[146]=(int)(cpu_temp * 10) % 10 + '0';
- buf_html[167]=(int)(dht11_temp) / 10 % 10 + '0',
- buf_html[168]=(int)(dht11_temp) % 10 + '0';
- buf_html[189]=(int)(dht11_humi) / 10 % 10 + '0',
- buf_html[190]=(int)(dht11_humi) % 10 + '0';
- //adc_value
- buf_html[214]=(int)(adc_value) / 1000 % 10 + '0',
- buf_html[215]=(int)(adc_value) / 100 %10 + '0';
- buf_html[216]=(int)(adc_value) / 10 % 10 + '0',
- buf_html[217]=(int)(adc_value) % 10 + '0';
- a[31]=len_buf_html/10000%10+'0';
- a[32]=len_buf_html/1000%10+'0';
- a[33]=len_buf_html/100%10+'0';
- a[34]=len_buf_html/10%10+'0';
- a[35]=len_buf_html%10+'0';
- for(len=0;a[len]!='\0';len++)
- putchar(a[len]);
- putchar('\n');
- send(fd_socket_conn,a,len,0);
- for(len=0;buf_html[len]!='\0';len++);
- send(fd_socket_conn,buf_html,len,0);
- free(buf_html);
- close(fd_socket_conn);
- }
- /*
- bzero(sendbuf,100);
- scanf("%s",sendbuf);
- if(sendbuf[0]=='1')
- {
- if(thread_flag==0)
- {
- thread_flag=1;
- pthread_create(&id2,NULL,Thread_CPU_Temp,NULL);
- if (pthread_mutex_init(&mut,NULL))
- {
- printf("互斥锁初始化失败\n");
- }
- if (pthread_cond_init(&cond,NULL))
- {
- printf("cond初始化失败\n");
- }
- }
- }
- else if(sendbuf[0]=='2')
- {
- thread_pause();
- }
- else if(sendbuf[0]=='3')
- {
- thread_resume();
- }
- */
- }
- }
复制代码
TCP接收线程:
- void * Thread_TCP_Web_Recv(void *arg)
- {
- int i,j;
- while(1)
- {
- fd_socket_conn = accept(socket_web_server , (struct sockaddr *)&sockaddr_in_conn , &addrsize);
- if(fd_socket_conn < 0)
- {
- printf("服务器接听失败!\n");
- flag_keep_alive = 0;
- }
- else if(fd_socket_conn >= 0)
- {
- printf("已有客户端成功连接服务器!\n");
- }
- bzero(recvbuf,1000);
- recv(fd_socket_conn,recvbuf,1000,0);
- printf("------\n%s\n------\n",recvbuf);
- if(recvbuf[0]=='G'&&recvbuf[1]=='E'&&recvbuf[2]=='T')
- {
- printf("客户端浏览器发出GET请求\n");
- flag_get = 1;
- flag_post = 0;
- flag_post_once = 1;
- }
- if(recvbuf[0]=='P'&&recvbuf[1]=='O'&&recvbuf[2]=='S'&&recvbuf[3]=='T')
- {
- printf("客户端浏览器发出POST回应\n");
- flag_get = 0;
- flag_post = 1;
- flag_post_once = 1;
- }
- for(i = 0;i <= HTTP_GET_DEFAULT_LEN ; i ++)
- {
- if(recvbuf[i]=='H'&&recvbuf[i+1]=='T'&&recvbuf[i+2]=='T'&&recvbuf[i+3]=='P'&&
- recvbuf[i+4]=='/')
- {
- printf("HTTP协议版本/类型:");
- for(j=i;j<=i+7;j++)
- putchar(recvbuf[j]);
- putchar('\n');
- }
- if(recvbuf[i]=='H'&&recvbuf[i+1]=='o'&&recvbuf[i+2]=='s'&&recvbuf[i+3]=='t')
- {
- printf("主机地址及端口号:");
- for(j=i+6;j<=i+22;j++)
- putchar(recvbuf[j]);
- putchar('\n');
- }
- if(recvbuf[i]=='C'&&recvbuf[i+1]=='o'&&recvbuf[i+2]=='n'&&recvbuf[i+3]=='n'&&
- recvbuf[i+4]=='e'&&recvbuf[i+5]=='c'&&recvbuf[i+6]=='t'&&recvbuf[i+7]=='i'&&
- recvbuf[i+8]=='o'&&recvbuf[i+9]=='n')
- {
- printf("连接方式:");
- for(j=i+12;j<=i+21;j++)
- putchar(recvbuf[j]);
- putchar('\n');
- flag_keep_alive = 1;
- }
- if(recvbuf[i]=='l'&&recvbuf[i+1]=='e'&&recvbuf[i+2]=='d'&&recvbuf[i+3]=='_'&&
- recvbuf[i+4]=='s'&&recvbuf[i+5]=='w'&&recvbuf[i+6]=='i'&&recvbuf[i+7]=='t'&&
- recvbuf[i+8]=='c'&&recvbuf[i+9]=='h'&&recvbuf[i+10]=='=')
- {
- printf("检测到LED控制指令:\n");
- if(recvbuf[i+11]=='o'&&recvbuf[i+12]=='n')
- {
- printf("LED开\n");
- //LED_Control(1);
- }
- else if(recvbuf[i+11]=='o'&&recvbuf[i+12]=='f'&&recvbuf[i+13]=='f')
- {
- printf("LED关\n");
- //LED_Control(0);
- }
- }
- }
- }
- }
复制代码
Makefile:
- PROG_UDP_IMAGE = udpimage
- SRCS_UDP_IMAGE = main.cc camera.cc tcp_udp_app.cc lcd.cc hid.cc
- CC = g++
- CLEANFILES = $(PROG_MAIN)
- INCLUDES ?=
- CFLAGS += -ljpeg -lpthread -ludev
- LDFLAGS ?=
- all: $(PROG_UDP_IMAGE)
- $(PROG_UDP_IMAGE): $(SRCS_UDP_IMAGE)
- $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(INCLUDES)
- clean:
- rm -f $(CLEANFILES)
复制代码
QT上位机应用程序:
debug.haozip01.zip
(9 MB, 下载次数: 4)
|
|