新手第一个实验,LED多种亮法的红外遥控,附带一个奇怪问题
本帖最后由 isilcala 于 2013-9-12 06:46 编辑大家好哈,俺是个纯新人,对单片机一无所知,误打误撞的发现了Arduino,然后网上看了两天貌似挺好玩的就下手买了……
下午收到的东西,晚上就折腾出了这么个东西。就是红外线遥控灯的亮暗啦。不过灯可以有长亮长暗,闪烁,呼吸,定时暗几种不同的亮法。
效果是酱紫的:
http://v.youku.com/v_show/id_XNjA3OTExNzQ0.html
代码如下:
#include <IRremote.h>// 使用IRRemote函数库
struct IRResult //红外线结果
{
int lastValue; //最后一次接收到的值
unsigned long lastMillis; //最后一次接收到的时间
};
enum LightType //灯光类型
{
onoff, //toggle型
blink, //闪烁
breathing, //呼吸灯
timedOff //定时关闭
};
struct Light
{
constint IRValue; //对应的红外代码
constbyte pinNumber; //对应Arduino针脚号
constLightTypetype; //灯类型
int para; //自定义参数
bool isOn; //是否开启
byte status; //额外附加状态参数
unsigned long lastMillis; //最后更新状态时间
};
const byte lightsCount = 5; //灯总数量
Light lights = { //初始化灯组
{
0x6897, 5, onoff } //普通toggle灯
, {
0x30CF, 8, blink, 500 } //闪烁灯,闪烁间隔500毫秒
,{
0x18E7, 9, breathing, 1000 } //呼吸灯,间隔1000毫秒
,{
0x7A85, 10, timedOff, 3000 } //定时关闭灯,3000毫秒后关闭
,{
0x10EF, 7, onoff}
};
const int irReceiverPin = 2;// 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口
IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口
decode_results results; // 定义results变量为红外结果存放位置
const int debouncingMillis = 100; //消抖时间100毫秒
IRResult irr; //用以保存红外线结果
void setup()
{
Serial.begin(9600); // 开启串口,波特率为9600
irrecv.enableIRIn(); // 启动红外解码
for(int i = 0; i < lightsCount; i++)
{
pinMode(lights.pinNumber, OUTPUT);
}
}
void loop()
{
updateLights(); //更新所有灯的状态
if (irrecv.decode(&results))
{
int r = results.value % 0x10000; //去除信号前的FF,只保留后四位
if((r != irr.lastValue) || (millis() > (irr.lastMillis + debouncingMillis))) //如果消抖间隔内两次信号相同则抛弃
{
irr.lastValue = r;
irr.lastMillis = millis();
for(int i = 0; i < lightsCount; i++)
{
if(lights.IRValue == irr.lastValue)
{
setLight(i); //初设对应灯的状态
}
}
}
irrecv.resume(); // 继续等待接收下一组信号
}
}
void setLight(int i) //初设对应灯的状态
{
lights.isOn = !lights.isOn; //先反转开关变量
switch(lights.type)
{
case timedOff:
digitalWrite(lights.pinNumber, HIGH); //定时关灯则每次按下按钮都认为是开启,即遥控按钮只能开启而不能关闭该灯。该灯只能由定时器关闭。
break;
default:
digitalWrite(lights.pinNumber, lights.isOn); //根据开关变量设置实际pin脚开还是关
break;
}
lights.lastMillis = millis();
}
void updateLights()
{
for(int i = 0; i < lightsCount; i++)
{
switch(lights.type)
{
case blink:
if(lights.isOn)
{
if(lights.lastMillis + lights.para < millis()) // 延迟para所指定时间后反转状态,状态位保存在status中
{
if(lights.status == 0)
{
lights.status = 1;
digitalWrite(lights.pinNumber, HIGH);
}
else
{
lights.status = 0;
digitalWrite(lights.pinNumber, LOW);
}
lights.lastMillis = millis();
}
}
break;
case breathing:
if(lights.isOn)
{
int t = millis() - lights.lastMillis;
if(lights.status == 0) // 状态0表示渐亮
{
analogWrite(lights.pinNumber, t > 255 ? 255 : t);
}
else // 否则渐暗
{
t = 255 - t;
analogWrite(lights.pinNumber, t < 0 ? 0 : t);
}
if(lights.lastMillis + lights.para < millis()) // 延迟para所指定时间后反转状态,状态位保存在status中
{
if(lights.status == 0)
lights.status = 1;
else
lights.status = 0;
lights.lastMillis = millis();
}
}
break;
case timedOff: // 定时关闭
if(lights.isOn)
{
if((millis() - lights.lastMillis) > lights.para)
{
digitalWrite(lights.pinNumber, LOW);
lights.lastMillis = millis();
lights.isOn = 0;
}
else
{
digitalWrite(lights.pinNumber, HIGH);
}
}
break;
}
}
}
这个代码在一定程度上应该是比较方便可以扩展。不过几乎没写过C,若有谬误请指正哈。
另外就是发现个很奇怪的问题,以上这个代码,如果呼吸灯是接在11脚上,一开脚上的灯不到1秒钟,整个板子就死机了……如果不开11脚的呼吸灯就没事,其他灯可以一直玩。如果不用11脚,我试了5脚10脚也都是正常的。百思不得其解啊!~请诸位高人赐教~
对了板子是在DFRobot买的意大利进口的原版 Arduino UNO V3 貌似这个库定义的D11脚是红外接收管的输入脚 邵林寺 发表于 2013-9-13 08:12 static/image/common/back.gif
貌似这个库定义的D11脚是红外接收管的输入脚
谢谢,我去翻了一下库文件,但似乎没挖到什么可疑的地方。。。
页:
[1]