利用GPIO发送遥控器信号

利用开发板GPIO模拟出方波,转换成遥控器信号。

一、硬件(R4电阻改成300多欧,太大了遥控头功率低)

请添加图片描述

二、控制代码testIR.c

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <asm-generic/fcntl.h>
#include <asm-generic/ioctl.h>

#define PANEL_NAME "/dev/gxpanel0"
#define _PANEL 'P'
#define PANEL_GPIO_HIGH      _IOW(_PANEL, 0x0A, uint32_t)
#define PANEL_GPIO_LOW       _IOW(_PANEL, 0x0B, uint32_t)

uint32_t pin = 68;
int fd;

//k=100000 370HZ,  k=1000 34KHZ, k=895 38KHZ
#define K38(V) do{volatile unsigned int k;for(k=0;k<V;k++)__asm__ volatile ("nop");}while(0)

#define HH(t) \
        do { \
            int i = t; \
            do { \
                ioctl(fd, PANEL_GPIO_HIGH, &pin);K38(894); \
                ioctl(fd, PANEL_GPIO_LOW, &pin); K38(894); \
            } while(--i > 0); \
        } while(0)
#define LL(t) \
        do { \
            int i = t; \
            ioctl(fd, PANEL_GPIO_LOW, &pin); \
            do { K38(1923); } while(--i > 0); \
        } while(0)

#define HH9000    HH(342) //38000*0.009
#define LL4500    LL(171) //38000*0.0045
#define HH560     HH(21)  //38000*0.000560
#define LL560     LL(21)  //38000*0.000560
#define LL1680    LL(64)  //38000*0.001680

void Irda_SendBytes(uint32_t user, uint32_t key)
{
    uint8_t v;
    uint32_t data;

    if (key == -1)
        data = user;
    else
        data = ((~key & 0xFF) << 24) | ((key & 0xFF) << 16) |
               ((~user & 0xFF) << 8) | (user & 0xFF);
    printf("==>Irda_SendBytes:%X\n", data);
    HH9000;
    LL4500;
    for(v = 0; v <= 32; v++) {
        HH560;
        if(data & 0x80000000) {
            LL560;
        } else {
            LL1680;
        }
        data <<= 1;
    }
    LL560;
}

long long getMilliseconds(struct timespec start, struct timespec end) {
    long long startMs = (long long)(start.tv_sec * 1000) + (long long)(start.tv_nsec / 1000000);
    long long endMs = (long long)(end.tv_sec * 1000) + (long long)(end.tv_nsec / 1000000);
    return endMs - startMs;
}

void Adj38K()
{
    struct timespec startTime, endTime;

    clock_gettime(CLOCK_MONOTONIC, &startTime);
    //HH(2280000); // need 60s, 38000*60=2280000
    LL(2280000);  //need 60s, 38000*60=2280000
    clock_gettime(CLOCK_MONOTONIC, &endTime);
    long long elapsedTime = getMilliseconds(startTime, endTime);
    printf("timespec(ms):%lld\n", elapsedTime);
    exit(0);
}

int main(int argc, char **argv)
{
    uint32_t arg1, arg2;

    if (argc > 1) {
        char *p = argv[1];
        if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
            arg1 = strtoul(p, NULL, 16);
        else
            arg1 = strtoul(p, NULL, 10);
    }
    if (argc > 2) {
        char *p = argv[2];
        if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
            arg2 = strtoul(p, NULL, 16);
        else
            arg1 = strtoul(p, NULL, 10);
    }
    fd = open(PANEL_NAME, O_RDWR);
    if( fd < 0 ) {
        printf("Error: panel fd:%d\n", fd);
        return;
    }

    //Adj38K(); //校准38K方波

    if (argc == 2) {
        if (arg1 == 0)
            ioctl(fd, PANEL_GPIO_LOW, &pin);
        else if (arg1 == 1)
            ioctl(fd, PANEL_GPIO_HIGH, &pin);
        else
            Irda_SendBytes(arg1, -1);
    } else if (argc == 3) {
        Irda_SendBytes(arg1, arg2);
    } else {
        /*do {
            Irda_SendBytes(0x11, 0x22);
            usleep(1000000);
        } while(1);*/
    }
    close(fd);
}

