Arduino红外遥控实现灯带循环,颜色设置和持久化

一个cosplay工作室找我做一个游戏中无人机的灯带,要求有组灯,一组是常亮的光圈,另一组是一个在循环的灯带。在这个项目中我分别用到了WS2812的灯带,红外线模组和EEPROM持久化(把数据存储在EEPROM里)。

接下来我会分别列出这三个模块的简单使用方法:

一、灯带模组:

FastLED.h是一个第三方库,编译前要添加库文件,一般灯带使用WS2812。WS2812一般有灯带型,灯珠型,和环形。最常见的就是灯带型的,就先说灯带类型的。

 1、 灯带型:灯带有VCC、GND和DIN三个引脚,VCC接正极,GND接负极,DIN接信号。

  2、 环形:(同上,多一个DOUT,用来输出信号到下一组灯带或者灯环)。

 3、单个灯珠:有VSS、VDD、DIN、DOUT四个引脚。这些引脚有什么用代表什么呢?

VSS:是共用一条地线,把地线并联上整个灯带。

VDD:是共用一条正极,把正极并联上整个灯带。

DIN:是信号输入口,第一颗灯珠接单片机定义的灯带 I/O口,后续的灯珠从第一个灯珠的DOUT接入。

DOUT:是灯珠的信号输出口,用来连接下一个灯珠的DIN口,实现多个灯珠组成灯带。

以下代码是灯带模组常用的设置、指令和一个简单的灯带点亮。

//LED灯带的头文件
#include <FastLED.h>  


//定义灯带长度
#define LED_PIN 2     //定义Din的io口
#define NUM_LEDS 255  
CRGB leds[NUM_LEDS];  //创建一个CRGB格式的数组,数组长度为255


void setup()
{
//添加一个 WS2812 LED灯组,把之前定义的3个数据填上去.
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);

FastLED.setMaxPowerInVoltsAndMilliamps(5, 1500);//设置灯带电压5V,1500mA
}

void loop()
{
//一个简单的灯带点亮,通过一个for循环和CRGB(r,g,b)定义灯带颜色和亮度,最后通过FastLED.show()
//点亮灯带。
for(int i=0;i<100;i++)
{
 leds[i]=CRGB(100,200,100)
}
FastLED.show;


delay(1000);
//LED灯清屏,这里展示一个用于清屏的指令
FastLED.clear();
delay(1000);


}

二、红外遥控模块:

红外模块有红外线接收器遥控器两个部分,遥控器通过发射红外光进信号传输,每个按键都有一个值,红外线接收器把收到的红外光传输到开发板中,转化成一个数字,我们创建一个switch来判断按下哪个按钮。

红外线接收器有3个引脚,DAT、VCC、GND。VCC和GND分别是正极和负极,DAT是信号,接到开发板定义的红外接收引脚。

以下是红外模组的一些常用代码:

//定义第三方头文件(编译代码时记得添加第三方库)
#include<IRremote.h>

//定义红外接收器引脚为13
int RECV_PIN=13;
IRrecv receiver(RECV_PIN);

void setup() 
{
//启动接收器
receiver.enableIRIn();
}

void loop()
{

//把定义的IRkey函数放在loop循环中等待按键按下。
IRkey();
delay(100);
}

//设计一个接收红外信号的函数,首先判断是否接收到红外线,如果接收到就进入translateIR()函数中判断按下
//的按键是哪个,最后允许新信号进入。
void IRkey()
{

//判断是否有红外信号输入
if(receiver.decode())
  {

    //判断按下按键
    translateIR();
    

   delay(100);

   //允许新信号进入
   receiver.resume();//记录新信号
  }
  
}


//定义判断按键的函数,通过检测不同的值来判断按下哪个按键,可以在每个case x:到break的中间定义按键功能
void translateIR()
{
 switch(receiver.decodedIRData.command)
  {
    case 162:
    //POWER 

  
    break;
    case 226:
   
 
    break;

    case 34:
    //TEST  

  
    break;

    case 2:
    //PLUS   

 
    break;

    case 194:
    //BACK
    
    break;

    case 224:
    //PREV


    break;

    case 168:
    //PLAY    

   
    break;

    case 144:
    //NEXT


    break;

    case 104:
    //0

    break;

    case 152:
    //MINUS



    break;
    case 176:
    //C
    

    break;

    case 48:
    //1


    break;

    case 24:
    //2


    break;

    case 122:
    //3
    

    break;

    case 16:
    //4


    break;

    case 56:
    //5


    break;

    case 90:
    //6


    break;

    case 66:
    //7


    break;

    case 74:
    //8


    break;

    case 82:
    //9


    break;
  }
}

