【萌新笔记】简单记录“智能管家”的设计过程
【新手笔记】"伪"智能管家的设计
智能管家设计的主要流程
本次智能管家的设计使用到S5PV210开发板(属于MPU芯片),基于linux内核(采用GPL协议)的操作系统,使用C语言编写。
智能管家的主要的流程图:
设计代码流程主要思路:通过设计一个Flag和Mod传递参数控制开发板进行动作,用到多线程去开启一个控制摄像头操作的线程和一个控制触摸屏的线程。
其中触摸屏的函数是控制开发板进行其他动作的主要函数。
主函数
关键部分:
while(1){if(Flag == 1) //音乐{bmp_show("./BMPphoto/yinyue.bmp");printf("Music!\n");music_play();}else if(Flag == 2) //相册{ bmp_show("./BMPphoto/xiangce.bmp");printf("Photo_album!\n");Photo_album();}else if(Flag == 3) //视频{ bmp_show("./BMPphoto/shipin.bmp");printf("Video!\n");video();}else if(Flag == 4) //摄像头{ bmp_show("./BMPphoto/shexiangtou.bmp");printf("Camera!\n");linux_v4l2();}else if(Flag == 5) //语音{ bmp_show("./BMPphoto/yuyin.bmp");printf("Welconme To Use Voice!\n");sleep(1);voice();}else if(Flag == 6) //游戏{ bmp_show("./BMPphoto/game.bmp");printf("Game!\n");Game_Play();}
}
主函数主要是实现判断触摸屏传递过来的Flag参数进行对应动作的判断,以及根据Flag进行开发板的动作控制。此外主函数还实现线程的创建(触摸屏线程和摄像头线程)。
音乐
关键部分:
char * cmd = "madplay";char music_name[100][50];bzero( music_name, 5000);music_cont = dir("./Music", ".mp3", music_name);char music_cmd_name[music_cont][50];int fd_mixer = open("/dev/mixer", O_RDWR);if(fd_mixer == -1){perror("open mixer error!\n");return -1;}ret = ioctl( fd_mixer, MIXER_READ(SOUND_MIXER_OGAIN), &vol);if(ret == -1){perror("read SOUND_MIXER_OGAIN ERROR!\n");return -1;}//拆分左右音道left = vol & 0xFF;right = (vol & 0xFF00) >>8; while(1){printf("Now Playing Music!\n");sleep(2);if(Flag == 11) //返回{system("killall madplay");bmp_show("./BMPphoto/main.bmp");Mod = 0;Flag = 0;break;}else if(Flag == 12) //开始播放{ sprintf( music_cmd_name[0], "%s %s &", cmd, music_name[0]);system(music_cmd_name[0]);printf("Flag : %d\n",Flag);Flag = 0;}else if(Flag == 18) //暂停播放{system("killall -SIGSTOP madplay");Flag = 0;}else if(Flag == 19) //继续播放{system("killall -SIGCONT madplay");Flag = 0;}else if(Flag == 13) //下一首{system("killall madplay");if(x >= music_cont) x = 0;sprintf( music_cmd_name[x], "%s %s &", cmd, music_name[x]);system(music_cmd_name[x]);x++;Flag = 0;}else if(Flag == 14) //上一首{system("killall madplay"); if(x < 0) x = music_cont - 1;sprintf( music_cmd_name[x], "%s %s &", cmd, music_name[x]);system(music_cmd_name[x]); x--;Flag = 0;}else if(Flag == 15) //加大音量{left += 3;right += 3;if(left > 100 && right > 100){left = right =100;printf("Sound can't add more\n");}vol = left | (right<<8);ioctl( fd_mixer, MIXER_WRITE(SOUND_MIXER_OGAIN), &vol);Flag = 0;}else if(Flag == 16) //减小音量{left -= 3;right -= 3;if(left < 70 && right <70){left = right =70;printf("Sound can't reduce more\n");} vol = left | (right<<8);ioctl( fd_mixer, MIXER_WRITE(SOUND_MIXER_OGAIN), &vol);Flag = 0;}}
在音乐函数里,主要是实现歌曲的上下首切换和音量调节功能,其中在开发板中,需要移植madplay(用于播放音乐的执行文件),通过system命令调用madplay实现播放音乐的效果。
在播放过程中还调用了列举该文件下所有音乐的命令,通过sprintf函数拼接命令和歌曲名字来实现切换歌曲的效果。
对于音量的调控,是基于调节开发板下的SOUND_MIXER_OGAIN声音增益,控制左右声道合成出完整声道输出,实现音量控制的效果,由于小于70左右几乎听不到声音,故音量最小值控制在70左右。
相册
关键部分:
while(1){if(Flag == 21){bmp_show("./BMPphoto/main.bmp");Mod = 0;Flag = 0;break;}else if(Flag == 22){tmp ++;if(tmp >= bmp_cont){tmp = 0;}lcd_draw_jpg( 0, 0, file_name[tmp]);Flag = 0;}else if(Flag == 23){tmp --;if(tmp < 0){tmp = bmp_cont - 1;}lcd_draw_jpg( 0, 0, file_name[tmp]);Flag = 0;}else if(Flag == 24){while(Flag == 24){tmp = photonum;lcd_draw_jpg( 0, 0, file_name[tmp]);sleep(2);if(photonum >= bmp_cont) photonum = 0;else photonum ++;}}else if(Flag == 25){lcd_draw_jpg( 0, 0, file_name[tmp]);Flag = 0;}}
相册主要是显示JPG格式的图片,而关于JPG格式图片的显示,本萌新暂时没有能力解析,借鉴于老师的功能函数。
视频
//创建管道文件if( -1 == access("/tmp/CuiHua" , F_OK) ) { ret = mkfifo("/tmp/CuiHua", 0777);if (-1 == ret ){perror("mkfifo error ");return -1 ;}printf("mkfifo succeed !\n");}//打开管道文件fd_fifo = open("/tmp/CuiHua", O_RDWR);if ( -1 == fd_fifo){perror("open CuiHua error ");return -1 ;}
视频的实现功能与音乐的功能相似,主要在于视频是采用管道,系统调用mplayer函数。
游戏
游戏主要是关于移植GBA模拟器的执行文件至开发板之中运行,通过系统调用VisualBoyAdvance去运行后缀的游戏,此外不加参数下GBA显示在LCD(800*480)的左上角一小块,加上参数“-3”后会扩展至全屏显示,通过插入键盘至开发板去游玩。
对于游戏,疑惑点在于返回至主界面时,系统调用killall VisualBoyAdvance不能在游戏这个函数体中实现,而是在触摸屏中在反馈退出游戏指令前时调用上述命令才能结束GBA模拟器。
LCD触摸屏
关键代码:
int touch_xy(int *x, int *y)
{int count = 0;int ts_fd = open("/dev/event0", O_RDONLY);if(ts_fd == -1){perror("open ts error\n");return -1;}struct input_event ts_event;while(1){read( ts_fd, &ts_event, sizeof(struct input_event));if(EV_ABS == ts_event.type)if(ABS_X == ts_event.code){*x = ts_event.value;count++;}else if(ABS_Y == ts_event.code){*y = ts_event.value;count++;}if(count == 2){printf("%s: ( %d, %d)\n", __FUNCTION__ ,*x, *y );count = 0;break;}} return 0;
}
先打开开发板中的触摸屏设备(event0)并判断是否打开成功,而输入设备的数据存储在input_event的结构体之中,读取结构的信息,对比定义中触摸屏的定义符EV_ABS,确定为触摸屏事件后,判断松开和按下的情况,ts_event.code的值先是先是x轴的,其次是显示y轴的,由此我们可以判断ABS_X和ABS_Y的值记录LCD触摸屏的输入值,从而实现触摸屏的xy坐标输出,为后续的各功能切换做准备。
摄像头
关键代码:
lcd_init();/* 初始化摄像头设备*/linux_v4l2_device_init("/dev/video3");/* 启动摄像头*/linux_v4l2_start_capturing();char * jpg_name = malloc(20) ;char * Video = malloc(50);char * tmp = "./Video/%d.jpg";while(1){//获取摄像头捕捉的画面linux_v4l2_get_fream(&freambuf);if(Flag == 40)show_video_data(80, 0, freambuf.buf , freambuf.length);else if(Flag == 42){show_video_data(80, 0, freambuf.buf , freambuf.length);photo_num ++ ; bzero(jpg_name , 20);sprintf( jpg_name,"./Video/%d.jpg", photo_num);//打开一个新的文件fd_pic_file = open(jpg_name, O_RDWR | O_CREAT | O_TRUNC , 0666);if ( -1 == fd_pic_file){perror("open pic error ");}//写入摄像头数据ret = write ( fd_pic_file , freambuf.buf , freambuf.length);printf(" Write:%d\n", ret );//关闭文件(如果没关闭相当没保存)close(fd_pic_file);if ( photo_num >= 150 ){video_num ++ ;bzero(Video_name , 20);sprintf( Video_name,"./Video/%d.avi", video_num);//printf("%d\n\n\n",video_num);sprintf(Video,"ffmpeg %s%s -f image2 -i %s", " ",Video_name,tmp);printf("%s\n\n\n",Video);system(Video); //system("ffmpeg -f image2 -i ./Video/%d.jpg ./Video/123.avi");system("rm ./Video/*.jpg");Flag = 0;}}}linux_v4l2_yuyv_quit();
由于在设计中考虑到摄像头的显示问题,在此设计多一个线程去控制摄像头的显示以及录像等功能。对于视频的原理在于拍摄多张照片后,通过移植ffmeg实现JPG照片转换为avi视频的功能。
BMP格式照片显示
关键代码:
//打开LCD设备lcd_fd = open("/dev/fb0", O_RDWR);if(lcd_fd == -1){perror("open lcd device error!\n");return -1;}//内存映射unsigned int *lcd_fb_addr = mmap( NULL, lcd_size, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);if(*(lcd_fb_addr) == -1){perror("mmap error!\n");goto err;}//打开图片bmp_fd = open( pathName, O_RDONLY);if(bmp_fd == -1){perror("open bmp error!\n");return -1;}//读写图片位置偏移ret = lseek( bmp_fd, 54, SEEK_SET);if(ret == -1){perror("lseek error!\n");return -1;}//读取图片信息char bmp_buf[bmp_size];ret = read( bmp_fd, bmp_buf, bmp_size);//printf("read : %d\n", ret);//图片数据处理int lcd_buf[480][800];for(y=0; y<H; y++)for(x=0; x<W; x++){lcd_buf[479-y][x] = bmp_buf[ (y*800 + x)*3 + 0] << 0 | bmp_buf[ (y*800 + x)*3 + 1] << 8 | bmp_buf[ (y*800 + x)*3 + 2] << 16 ;}//写入图片到LCDfor(y=0; y<H; y++)for(x=0; x<W; x++){*(lcd_fb_addr + x + y*800) = lcd_buf [y][x] ;}//关闭图片retval = munmap( lcd_fb_addr, lcd_size);if(retval == -1){perror("unmap fb error\n");return -1;}retval = close(lcd_fd);if(retval == -1){perror("open lcd device error\n");return -1;}return 0;
err:close(lcd_fd);return -1;
BMP格式的照片信息头54个字节是记录照片的各种信息,在本次设计中没有用到,可以用lseek跳过图片的头信息。而对于LCD屏幕(开发板中的fb0文件),实际上是ARGB四个参数,分别对应灰度和RGB三原色。而位深是24位的BMP格式只有RGB三原色,此外实际BMP照片存储的不是规则顺序RGB,而是BGR,故在LCD屏幕上显示BMP格式的照片,需要分别对RGB三原色进行位移对应,才能显示正确的照片颜色。
而采用内存映射mmap的关系,显存,一旦映射关系建立之后,LCD控制器就会自动从显存中读取像素数据传输 给LCD驱动器。这个显示的过程不需要CPU的参与,就可以减少CPU的工作负担。
存在问题与猜想
1、摄像头在拍摄过程中容易出现卡顿,掉帧的现象,使得录像出来的功能画质不佳,猜测有a、线程开设过多,占用CPU过多内存,摄像头工作无法保持流畅,主要原因在于设计代码的不完善(主要原因);b、开发板的芯片型号有点旧。
2、语音功能极度不完善,能运用alsa库等进行录音和上传录音至Linux端,也能实现简单开发板控制动作,主要问题在于自我开发能力不够,不会将语音的返回的ID号整合于自己的代码之中,也就导致无法通过语音控制开发板实现相册,音乐等功能。
本次设计,对我这个萌新来说还是有很大收获的,遗憾是有些挺多功能不完善的,想实现的却技术能力不足,希望将来能继续努力吧,留下这篇文章去记录自己做过的“智能管家”。
【萌新笔记】简单记录“智能管家”的设计过程相关推荐
- (萌新笔记)python的复习笔记
简介:python,作为我在暑假入门的第一门语言,我发现它特别简洁和实用,因此我想记录我的python学习过程,现在刚刚大一入门(我比较弱鸡,所以本文可能会有记录很多我初学时遇到的问题,还请大家斟酌观 ...
- (萌新笔记)C语言的复习笔记
初始时间:大一(上) 10月 更新时间:大一(上) 10月 想了想还是写一下简介吧,我在暑假自学了一点C语言,现在是个大一入门C语言(的弱鸡,所以本文可能会有很多基本知识,还请大家斟酌观看 PS:本文 ...
- (萌新笔记)C++与C的不同
本文设计到的C++知识比较浅薄,只适用于学过一些C语言并想大致看看C++的伙伴 一.引入概念字面量(我知道C语言有,但我那时还没学 定义:字面量(literal)是用于表达源代码中一个固定值的表示法( ...
- Python萌新笔记
Mychael上了大学,对Python产生了浓厚的兴趣,便开始了Python的学习 学习的时候,感觉Python确实比以往学的C++表达简洁很多,而又不失强大 以后的学习笔记就记在这啦 变量 Pyth ...
- 静态文件之static+url控制系统(萌新笔记)
打个比方,当我们在django中用jquery时需要在django文件里建一个static文件,把jquery复制进去,在django中不能直接加jquery的文件.记得用的时候在setting里面最 ...
- 小白萌新笔记——鼠标失灵
针对鼠标左右键间歇性失灵,时不时失灵,完全不能用 情况一:鼠标本身 点击控制面板 进入硬件管理 点击鼠标 先查看是否是鼠标本身有问题 解决方法:更换鼠标查看是否还存在问题! 1.然后可以选择拆开鼠标然 ...
- 复盘《新冠疫苗在线预约系统》设计过程Nodejs+express+Mysql+前端
新冠疫苗预约 使用的技术:nodejs +express +Mysql +html+bootstrap 运行环境:vscode 1. 项目的搭建 检验node环境 确认是否安装node express ...
- 萌新学习Python爬取B站弹幕+R语言分词demo说明
代码地址如下: http://www.demodashi.com/demo/11578.html 一.写在前面 之前在简书首页看到了Python爬虫的介绍,于是就想着爬取B站弹幕并绘制词云,因此有了这 ...
- 刚毕业的职场萌新应具备这9种技能
一年一度的毕业季又到了 不知道各位有没有找到心仪的工作呢 初入职场的萌新 一定是既激动又紧张 今日分享一份职场新人书单 介绍9种职场必备的技能 这既是图灵君多年工作的经验总结 也是送给所有毕业生的一份 ...
- 《机器学习实战》萌新读书笔记 ② — — 第三章 决策树 内容提要、知识拓展和详细注释代码
目录 引入: 什么是决策树? 决策树相较KNN的优势? 决策树的运作方式? 决策树模型的优缺? 决策树的构造: 构造思路 信息增益 划分数据集 递归构造决策树 绘制决策树树形图 Matplotlib注 ...
最新文章
- abstract不能和哪些关键字共存 学习
- nvidia-smi:Failed to initialize NVML: Driver/library version mismatch
- 在HTML文档内引入CSS
- 字节流写数据的两个小问题
- Extjs 4.2 MVC+ThreeJs学习笔记(二)一个简单的ThreeJS场景
- php yii 插入,Yii2 批量插入、更新数据实例
- 30.磁盘 I/O 问题
- 用LeapFTP上传文件碰到的问题及解决办法
- 23种设计模式之工厂模式
- 长城汽车召回上万辆欧拉IQ:电池存在安全隐患,曾因自燃被拉黑
- 黑苹果教程(二)自己制作cdr、dmg镜像
- Java poi读取Excel表格中公式的计算值
- pwnable-passcode
- 无所不能的Java系列文章
- 【无标题】CCSRP是网络与信息安全应急人员认证(现更名为CCSC)
- (CVPR 2020)3DSSD: Point-based 3D Single Stage Object Detector
- Yoshua Bengio, Yann LeCun, Geoffrey Hinton 获 2018 年图灵奖...
- Unity3D基础知识之Camera摄像机及其属性
- DAU、MAU、ARPU等究竟是什么——互联网企业常用指标科普
- A2B 1主多从的实验
热门文章
- CentOS7快速配置服务器网卡聚合双bond方法
- Masked Arrays(numpy arrays掩码)针对数据中存在无效或者确实数据
- java hotspot tm_Java HotSpot(TM) 64-Bit Server VM warning
- 京东注册页开发 HTML5 1014
- 什么是高防ip?高防ip是什么意思?
- 数学三大危机与无穷小微积分
- WindowsStore_LTSC 2019_win10商店恢复包
- 兼容android 6.0以上获取设备编号等权限
- 点成分享 | 麦氏比浊仪在药敏试验中的应用
- 多恩布什《宏观经济学》第十三版笔记和课后答案