记录一下我的树莓派遥控器控制程序

树莓派 杨博, 卫 905次浏览 5个评论

好久没有一发了,最近准备把PWM控制的LED三色流水灯换成SPI通讯的8*8点阵屏,但是PWM控制流水灯需要C语言创建多线程,在换成点阵屏之前我就记录一下。这里就不详细注释了。

#include <wiringPi.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lirc/lirc_client.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
#include <softPwm.h>
#include <pthread.h>
//The WiringPi pin numbers used by our LEDs
#define LED1 4 //控制LED1的GPIO
#define LED2 5 //控制LED2的GPIO
#define ON 1
#define OFF 0
//定义LED三元色
#define LedPinRed 21
#define LedPinGreen 22
#define LedPinBlue 23

void flipLED (int led);//反转LED当前的状态
void set_vol(long volume); //关于C语言控制ALSA音量,参见C语言控制树莓派系统音量
long get_vol();
void volup(long vol);
void voldown(long vol);
void mctrl(char *c); //salve模式控制mplayer,详细指令见官方文档
void ledColorSet(unsigned char r_val,unsigned char g_val,unsigned char b_val); // Wiring提供softPWM功能
void breathe(); //多线程实现PWM不停变化流水灯
void ttime(); //语音报时+室内温度(DS18B20),涉及到的脚本见树莓派使用DS18B20读取室内温度并语音播报
void tweather(); //脚本见一个语音播报天气的Shell脚本

int main(int argc, char *argv[])
{
struct lirc_config *config;

//Timer for our buttons
int buttonTimer = millis();
unsigned char mplayer=0;   //mplayer是否正在运行的标志位
char *code;
long vol;                               //储存当前音量
//Initiate WiringPi and set WiringPi pins 4, 5 & 6 (GPIO 23, 24 & 25) to output. These are the pins the LEDs are connected to.
if (wiringPiSetup () == -1){
printf("wiringPiSetup Failed");
exit (1) ;
}
if(mkfifo("/tmp/myfifo",0777)) //创建控制mplayer的pipe
printf("fifo create error\n");
//下面初始化一些GPIO口
pinMode (LED1, OUTPUT);
pinMode (LED2, OUTPUT);
digitalWrite(LED1, OFF);
digitalWrite(LED2, OFF);
pinMode (LedPinRed, OUTPUT);
pinMode (LedPinGreen, OUTPUT);
pinMode (LedPinGreen, OUTPUT);
digitalWrite(LedPinRed, OFF);
digitalWrite(LedPinGreen, OFF);
digitalWrite(LedPinBlue, OFF);
//后面的功能都是用lirc遥控实现的,lirc配置参见搞定树莓派的红外接收,下面程序主体部分来自HOW TO CONTROL THE GPIO ON A RASPBERRY PI WITH AN IR REMOTE
    //Initiate LIRC. Exit on failure
    if(lirc_init("lirc",1)==-1)
    {printf("lirc_init Failed");
        exit(EXIT_FAILURE);}
    //Read the default LIRC config at /etc/lirc/lircd.conf  This is the config for your remote.
    if(lirc_readconfig(NULL,&config,NULL)==0)
    {
        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0)
        {
            //If code = NULL, meaning nothing was returned from LIRC socket,
            //then skip lines below and start while loop again.
            if(code==NULL) continue;{
                //Make sure there is a 400ms gap before detecting button presses.
                if (millis() - buttonTimer  > 300){    //按键去抖
                    //Check to see if the string "KEY_0" appears anywhere within the string 'code'.
                    if(strstr (code,"KEY_0")){        //Key0就是试验一下红外能不能正常工作,正常情况下红灯会闪一下
                        printf("MATCH on KEY_0\n");   //输出日志便于以后检测bug
                        fflush(stdout);               //及时刷新才能显示出来
                        buttonTimer = millis();       //记录时间,用于按键去抖
                        digitalWrite(LedPinRed, ON);  //指示灯闪一下
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                    }
                    if(strstr (code,"KEY_1")){        //用于点亮LED1
                        printf("MATCH on KEY_1\n");
                        fflush(stdout);
                        flipLED(LED1);
                        buttonTimer = millis();
                        digitalWrite(LedPinRed, ON);
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                    }
                    else if(strstr (code,"KEY_2")){   //用于点亮LED1
                        printf("MATCH on KEY_2\n");
                        fflush(stdout);
                        flipLED(LED2);
                        buttonTimer = millis();
                        digitalWrite(LedPinRed, ON);
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                    }
                    else if(strstr (code,"KEY_3")){    //用于打开mplayer
                        digitalWrite(LedPinRed, ON);
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                        printf("MATCH on KEY_3\n");
                        if(!mplayer){
                            printf("Running MPlayer...\n");
                            system("mplayer -volume 35 -softvol -slave -quiet -shuffle -input file=/tmp/myfifo /root/Music/* &");
                            mplayer=1;
                        }
                        else {
                            printf("Quiting Mplayer\n");
                            mctrl("quit 0\n");
                            mplayer=0;
                        }
                        fflush(stdout);
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_4")){   //用于播报时间,温度
                        printf("MATCH on KEY_4\n");
                        fflush(stdout);
                        vol=get_vol();   //记录当前系统音量
                        if(mplayer)
                            mctrl("volume 5 1\n");  //降低当前音乐的音量
                        set_vol(70);      //系统音量调高
                        ttime();
                        set_vol(vol);     //恢复系统音量
                        if(mplayer)
                            mctrl("volume 35 1\n");//恢复当前音乐的音量
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_5")){  //用于打开播报天气
                        printf("MATCH on KEY_5\n");
                        fflush(stdout);
                        vol=get_vol();
                        if(mplayer)mctrl("volume 5 1\n");
                        set_vol(70);
                        tweather();
                        set_vol(vol);
                        if(mplayer)
                            mctrl("volume 35 1\n");
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_PLAYPAUSE")){  //mplayer暂停
                        digitalWrite(LedPinRed, ON);
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                        printf("MATCH on KEY_PLAYPAUSE\n");
                        fflush(stdout);
                        mctrl("pause\n");
                        buttonTimer = millis();
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_LEFT")){  //mplayer上一曲
                        digitalWrite(LedPinRed, ON);
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                        printf("MATCH on KEY_LEFT\n");
                        fflush(stdout);
                        mctrl("pt_step -1\n");
                        buttonTimer = millis();
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_RIGHT")){   //mplayer下一曲
                        digitalWrite(LedPinRed, ON);
                        delay(100);
                        digitalWrite(LedPinRed, OFF);
                        printf("MATCH on KEY_RIGHT\n");
                        fflush(stdout);
                        mctrl("pt_step 1\n");
                        buttonTimer = millis();
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_9")){    //关机
                        if(millis() - buttonTimer  < 1300){  //双击执行关机
                            printf("Shuting Down\n");
                            fflush(stdout);
                            system("shutdown -h 0");      
                            digitalWrite(LedPinRed, ON);
                            delay(100);
                            digitalWrite(LedPinRed, OFF);
                        }
                        buttonTimer = millis();
                    }
                    else if(strstr (code,"KEY_8")){  //关机
                        if(millis() - buttonTimer  < 1300){//双击执行重启
                            printf("Rebooting\n");
                            fflush(stdout);
                            digitalWrite(LedPinRed, ON);
                            delay(100);
                            digitalWrite(LedPinRed, OFF);
                            system("shutdown -r 0");      }
                        buttonTimer = millis();

                    }
                }
                if(strstr (code,"KEY_VOLUMEDOWN")){ //mplayer音量减
                    digitalWrite(LedPinRed, ON);
                    delay(100);
                    digitalWrite(LedPinRed, OFF);
                    printf("MATCH on KEY_VOLUMEDOWN\n");
                    fflush(stdout);
                    voldown(4);
                }
                if(strstr (code,"KEY_VOLUMEUP")){   //mplayer音量加
                    digitalWrite(LedPinRed, ON);
                    delay(100);
                    digitalWrite(LedPinRed, OFF);
                    printf("MATCH on KEY_VOLUMEUP\n");
                    fflush(stdout);
                    volup(4);
                }

            }
            //Need to free up code before the next loop
            free(code);
        }
        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    }
    //lirc_deinit() closes the connection to lircd and does some internal clean-up stuff.
    lirc_deinit();
    exit(EXIT_SUCCESS);
}