三、持久化EEPROM模块:

通过EEPROM我们可以把变量,数据等信息保留在开发板的闪存中,这使得重启后也得以保留数据,要注意的是闪存的容量不大,而且大量擦写会大幅度降低闪存的寿命。要尽量减少擦写次数,不要不加限制的在各种循环中添加存储函数,最好给一些条件来触发擦写。

EEPROM.h是Arduino自带的库,不需要单独添加库文件。

以下是EEPROM库的一些常用代码(更多可以查阅资料):

//定义头文件
#include <EEPROM.h>

//设置内存区域给不同要存储的变量,内部EEPROM的步长是一个字节,每个变量数字最大为255,超出就无法使用
//此处定义了3个空位。
#define EEPROM_ADDR  0
#define EEPROM_ADDR1 2
#define EEPROM_ADDR2 4

//定义3个变量存放数据
int i,j,k;

void setup() 
{

int a=1,b=2,c=3;
//把a、b、c的值存入内存(自定义的函数)
saveValueToEEPROM(a,b,c);
  
//从内存中读取(自定义的函数)
  loadValueFromEEPROM();

//可以自行添加显示i、j、k的其他代码来验证其值


}


//创建一个保存变量的函数,括号中有三个元素,分别对应需要存储的三个数据,可以自己定义存储数量
void saveValueToEEPROM(int value,int value1,int value2) 
{
  
存入数据到空位中
EEPROM.put(EEPROM_ADDR, value);
EEPROM.put(EEPROM_ADDR1, value1);
EEPROM.put(EEPROM_ADDR2, value2);
}


// 从EEPROM加载变量值
void loadValueFromEEPROM() 
{

//读取空位数据到变量中
EEPROM.get(EEPROM_ADDR,i);
EEPROM.get(EEPROM_ADDR1,j);
EEPROM.get(EEPROM_ADDR2, k);
}

最后放上整个项目的代码:

#include <FastLED.h>
#include<IRremote.h>
#include <EEPROM.h>
//红外
int RECV_PIN=13;//定义红外接收器引脚为13
IRrecv receiver(RECV_PIN);
//LED
#define NUM_LEDS 255
#define NUM_LEDS2 17
CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS2];
#define LED_PIN 2
#define LED_PIN2 12
int light_PIN1=3;
int light_PIN2=4;
int light_PIN3=5;
int bk=1;
//设置参数
int setLedLong=5,ledLong=10, del=5;
int r=200,g=200,b=200;
//持久化
#define EEPROM_ADDR  0
#define EEPROM_ADDR1 2
#define EEPROM_ADDR2 4
#define EEPROM_ADDR3 6
#define EEPROM_ADDR4 8
#define EEPROM_ADDR5 10

void setup() {
  // put your setup code here, to run once:
  loadValueFromEEPROM();
  //按钮
pinMode(light_PIN1, INPUT_PULLUP);
digitalWrite(light_PIN1,HIGH);

pinMode(light_PIN2, INPUT_PULLUP);
digitalWrite(light_PIN2,HIGH);

pinMode(light_PIN3, INPUT_PULLUP);
digitalWrite(light_PIN3,HIGH);
//LED
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.addLeds<WS2812, LED_PIN2, GRB>(leds2, NUM_LEDS2);

FastLED.setMaxPowerInVoltsAndMilliamps(5, 1500);
//红外
receiver.enableIRIn();//启动接收器
}
void loop() {
  // put your main code here, to run repeatedly:
  if(bk==1)
  {ringLed();
 IRkey();
danR();}

else if(bk==0){IRkey();FastLED.clear();FastLED.show();delay(500);}
}

void danR()//单灯循环 运行模式1
{
  //可调整
  // setLedLong=4;//设置Led灯带长度
  //ledLong=16;//设置灯带总长度
  // del =5;//灯行走速度

//不可调整
int ruondFstLed=ledLong+1;//循环的第一个灯

  int lastLed=ledLong-1;//最后一个灯的位置

 int LightedLong=0;//初始灯带亮的长度

 //FastLED.clear();
 for(int y=0;y<setLedLong;y++){LightedLong++;ruondFstLed--;}
  for (int i=0; i<ledLong; i++)//i+1整个亮起的灯条就往前一格

  {if(receiver.decode())//红外遥控退出循环
  {FastLED.clear();FastLED.show();break;}//红外遥控退出循环

    for( int j=0;j<LightedLong;j++){ IRkey();//j增加亮起的灯条长度增加
    leds[i+j] = CRGB(r,g, b);//整条亮起灯条的颜色,以后可以通过增加和j有关的变量来改变边缘颜色
    }
    
    for(int k=0;k<setLedLong;k++)//多半是防边缘亮起不灭,并不是,这是整个灯带运行的条件???到底做什么的?
    leds[ledLong+k]=CRGB(0,0,0);//没了这两条代码,整条灯带都卡死,wtf,整个代码都基于这个bug运行吗?
 
    if(i>=ruondFstLed)leds[i-ruondFstLed] = CRGB(r,g, b);//在同一个循环中。说不定可以和上面一起改颜色
     if (digitalRead(light_PIN2) == LOW||digitalRead(light_PIN3) == LOW)//按键切换,移植改可删
      {
       break;
      }
    
    delay(del*50);
leds[i-1]=CRGB(r/3,g/3,b/3);



FastLED.show();
}
leds[lastLed] = CRGB(r/1.5,g/1.5, b/1.5);


}

