isilcala 发表于 2013-9-11 19:50:53

新手第一个实验,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

邵林寺 发表于 2013-9-13 08:12:52

貌似这个库定义的D11脚是红外接收管的输入脚

isilcala 发表于 2013-9-13 16:59:30

邵林寺 发表于 2013-9-13 08:12 static/image/common/back.gif
貌似这个库定义的D11脚是红外接收管的输入脚

谢谢,我去翻了一下库文件,但似乎没挖到什么可疑的地方。。。
页: [1]
查看完整版本: 新手第一个实验,LED多种亮法的红外遥控,附带一个奇怪问题