《博哥玩Arduino》- 蓝牙七彩灯优化版V2.0

1.前言

上一篇说到还有两个未优化事项,如下:

  • 未优化事项:可以考虑后期加入记录上一次灯颜色状态,下一次开灯就默认是该颜色
  • 未优化事项:是否可以在板子上加入一个按钮,可以切换常用颜色,不一定每次都用app

2.遇到问题以及解决方案

  • 未优化事项:可以考虑后期加入记录上一次灯颜色状态,下一次开灯就默认是该颜色
    这里就要用到EEPROM这个掉电保存;
  • 未优化事项:是否可以在板子上加入一个按钮,可以切换常用颜色,不一定每次都用app
    本来想加入红外遥控的,但是红外遥控影响了PWM,所以只能用按键;

3.调试代码

/**
* 日期:2016/12/30
* 功能:蓝牙台灯
* 作者:单片机菜鸟
**/
#include<EEPROM.h>

#define BTSerial Serial1
#define MyDebugSerial Serial

//该条语句用于使能DEBUG输出信息,屏蔽掉就不会输出debug调试信息
//#define DEBUG
//该条语句用于使能是共阴RGB  屏蔽掉就是共阳RGB
//#define COMMON_GND

#ifdef DEBUG
#define DBGLN(message)    MyDebugSerial.println(message)
#else
#define DBGLN(message)
#endif

#define MAX  7
#define KEY  7
#define PIN_RED 9
#define PIN_GREEN 10
#define PIN_BLUE 11

#define RED_ADDR 0  //红色 eeprom地址
#define BLUE_ADDR 1 //蓝色 eeprom地址
#define GREEN_ADDR 2 //绿色 eeprom地址

int red = 0;//红色
int green = 0;//绿色
int blue = 0;//蓝色
boolean isNeedtoSave = false;//是否需要保存
int saveCountX = 0;//统计当前次数
int saveCountY = 0;//统计当前次数

// 定义记录按键当前状态的变量
int state_btn;
// 定义记录按键最近一次状态变化的变量,并初始化状态为LOW。
int lastButtonState = LOW;
// 定义记录最近一次抖动的时间变量,并初始化时间为0毫秒。
long lastDebounceTime = 0;
// 定义延迟抖动的时间变量
long debouncdDelay = 60;

int currentcode = 0;

//rgb编码
unsigned int rgb_code[MAX][3] = {
  {255,255,255},//白光
  {255,0,0},//红光
  {0,255,0},//绿光
  {0,0,255},//蓝光
  {255,255,0},//黄光
  {0,255,255},//浅蓝
  {255,0,255}//浅紫
};

void setup() {
  pinMode(PIN_RED, OUTPUT);
  pinMode(PIN_GREEN, OUTPUT);
  pinMode(PIN_BLUE, OUTPUT);
  //配置10号引脚为输入引脚 如果是自己连接普通按键 pinMode(KEY,INPUT_PULLUP),弱上拉
  pinMode(KEY,INPUT);
  BTSerial.begin(9600);
  #ifdef DEBUG
    MyDebugSerial.begin(9600);
  #endif
  init_RGB();
}

void loop() {
  int leng = ReceiveBTMessage();
  if(leng>0){
    //收到了新RGB数值
    colorRGB(red,green,blue);
  }
  changeRGBbyButton();
  saveEEPROM();
}

/**
* 初始化RGB灯
*/
void init_RGB(){
  red = EEPROM.read(RED_ADDR);
  DBGLN(red);
  delay(10);
  green = EEPROM.read(GREEN_ADDR);
  delay(10);
   DBGLN(green);
  blue = EEPROM.read(BLUE_ADDR);
  delay(10);
  DBGLN(blue);
  colorRGB(red,green,blue);
}

void saveEEPROM(){
  //以下这段代码是为了存储eeprom  因为定时中断不能用 所以就用了这么猥琐的代码
  if(saveCountX == 30){

    if(saveCountY == 30000){
      saveCountX = 0;
      saveCountY = 0;
      if(isNeedtoSave){
        isNeedtoSave = false;
        saveRGBtoEEPROM();
      }
    }else{
      saveCountY ++;
    }
  }else{
    if(saveCountY == 30000){
      saveCountX ++;
      saveCountY = 0;
    }else{
      saveCountY ++;
    }
  }
}