生成可执行代码,其中/dev/panel0设备自己开发,就是简单的控制GPIO高低点位

arm-linux-gnueabihf-gcc -D LINUX_OS -g -O0 testIR.c -o testIR

修改连接板子的ttyUSB0权限

sudo chmod 666 /dev/ttyUSB0

测试,在串口终端里运行

echo -e "/testIR 0xBB444FB0" > /dev/ttyUSB0

三、网页发送遥控器信号

在开发板的开发电脑上安装lighttpd

sudo apt install lighttpd

配置好web目录,启动 lighttpd
安装CGI模块

sudo apt-get install lighttpd-mod-cgi
sudo lighttpd-enable-mod cgi
sudo service lighttpd restart

修改CGI配置/etc/lighttpd/conf-enabled/10-cgi.conf

# /usr/share/doc/lighttpd/cgi.txt

server.modules += ( "mod_cgi" )

$HTTP["url"] =~ "^/execute-script/" {
        cgi.assign = ( ".py" => "/usr/bin/python" )
}

重启lighttpd

sudo service lighttpd restart

添加CGI脚本execute-script/script.py

这是测试脚本,把测试脚本改成执行命令echo -e “/testIR 0xBB444FB0” > /dev/ttyUSB0,就可以达到网页控制遥控器信号

#!/usr/bin/python

import cgi
import os

form = cgi.FieldStorage()

print("Content-type: text/html\n\n")
print("<html><body>")
print("<h1>POST Data:</h1>")
print("<ul>")
for key in form.keys():
    print("<li>{0}:{1}</li>".format(key, form[key].value))
    os.system("echo -e '' > /dev/ttyUSB0")
    os.system("echo -e '/testIR "+form[key].value+"' > /dev/ttyUSB0")
print("</ul>")
print("</body></html>")

网页使用CGI

测试代码,使用POST发送到CGI

<!DOCTYPE html>
<html>
<head>
    <title>遥控器</title>
	<meta charset="utf-8">
    <style>
		.button {
			position: absolute; 
			width: 90px;
			height: 30px;
			background-color: #ccc;
			border-radius: 12px;
			display: flex;
			justify-content: center;
			align-items: center;
			font-size: 20px;
			cursor: pointer;
			transition: background-color 0.3s ease;
		}
		.button.active {
			background-color: #ff0000;
		}
    </style>
