极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10330|回复: 2

新手第一个实验,LED多种亮法的红外遥控,附带一个奇怪问题

[复制链接]
发表于 2013-9-11 19:50:53 | 显示全部楼层 |阅读模式
本帖最后由 isilcala 于 2013-9-12 06:46 编辑

大家好哈,俺是个纯新人,对单片机一无所知,误打误撞的发现了Arduino,然后网上看了两天貌似挺好玩的就下手买了……

下午收到的东西,晚上就折腾出了这么个东西。就是红外线遥控灯的亮暗啦。不过灯可以有长亮长暗,闪烁,呼吸,定时暗几种不同的亮法。

效果是酱紫的:


代码如下:

  1. #include <IRremote.h>  // 使用IRRemote函数库

  2. struct IRResult //红外线结果
  3. {
  4.   int lastValue;        //最后一次接收到的值
  5.   unsigned long lastMillis;        //最后一次接收到的时间
  6. };

  7. enum LightType //灯光类型
  8. {
  9.   onoff,         //toggle型
  10.   blink,         //闪烁
  11.   breathing,         //呼吸灯
  12.   timedOff        //定时关闭
  13. };

  14. struct Light
  15. {
  16.   const  int IRValue;        //对应的红外代码
  17.   const  byte pinNumber;        //对应Arduino针脚号
  18.   const  LightType  type;        //灯类型
  19.   int para;                //自定义参数
  20.   bool isOn;        //是否开启
  21.   byte status;        //额外附加状态参数
  22.   unsigned long lastMillis;                //最后更新状态时间
  23. };

  24. const byte lightsCount = 5;                //灯总数量
  25. Light lights[lightsCount] = {                //初始化灯组
  26.   {
  27.     0x6897, 5, onoff          }         //普通toggle灯
  28.   , {
  29.     0x30CF, 8, blink, 500          }        //闪烁灯,闪烁间隔500毫秒
  30.   ,{
  31.     0x18E7, 9, breathing, 1000          }        //呼吸灯,间隔1000毫秒
  32.   ,{
  33.     0x7A85, 10, timedOff, 3000            }                //定时关闭灯,3000毫秒后关闭
  34.   ,{
  35.     0x10EF, 7, onoff  }
  36. };

  37. const int irReceiverPin = 2;  // 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口
  38. IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口
  39. decode_results results;    // 定义results变量为红外结果存放位置

  40. const int debouncingMillis = 100;        //消抖时间100毫秒

  41. IRResult irr;        //用以保存红外线结果

  42. void setup()
  43. {
  44.   Serial.begin(9600);   // 开启串口,波特率为9600
  45.   irrecv.enableIRIn();   // 启动红外解码
  46.   for(int i = 0; i < lightsCount; i++)
  47.   {
  48.     pinMode(lights[i].pinNumber, OUTPUT);
  49.   }
  50. }

  51. void loop()
  52. {
  53.   updateLights();        //更新所有灯的状态

  54.   if (irrecv.decode(&results))
  55.   {
  56.     int r = results.value % 0x10000;        //去除信号前的FF,只保留后四位
  57.     if((r != irr.lastValue) || (millis() > (irr.lastMillis + debouncingMillis)))        //如果消抖间隔内两次信号相同则抛弃
  58.     {
  59.       irr.lastValue = r;
  60.       irr.lastMillis = millis();
  61.       for(int i = 0; i < lightsCount; i++)
  62.       {
  63.         if(lights[i].IRValue == irr.lastValue)
  64.         {
  65.           setLight(i);                //初设对应灯的状态
  66.         }
  67.       }
  68.     }
  69.     irrecv.resume();    // 继续等待接收下一组信号
  70.   }
  71. }

  72. void setLight(int i)        //初设对应灯的状态
  73. {
  74.   lights[i].isOn = !lights[i].isOn;                //先反转开关变量

  75.   switch(lights[i].type)
  76.   {
  77.   case timedOff:
  78.     digitalWrite(lights[i].pinNumber, HIGH);                //定时关灯则每次按下按钮都认为是开启,即遥控按钮只能开启而不能关闭该灯。该灯只能由定时器关闭。
  79.     break;
  80.   default:
  81.     digitalWrite(lights[i].pinNumber, lights[i].isOn);                //根据开关变量设置实际pin脚开还是关
  82.     break;
  83.   }
  84.   lights[i].lastMillis = millis();
  85. }

  86. void updateLights()
  87. {
  88.   for(int i = 0; i < lightsCount; i++)
  89.   {
  90.     switch(lights[i].type)
  91.     {
  92.     case blink:
  93.       if(lights[i].isOn)
  94.       {
  95.         if(lights[i].lastMillis + lights[i].para < millis())                // 延迟para所指定时间后反转状态,状态位保存在status中
  96.         {
  97.           if(lights[i].status == 0)
  98.           {
  99.             lights[i].status = 1;
  100.             digitalWrite(lights[i].pinNumber, HIGH);
  101.           }
  102.           else
  103.           {
  104.             lights[i].status = 0;
  105.             digitalWrite(lights[i].pinNumber, LOW);
  106.           }
  107.           lights[i].lastMillis = millis();
  108.         }
  109.       }
  110.       break;
  111.     case breathing:       
  112.       if(lights[i].isOn)
  113.       {
  114.         int t = millis() - lights[i].lastMillis;
  115.         if(lights[i].status == 0)        // 状态0表示渐亮
  116.         {
  117.           analogWrite(lights[i].pinNumber, t > 255 ? 255 : t);
  118.         }
  119.         else        // 否则渐暗
  120.         {
  121.           t = 255 - t;
  122.           analogWrite(lights[i].pinNumber, t < 0 ? 0 : t);
  123.         }
  124.         if(lights[i].lastMillis + lights[i].para < millis())        // 延迟para所指定时间后反转状态,状态位保存在status中
  125.         {
  126.           if(lights[i].status == 0)
  127.             lights[i].status = 1;
  128.           else
  129.             lights[i].status = 0;
  130.           lights[i].lastMillis = millis();
  131.         }
  132.       }
  133.       break;
  134.     case timedOff:                // 定时关闭
  135.       if(lights[i].isOn)
  136.       {
  137.         if((millis() - lights[i].lastMillis) > lights[i].para)
  138.         {         
  139.           digitalWrite(lights[i].pinNumber, LOW);
  140.           lights[i].lastMillis = millis();
  141.           lights[i].isOn = 0;
  142.         }
  143.         else
  144.         {
  145.           digitalWrite(lights[i].pinNumber, HIGH);
  146.         }
  147.       }
  148.       break;
  149.     }
  150.   }
  151. }
复制代码


这个代码在一定程度上应该是比较方便可以扩展。不过几乎没写过C,若有谬误请指正哈。

另外就是发现个很奇怪的问题,以上这个代码,如果呼吸灯是接在11脚上,一开脚上的灯不到1秒钟,整个板子就死机了……如果不开11脚的呼吸灯就没事,其他灯可以一直玩。如果不用11脚,我试了5脚10脚也都是正常的。百思不得其解啊!~请诸位高人赐教~

对了板子是在DFRobot买的意大利进口的原版 Arduino UNO V3
回复

使用道具 举报

发表于 2013-9-13 08:12:52 | 显示全部楼层
貌似这个库定义的D11脚是红外接收管的输入脚
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-13 16:59:30 | 显示全部楼层
邵林寺 发表于 2013-9-13 08:12
貌似这个库定义的D11脚是红外接收管的输入脚

谢谢,我去翻了一下库文件,但似乎没挖到什么可疑的地方。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-7 17:03 , Processed in 0.036311 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表