查看: 9845|回复: 67

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

[复制链接]
  • TA的每日心情
    开心
    2019-6-18 08:58
  • 签到天数: 697 天

    [LV.9]以坛为家II

    发表于 2016-12-30 22:30 | 显示全部楼层 |阅读模式
    本帖最后由 单片机菜鸟 于 2019-6-5 23:37 编辑

    qq群:491507716    博哥私人号:2421818708


    一、前言


    app 下载路径:
    游客,如果您要查看本帖隐藏内容请回复
    app 源码下载路径
    游客,如果您要查看本帖隐藏内容请回复


        前篇帖子
        《博哥玩Arduino》- 蓝牙七彩灯优化版V1.0http://www.arduino.cn/forum.php?mod=viewthread&tid=32113&fromuid=93655
    (出处: Arduino中文社区)
         有讲到有两个未优化事项,如下:
         未优化事项:可以考虑后期加入记录上一次灯颜色状态,下一次开灯就默认是该颜色
         未优化事项:是否可以在板子上加入一个按钮,可以切换常用颜色,不一定每次都用app

    二、遇到问题以及解决方案

         1.未优化事项:可以考虑后期加入记录上一次灯颜色状态,下一次开灯就默认是该颜色
            这里就要用到EEPROM这个掉电保存,EEPROM讲解可以参考
           《博哥Arduino学习笔记系列》- 第七课 EEPROM断电保存数据http://www.arduino.cn/forum.php?mod=viewthread&tid=32123&fromuid=93655
    (出处: Arduino中文社区)

         2.未优化事项:是否可以在板子上加入一个按钮,可以切换常用颜色,不一定每次都用app
             本来想加入红外遥控的,但是红外遥控影响了PWM,所以只能用按键,按键讲解可以参考
          《博哥Arduino学习笔记系列》- 第四课 经典按键实验http://www.arduino.cn/forum.php?mod=viewthread&tid=31647&fromuid=93655
    (出处: Arduino中文社区)

            本来想上个视频的,但是其实跟V1.0很像,所以就不上了。
    三、调试代码
      

    kittenblock中小学创客名师推荐的图形化编程软件

    /**
    * 日期: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 == ':'){
              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==';'){
               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;
    }
    


    32K]O1}1F1$YO}G@$X~}{10.png

    qq群:491507716    博哥私人号:2421818708
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-4-2 09:54
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2016-12-30 22:53 | 显示全部楼层
    挺好的                        
  • TA的每日心情
    开心
    2019-6-17 10:59
  • 签到天数: 157 天

    [LV.7]常住居民III

    发表于 2016-12-31 16:05 | 显示全部楼层
    不错,顶一个。。
  • TA的每日心情
    开心
    2019-6-18 08:58
  • 签到天数: 697 天

    [LV.9]以坛为家II

     楼主| 发表于 2016-12-31 20:37 | 显示全部楼层

    哈哈哈哈 谢谢
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-6-18 08:58
  • 签到天数: 697 天

    [LV.9]以坛为家II

     楼主| 发表于 2016-12-31 20:38 | 显示全部楼层
    电磁波 发表于 2016-12-31 16:05
    不错,顶一个。。

    哈哈哈哈 谢谢
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-6-18 08:58
  • 签到天数: 697 天

    [LV.9]以坛为家II

     楼主| 发表于 2016-12-31 21:27 | 显示全部楼层

    那你觉得应该怎么写呢  可以放上来看看  再者就是应该职责分离   ReceiveBTMessage 和 changeRGB他们的作用就如名字  不应该在里面再嵌入一个save
    打赏作者鼓励一下!
  • TA的每日心情
    擦汗
    2017-1-10 09:19
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-12-31 21:57 | 显示全部楼层
    /**
    * 日期: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);
    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);


      }
      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);

    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);

        /*****
    //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;
    ***/



    :)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);
           }
        }
      }
      // 更新按键最近一次状态变化的变量
         lastButtonState = buttonState;
    }
  • TA的每日心情
    擦汗
    2017-1-10 09:19
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-12-31 22:03 | 显示全部楼层
    我的思路是:
    只有 ReceiveBTMessage 和 changeRGB这两个事件需要写入EEP。
    那么只需要在每个事件下写入EEP数据即可
  • TA的每日心情
    开心
    2019-6-18 08:58
  • 签到天数: 697 天

    [LV.9]以坛为家II

     楼主| 发表于 2016-12-31 22:05 | 显示全部楼层
    caonimaB 发表于 2016-12-31 21:57
    /**
    * 日期:2016/12/30
    * 功能:蓝牙台灯

    这样会有一个问题就是  每次改变状态都要保存一遍 你得考虑如果手机端app在1s以内发送多次数据 那是不是你这里不断地写eeprom呢 ?我那个代码就是为了在某次状态改变之后隔一段时间才去保存的
    打赏作者鼓励一下!
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    MAC arduino ESP8266mDNS.h不能加载。。。
    MAC arduino ESP8266mDNS.
    SpiderRobot 蜘蛛
    SpiderRobot 蜘蛛
    关于SpiderRobot 项目实行方案 之前有人推荐我做这个项目,于是乎就有了这个 h
    【原创】 drawbot平面关节scara机械臂写字机 画画机器人直播...
    【原创】 drawbot平面关节
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    项目分享——arduino梦幻交互雪花2019
    项目分享——arduino梦幻
    雪花由30颗LED打造,分为17个独立的部分,由Arduino Nano控制。每组LED都可以用PWM调
    体验OneNET4.0,一起来拼开发板
    体验OneNET4.0,一起来拼
    一、 活动时间2019年04月09日-2019年6月30日 二、活动链接1.登录Arduino中文社区账
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表