void flipLED (int led)
{
    //If LED is on, turn it off. Otherwise it is off, so thefore we need to turn it on.
    if(digitalRead(led)==ON){
        printf("Remote light off");
        digitalWrite(led, OFF);
    }
    else{
        printf("Remote light on");
        digitalWrite(led, ON);
    }
}

void mctrl(char *c)
{
    int fd = open("/tmp/myfifo", O_WRONLY);
    write(fd,c,strlen(c));
    close(fd);
}

void set_vol(long volume)
{
    long min, max;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;
    const char *card = "default";                    //不同设备不一样!不能照搬!
    const char *selem_name = "Speaker";      //不同设备不一样!不能照搬!
    snd_mixer_open(&handle, 0);
    snd_mixer_attach(handle, card);
    snd_mixer_selem_register(handle, NULL, NULL);
    snd_mixer_load(handle);
    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, selem_name);
    snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
    snd_mixer_selem_set_playback_volume_all(elem, volume*(max-min)/100+min);
    snd_mixer_close(handle);
}
long get_vol() {
    snd_mixer_t *handle = NULL;
    snd_mixer_elem_t *elem = NULL;
    snd_mixer_selem_id_t *s_elem = NULL;
    long int vol, max, min;

    if (0 < (snd_mixer_open(&handle, 0))) {
        goto error;
    }

    if (0 < (snd_mixer_attach(handle, "default"))) {   //不同设备不一样!不能照搬!
        goto error;
    }

    if (0 < (snd_mixer_selem_register(handle, NULL, NULL))) {
        goto error;
    }

    if (0 < (snd_mixer_load(handle))) {
        goto error;
    }

    snd_mixer_selem_id_malloc(&s_elem);
    if (NULL == s_elem) {
        goto error;
    }

    snd_mixer_selem_id_set_name(s_elem, "Speaker");     //不同设备不一样!不能照搬!
    if (NULL == (elem = snd_mixer_find_selem(handle, s_elem))) {
        goto error;
    }

    /* Use `set' to change the current volume value */
    if (0 < (snd_mixer_selem_get_playback_volume(elem, 0, &vol))) { goto error; } snd_mixer_selem_get_playback_volume_range(elem, &min, &max); snd_mixer_selem_id_free(s_elem); snd_mixer_close(handle); // printf("%s %ld%%\n", "Volume set to", (vol-min) * 100 / max-min); return (vol-min)*100/(max-min); error: if (NULL != s_elem) { snd_mixer_selem_id_free(s_elem); s_elem = NULL; } if (NULL != handle) { snd_mixer_close(handle); handle = NULL; } } void volup(long vol){ long volume=get_vol(); volume+=vol; if(volume>100)volume=100;
    set_vol(volume);
    printf("system volume set to %d%\n",volume);
    fflush(stdout);
}
void voldown(long vol){
    long volume=get_vol();
    volume-=vol;
    if(volume<0)volume=0;
    set_vol(volume);
    printf("system volume set to %d%\n",volume);
    fflush(stdout);
}

