|
|
本帖最后由 isilcala 于 2013-9-12 06:46 编辑
大家好哈,俺是个纯新人,对单片机一无所知,误打误撞的发现了Arduino,然后网上看了两天貌似挺好玩的就下手买了……
下午收到的东西,晚上就折腾出了这么个东西。就是红外线遥控灯的亮暗啦。不过灯可以有长亮长暗,闪烁,呼吸,定时暗几种不同的亮法。
效果是酱紫的:
代码如下:
- #include <IRremote.h> // 使用IRRemote函数库
- struct IRResult //红外线结果
- {
- int lastValue; //最后一次接收到的值
- unsigned long lastMillis; //最后一次接收到的时间
- };
- enum LightType //灯光类型
- {
- onoff, //toggle型
- blink, //闪烁
- breathing, //呼吸灯
- timedOff //定时关闭
- };
- struct Light
- {
- const int IRValue; //对应的红外代码
- const byte pinNumber; //对应Arduino针脚号
- const LightType type; //灯类型
- int para; //自定义参数
- bool isOn; //是否开启
- byte status; //额外附加状态参数
- unsigned long lastMillis; //最后更新状态时间
- };
- const byte lightsCount = 5; //灯总数量
- Light lights[lightsCount] = { //初始化灯组
- {
- 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[i].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[i].IRValue == irr.lastValue)
- {
- setLight(i); //初设对应灯的状态
- }
- }
- }
- irrecv.resume(); // 继续等待接收下一组信号
- }
- }
- void setLight(int i) //初设对应灯的状态
- {
- lights[i].isOn = !lights[i].isOn; //先反转开关变量
- switch(lights[i].type)
- {
- case timedOff:
- digitalWrite(lights[i].pinNumber, HIGH); //定时关灯则每次按下按钮都认为是开启,即遥控按钮只能开启而不能关闭该灯。该灯只能由定时器关闭。
- break;
- default:
- digitalWrite(lights[i].pinNumber, lights[i].isOn); //根据开关变量设置实际pin脚开还是关
- break;
- }
- lights[i].lastMillis = millis();
- }
- void updateLights()
- {
- for(int i = 0; i < lightsCount; i++)
- {
- switch(lights[i].type)
- {
- case blink:
- if(lights[i].isOn)
- {
- if(lights[i].lastMillis + lights[i].para < millis()) // 延迟para所指定时间后反转状态,状态位保存在status中
- {
- if(lights[i].status == 0)
- {
- lights[i].status = 1;
- digitalWrite(lights[i].pinNumber, HIGH);
- }
- else
- {
- lights[i].status = 0;
- digitalWrite(lights[i].pinNumber, LOW);
- }
- lights[i].lastMillis = millis();
- }
- }
- break;
- case breathing:
- if(lights[i].isOn)
- {
- int t = millis() - lights[i].lastMillis;
- if(lights[i].status == 0) // 状态0表示渐亮
- {
- analogWrite(lights[i].pinNumber, t > 255 ? 255 : t);
- }
- else // 否则渐暗
- {
- t = 255 - t;
- analogWrite(lights[i].pinNumber, t < 0 ? 0 : t);
- }
- if(lights[i].lastMillis + lights[i].para < millis()) // 延迟para所指定时间后反转状态,状态位保存在status中
- {
- if(lights[i].status == 0)
- lights[i].status = 1;
- else
- lights[i].status = 0;
- lights[i].lastMillis = millis();
- }
- }
- break;
- case timedOff: // 定时关闭
- if(lights[i].isOn)
- {
- if((millis() - lights[i].lastMillis) > lights[i].para)
- {
- digitalWrite(lights[i].pinNumber, LOW);
- lights[i].lastMillis = millis();
- lights[i].isOn = 0;
- }
- else
- {
- digitalWrite(lights[i].pinNumber, HIGH);
- }
- }
- break;
- }
- }
- }
复制代码
这个代码在一定程度上应该是比较方便可以扩展。不过几乎没写过C,若有谬误请指正哈。
另外就是发现个很奇怪的问题,以上这个代码,如果呼吸灯是接在11脚上,一开脚上的灯不到1秒钟,整个板子就死机了……如果不开11脚的呼吸灯就没事,其他灯可以一直玩。如果不用11脚,我试了5脚10脚也都是正常的。百思不得其解啊!~请诸位高人赐教~
对了板子是在DFRobot买的意大利进口的原版 Arduino UNO V3 |
|