void ringLed()
{
  for(int i=0;i<17;i++)
  leds2[i] = CRGB(r,g, b);
}


void IRkey()
{
if(receiver.decode())
  {
    translateIR();//按键赋予功能
    
   delay(100);
   receiver.resume();//记录新信号
  }
  
}
void translateIR()
{
  switch(receiver.decodedIRData.command)
  {
    case 162:
    //POWER   模式按键  进入开关模式
 if(bk==1)bk=0;
  else if(bk==0)bk=1;
   
    break;
    case 226:
    //MENU    模式按键 进入设置模式
 
    break;
    case 34:
    //TEST    模式按键 进入测试模式
    saveValueToEEPROM(setLedLong,ledLong,del);
    saveValueClToEEPROM(r,g,b);
    break;
    case 2:
    //PLUS    功能按键
setLedLong++;if(setLedLong>ledLong)setLedLong=0;//灯亮的长度不能超过总长度
    break;
    case 194:
    //BACK
    bk=0;
    break;
    case 224:
    //PREV
del++;if(del>=255)del=255;
    break;
    case 168:
    //PLAY    模式按键 进入运行模式
   

   

    

    
    
    break;
    case 144:
    //NEXT
del--;if(del<=0)del=1;
    break;
    case 104:
    //0

    break;
    case 152:
    //MINUS
setLedLong--;if(setLedLong<0)setLedLong=0;//灯亮的长度不能超过总长度
    break;
    case 176:
    //C重置
    
    ledLong=3;setLedLong=1;del=6;r=200;g=200;b=200;
    leds[9]=CRGB(0,0,0);//发现第九格会有暗光,给它办了

    break;
    case 48:
    //1

ledLong++;
    break;
    case 24:
    //2
    ledLong--;if(ledLong<1)ledLong=1;


    break;
    case 122:
    //3
    

    break;
    case 16:
    //4
r=r+5;rgbs();
    break;
    case 56:
    //5
g=g+5;rgbs();
    break;
    case 90:
    //6
b=b+5;rgbs();
    break;
    case 66:
    //7
r=r-5;rgbs();
    break;
    case 74:
    //8
g=g-5;rgbs();
    break;
    case 82:
    //9
b=b-5;rgbs();
    break;
  }
}

void rgbs()
{
  if(r>255)r=0;
  else if(r<0)r=255;
  if(g>255)g=0;
  else if(g<0)g=255;
  if(b>255)b=0;
  else if(b<0)b=255;
 
}

// 将小段的灯长和总灯长变量值保存到EEPROM
void saveValueToEEPROM(int value,int value1,int value2) {
  
EEPROM.put(EEPROM_ADDR, value);
EEPROM.put(EEPROM_ADDR1, value1);
EEPROM.put(EEPROM_ADDR2, value2);
 
}
void saveValueClToEEPROM(int value3,int value4,int value5) {
  

EEPROM.put(EEPROM_ADDR3, value3);
EEPROM.put(EEPROM_ADDR4, value4);
EEPROM.put(EEPROM_ADDR5, value5);
  
}


// 从EEPROM加载变量值
void loadValueFromEEPROM() {

EEPROM.get(EEPROM_ADDR,setLedLong);
EEPROM.get(EEPROM_ADDR1,ledLong);
EEPROM.get(EEPROM_ADDR2, del);
EEPROM.get(EEPROM_ADDR3, r);
EEPROM.get(EEPROM_ADDR4, g);
EEPROM.get(EEPROM_ADDR5, b);
}

项目硬件连接:

运行代码时按c开始运行程序,c是重置灯带,456789是用来控制灯带颜色的,←和→用来控制灯带循环速度,+-和12分别用来控制灯带总长和高亮灯带长度。 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值