/**
* 把rgb数据保存到EEPROM上去
*/
void saveRGBtoEEPROM(){
  DBGLN("saveRGBtoEEPROM");
  DBGLN(red);
  DBGLN(green);
  DBGLN(blue);
  EEPROM.write(RED_ADDR,red);
  delay(50);
  EEPROM.write(GREEN_ADDR,green);
  delay(50);
  EEPROM.write(BLUE_ADDR,blue);
  delay(50);
}

/**
* 读取串口缓冲区里面的数据
*/
int ReceiveBTMessage(){
  /**
     * @Desc 把RGB组合成协议内的数据格式
     *  开始符+长度+rgb+结束符
     * "+C,n:rgbString;"
     * 例子:"+C,10:100,255,60;"
     **/
  String data = "";
  if (BTSerial.available()>0){
    unsigned long start;
    start = millis();
    char c0 = BTSerial.read();
    if (c0 == '+'){
      char c;
      boolean data_right = false;
      while (millis()-start<200) {
        if (BTSerial.available()>0){
          c = BTSerial.read();
          delay(1);
          data += c;
        }
        if (c==';'){
          data_right = true;
          break;
        }
      }
      DBGLN(data);
      if(!data_right)return;

      int sLen = strlen(data.c_str());
      int i,r,g,b;
      for (i = 0; i <= sLen; i++){
        if (data[i] == ':'){
          break;
        }
      }
      int iSize;
      //"+C,10:100,255,60;"    
      String _size = data.substring(2, i);
      iSize = _size.toInt();

      //"+C,10:1,1,1;"
      if(iSize!=sLen-i-2)return;

      for(r=i+1;r<=sLen;r++){
         if(data[r]==','){
           break;
          }  
      }

      for(g=r+1;g<=sLen;g++){
         if(data[g]==','){
           break;
          }  
      }

      for(b=g+1;b<=sLen;b++){
         if(data[b]==';'){
           break;
          }  
      }

      String sred = data.substring(i+1,r);
      String sgreen = data.substring(r+1,g);
      String sblue = data.substring(g+1,b);

      red = sred.toInt();
      green = sgreen.toInt();
      blue = sblue.toInt();

      DBGLN("red:"+sred);
      DBGLN("green:"+sgreen);
      DBGLN("blue:"+sblue);

      isNeedtoSave = true;
      //变成0
      saveCountX = 0;
      saveCountY = 0;
      
      return iSize;
    }else{
      while(BTSerial.read() >= 0){}  
    }
  }
  return 0;
}

/**
* 控制RGB颜色
*/
void colorRGB(int red, int green, int blue){
  #ifdef COMMON_GND
     analogWrite(PIN_RED,constrain(red,0,255));
     analogWrite(PIN_GREEN,constrain(green,0,255));
     analogWrite(PIN_BLUE,constrain(blue,0,255));
  #else
     analogWrite(PIN_RED,constrain(255-red,0,255));
     analogWrite(PIN_GREEN,constrain(255-green,0,255));
     analogWrite(PIN_BLUE,constrain(255-blue,0,255));
  #endif
}

/**
* 按键切换显示(应用于无app情景)
*/
void changeRGBbyButton(){
  int buttonState = digitalRead(KEY);//读取当前按键状态

  if(buttonState != lastButtonState){
     //如果按键发生了变化  则重新设置最近一次抖动的时间
     //方法millis()可以获取当前时间,单位统一为毫秒。
     lastDebounceTime = millis();  
  }
  
  // 判断按键按下或抬起的状态时间间隔是否大于延迟抖动的时间长度。
  if(millis()-lastDebounceTime>debouncdDelay){
    // 判断当前的按键状态是否和之前有所变化
    if(buttonState != state_btn){
       // 如果发生了变化,
       // 则更新按键状态变量。
       state_btn = buttonState;
       if(state_btn == HIGH){
        //再次确认是否真的按下了按键,是的话
         currentcode++;
         if(currentcode == MAX){
             currentcode = 0;
         }
         red = rgb_code[currentcode][0];
         green = rgb_code[currentcode][1];
         blue = rgb_code[currentcode][2];
         colorRGB(red,green,blue);
         isNeedtoSave = true;
        //变成0
        saveCountX = 0;
        saveCountY = 0;
       }
    }
  }
  // 更新按键最近一次状态变化的变量
     lastButtonState = buttonState;
}

代码经过测试可行。。。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单片机菜鸟哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值