void ledColorSet(unsigned char r_val,unsigned char g_val,unsigned char b_val)
{
    softPwmWrite(LedPinRed,   r_val);
    softPwmWrite(LedPinGreen, g_val);
    softPwmWrite(LedPinBlue,  b_val);
}
void breathe()  //softPWM实现跑马灯变色
{
    int i=0;
    int j=0;
    int k=0;
    for(i=0;i<200;i++)
    {ledColorSet(i,j,k);delay(10);}
    while(1){
        for(i=200;k<200;k++,i--)
        {ledColorSet(i,j,k);delay(10);}
        for(k=200;j<200;k--,j++)
        {ledColorSet(i,j,k);delay(10);}
        for(j=200;k<200;k++,j--)
        {ledColorSet(i,j,k);delay(10);}
        for(k=200;j<200;k--,j++)
        {ledColorSet(i,j,k);delay(10);}
        for(j=200;i<200;j--,i++)
        {ledColorSet(i,j,k);delay(10);}
        for(i=200;k<200;i--,k++)
        {ledColorSet(i,j,k);delay(10);}
        for(k=200;i<200;k--,i++)
        {ledColorSet(i,j,k);delay(10);}
    }
}
void ttime()   //语音报时的时候跑马灯不停变色,要用到多线程,所以我单独写了一个函数
{
    softPwmCreate(LedPinRed,  0, 256);
    softPwmCreate(LedPinGreen,0, 256);
    softPwmCreate(LedPinBlue, 0, 256);
    pthread_t pwm;
    int ret;
    ret=pthread_create(&pwm,NULL,(void  *)breathe,NULL);  //创建线程
    if(ret!=0)
        printf("Create pthread error!\n");
    system("/root/ttime.sh");
    pthread_cancel (pwm) ;
    pthread_join   (pwm, NULL) ;
    softPwmStop(LedPinBlue);
    softPwmStop(LedPinRed);
    softPwmStop(LedPinGreen);
}
void tweather()  //语音播报天气,同上
{
    softPwmCreate(LedPinRed,  0, 256);
    softPwmCreate(LedPinGreen,0, 256);
    softPwmCreate(LedPinBlue, 0, 256);
    pthread_t pwm;
    int ret;
    ret=pthread_create(&pwm,NULL,(void  *)breathe,NULL);
    if(ret!=0)
        printf("Create pthread error!\n");
    system("/root/tweather.sh");
    pthread_cancel (pwm) ;
    pthread_join   (pwm, NULL) ;
    softPwmStop(LedPinBlue);
    softPwmStop(LedPinRed);
    softPwmStop(LedPinGreen);
}

本文只是我自己记录,不做过多解释,不懂的地方需要大家自己探索


本文版权:霜之哀伤 转载请注明记录一下我的树莓派遥控器控制程序
喜欢 (3)or分享 (0)
杨博, 卫
关于作者:
喜欢折腾路由器,懂一点Linux,最近正在学习树莓派...
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(5)个小伙伴在吐槽
  1. 5aimiku
    树莓派3都降价了。socialstock上特价5折
    5aimiku2016-10-10 20:31 回复
    • 杨博, 卫
      树莓派2还是够用的,虽然买了RaspberryPi3回来估计可以做软路由了,而且性能还是很让我心动的。不过还没有大的升级,等到处理器什么时候不需要主动散热了我再买 :evil:
      杨博, 卫2016-10-12 17:47 回复
      • 5aimiku
        2不够嘛。我觉得足以软路由了。主要还是半价
        5aimiku2016-10-12 19:06 回复
        • 杨博, 卫
          因为没有自带wifi啊,USB无线网卡我试了好几个,稳定性都不好,设备一多就掉线。。。
          杨博, 卫2016-10-13 15:24 回复
          • 5aimiku
            ..不要这么蛋疼吧
            5aimiku2016-10-13 17:17