树莓派B+的红外设置网上很多,简单来说就是通过ssh连接到树莓派之后,进行执行以下命令:“apt-get install lirc”. 如果一切顺利,那么这个时候可以参照之前的博客,树莓派 红外接收 RPi2 gpio chip not found lirc_rpi。如果和我一样不幸遇到无法检测到红外设备的情况,也可以参照之前的博客进行troubleshooting。
当你成功录制按键之后,接下来需要的是配置lircrc, 目录是在/etc/lirc/lircrc 。这个文件的目的就是让红外lirc后台程序运行时候,接收到每个按键会触发什么行为。这个配置文件的编写占据了比较大的effort。现附上我的配置文件,再进行详细解释。
begin
prog = irexec
button = stop
repeat = 2
delay = 2
config = /root/douban_fm/fifowrite.exe q
end
begin
prog = irexec
button = mute
config = /root/douban_fm/fifowrite.exe m
end
begin
prog = irexec
button = next
config = /root/douban_fm/fifowrite.exe n
end
begin
prog = irexec
button = pause
config = /root/douban_fm/fifowrite.exe p
end
begin
prog = irexec
button = volume_up
config = /root/douban_fm/fifowrite.exe o
end
begin
prog = irexec
button = volume_down
config = /root/douban_fm/fifowrite.exe i
end
begin
prog = irexec
button = power
repeat = 2
delay = 2
config = sudo sh /root/douban_fm/start_douban.sh
end
在这个配置文件中,比较重要的有三个部分:
这个文件是用来和播放豆瓣的主程序进行通信的程序。将command写入一个pipe文件中,然后播放主程序再通过一个fiforead.exe 程序进行读取。涉及到的按键就是音量增,音量减,暂停,切歌,静音以及退出。
fiforead.c
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
const char *fifo_name = "/root/douban_fm/my_fifo";
int pipe_fd = -1;
int data_fd = -1;
int res = 0;
const int open_mode = O_RDONLY;
char buffer[2];
int bytes_read = 0;
int bytes_write = 0;
memset(buffer, '\0', sizeof(buffer));
// printf("Process %d opening FIFO O_RDINLY\n", getpid());
pipe_fd = open(fifo_name, open_mode);
// data_fd = open("DataFormFIFO.txt", O_WRONLY|O_CREAT, 0644);
// printf("Process %d result %d\n", getpid(), pipe_fd);
if(pipe_fd != -1)
{
do
{
res = read(pipe_fd, buffer, 1);
if(res <= 0)
break;
printf("%s\n", buffer);
// bytes_write = write(data_fd, buffer, res);
bytes_read += res;
}while(res > 0);
close(pipe_fd);
// close(data_fd);
}
else
exit(EXIT_FAILURE);
// printf("Process %d finished, %d bytes read\n", getpid(), bytes_read);
exit(EXIT_SUCCESS);
}
fifowrite.c
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
const char *fifo_name = "/root/douban_fm/my_fifo";
int pipe_fd = -1;
int data_fd = -1;
int res = 0;
const int open_mode = O_WRONLY;
int bytes_sent = 0;
char buffer[2];
if(access(fifo_name, F_OK)==-1)
{
//PIPE file not exist
//Create it
res = mkfifo(fifo_name, 0777);
if(res != 0)
{
fprintf(stderr, "Could not creat fifo %s\n", fifo_name);
exit(EXIT_FAILURE);
}
}
// printf("Process %d opening FIFO O_WRONLY\n", getpid());
pipe_fd = open(fifo_name, open_mode);
// data_fd = open("Data.txt", O_RDONLY);
// printf("Process %d result %d\n", getpid(), pipe_fd);
if(pipe_fd != -1)
{
// int bytes_read = 0;
// bytes_read = read(data_fd, buffer, PIPE_BUF);
buffer[0] = *argv[1];
buffer[1] = '\0';
res = write(pipe_fd, buffer, 1);
/* while(bytes_read > 0)
{
res = write(pipe_fd, buffer, bytes_read);
if(res == -1)
{
fprintf(stderr, "Write err on pipe\n");
exit(EXIT_FAILURE);
}
bytes_sent +=res;
bytes_read = read(data_fd, buffer, PIPE_BUF);
buffer[bytes_read] = '\0';
}*/
close(pipe_fd);
// close(data_fd);
}
else
exit(EXIT_FAILURE);
// printf("Process %d finished\n", getpid());
exit(EXIT_SUCCESS);
}
把这两段代码在树莓派中分别创建两个.c 文件之后,执行命令:
gcc -o ./fifowrite.exe fifowrite.c -lm
gcc -o ./fiforead.exe fiforead.c -lm
这样控制程序的命令就可以通过这段文件共享了。
这段shell做的工作就是在起进程之前先检查系统中是否已经有播放程序在执行了。如果没有就把程序起起来,如果有就退出。
#!/bin/bash
num=`ps aux|grep /root/douban_fm/play_douban.py|grep -v "grep"|wc -l`
if test $num -eq 0 ;
then
aplay /usr/share/scratch/Media/Sounds/Effects/Bubbles.wav
nohup /root/douban_fm/play_douban.py >> /root/mlog/douban_fm.log &
else
exit
fi
在实际过程中遇到的问题是有可能遇到连击或者红外信号的连续发送导致在同一时间起了多个这样的脚本,还是会导致多个播放程序在后台启动。一开始的解决方案是在shell中生成随机数,让其sleep几秒钟,由于sleep时间是随机的,也就可以保证同时起的shell都会启动播放程序。可参见Linux 实现随机数多种方法。本人亲测通过时间的方法获取随机数不成。之后的方法也没有进行尝试。这个问题究其根本就是红外读取信号的时候会在短时间内重复获取信号。
这就是配置文件中第三部分要注意的。
repeat 和delay的含义可以参见官方文档lircrc 配置文件详解。
repeat
告诉程序如果key重复按键之后应该做什么,如果设置成2 就是连按两下会出发什么动作。当默认是0的时候就会忽略重复按键。
好了,现在基本的外围设置已经完成。接下来就是需要进行豆瓣播放程序的开发。详见下一篇