</head>
<body>    
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40c43b')" style="left: 10px; top: 10px;">Power</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f402ed1')" style="left: 310px; top: 10px;">Mute</div>
	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f406c93')" style="left: 10px; top: 50px;">►||</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40ec13')" style="left: 110px; top: 50px;">USB/■</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f406699')" style="left: 210px; top: 50px;">Rec</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f404cb3')" style="left: 310px; top: 50px;">Info</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f401ce3')" style="left: 10px; top: 90px;">|◄◄</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f409c63')" style="left: 110px; top: 90px;">►►|</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f405ca3')" style="left: 210px; top: 90px;">◄◄</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40dc23')" style="left: 310px; top: 90px;">►►</div>
	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4006f9')" style="left: 30px; top: 130px;">Fav</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4026d9')" style="left: 290px; top: 130px;">Sat</div>

	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40847b')" style="left: 160px; top: 150px;"></div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4024db')" style="left: 60px; top: 190px;"></div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40a45b')" style="left: 160px; top: 190px;">OK</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40e41b')" style="left: 260px; top: 190px;"></div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40946b')" style="left: 160px; top: 230px;"></div>
	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40d42b')" style="left: 30px; top: 250px;">Menu</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4014eb')" style="left: 290px; top: 250px;">Exit</div>
	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4046b9')" style="left: 30px; top: 290px;">SUBTITLE</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f403ec1')" style="left: 160px; top: 290px;">RECALL</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40f40b')" style="left: 290px; top: 290px;">PAGE+</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4044bb')" style="left: 30px; top: 330px;">TXT</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f408c73')" style="left: 160px; top: 330px;">AUDIO</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40cc33')" style="left: 290px; top: 330px;">PAGE-</div>	
	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f408e71')" style="left: 30px; top: 370px;">1</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f409e61')" style="left: 160px; top: 370px;">2</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f400ef1')" style="left: 290px; top: 370px;">3</div>	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40b649')" style="left: 30px; top: 410px;">4</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f401ee1')" style="left: 160px; top: 410px;">5</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4036c9')" style="left: 290px; top: 410px;">6</div>	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f409669')" style="left: 30px; top: 450px;">7</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40be41')" style="left: 160px; top: 450px;">8</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4016e9')" style="left: 290px; top: 450px;">9</div>	
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f4004fb')" style="left: 30px; top: 500px;">EPG</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f40a659')" style="left: 160px; top: 500px;">0</div>
	<div class="button" onmousedown="toggleButton(this)" onmouseup="sendButton(event, '0x7f406e91')" style="left: 290px; top: 500px;">TV/RADIO</div>
    <script>
        function toggleButton(button) {
            button.classList.toggle('active');
        }

        function sendButton(event, keyValue) {
            const button = event.target;
			const key = keyValue
            fetch('execute-script/script.py', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
				body: "key="+key
            })
            .then(response => {
                button.classList.remove('active'); //恢复按键的原始颜色
            })
            .catch(error => {
                button.classList.remove('active'); //恢复按键的原始颜色
            });
        }
    </script>
</body>
</html>

效果图
在这里插入图片描述

附:美的遥控器资料

#define MIDEA_HDR_MARK    4500
#define MIDEA_HDR_SPACE   4500
#define MIDEA_BIT_MARK    560
#define MIDEA_ONE_SPACE   1680
#define MIDEA_ZERO_SPACE  560
#define MIDEA_STOP_SPACE  4500

void IRsend::sendMIDEA(unsigned long data, int nbits) {
	unsigned long address = 0xB24D;
	enableIROut(38);
	//leader code
	mark(MIDEA_HDR_MARK);
	space(MIDEA_HDR_SPACE);
	//address code
	for (int i = 0; i < 16; i++) {
		if (address & 0x8000) {
			mark(MIDEA_BIT_MARK);
			space(MIDEA_ONE_SPACE);
		} else {
			mark(MIDEA_BIT_MARK);
			space(MIDEA_ZERO_SPACE);
		}
		address <<= 1;
	}
	//data code
	for (int i = 0; i < nbits; i++) {
		if (data & 0x80000000) {
			mark(MIDEA_BIT_MARK);
			space(MIDEA_ONE_SPACE);
		} else {
			mark(MIDEA_BIT_MARK);
			space(MIDEA_ZERO_SPACE);
		}
		data <<= 1;
	}
	//stop code
	mark(MIDEA_BIT_MARK);
	space(MIDEA_STOP_SPACE);
}

修改完后,保存即可。
可以通过如下例子调用:
#include <IRremote.h>

IRsend irsend;
void setup()
{
  Serial.begin(9600);
}

void loop() {
  irsend.sendMIDEA(0x7B84E01F, 32);
  irsend.sendMIDEA(0x7B84E01F, 32);
  delay(5000);
}

注: 上面的例子有两行相同的 irsend.sendMIDEA(0x7B84E01F, 32);  这个是因为美的空调(R51D)协议 一次按键重复发两次,所以要执行两次。
关闭 0x7B84E01F
摆风 0x6B94E01F
强劲 0xF50AA25D
清新 0xF50AA35C
数显 0xF50AA55A
风向 0x1FE044BB
开:根据温度不同数据码不同,下面一一列表:
170x1FE008F7
180x1FE018E7
190x1FE038C7
200x1FE028D7
210x1FE06897
220x1FE07887
230x1FE058A7
240x1FE048B7
250x1FE0C837
260x1FE0D827
270x1FE09867
280x1FE08877
290x1FE0A857
300x1FE0B847
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值