Cherry 发表于 2019-5-27 14:50:00

转载:基于机智云的懒人声控灯

作者:打包还是带走
         最近,接触到机智云智能硬件云服务平台(类似物联网),也花几天了解了平台的开发流程,搞清楚后就想搞事情,手头上剩了一些材料(元器件),反正也是闲着,搞点东东玩玩,娱乐一下枯燥乏味的生活。

         这个灯怎么来的,源于一句话:“我有一个大胆的想法!!!”,应该是这样,然后就有了这个灯。差不多花了20天的时间,也没有20天,就是偶尔花点时间弄一下。先说下具体功能:


[*]离线按钮控制开关
[*]远程APP控制开关
[*]声控控制开关
[*]胶粘在了懒人支架上
[*]没有电池离电死(这也算功能吧)
         以上可以说是非常的懒人了,灯度也很高,在测试声控的时候离得太近眼睛又对着灯,喊了一下差点瞎了,所以远离灯源,祝您心明眼亮。综上,“懒人声控致瞎灯”名字由此而来。
         前方高能预警!注意!这不是演习!制作过程如下:
         Step1 材料准备
1.1   主控:Arduino Pro mini以及FTD1232串口下载器
1.2   通信:正点原子ESP8266 WIFI模块
1.3   声控:声音检测模块
1.4   光源:5W 白灯10颗灯珠,5V供电
1.5   供电:DC 5V-2A 适配器
1.6   支架:懒人手机支架(后续改装用)
1.7   工具:电烙铁,热熔胶,钩刀,
1.8   模型:亚克力板20x30cm,厚度2mm
1.9   额外:1路继电器,轻触开关,自锁开关,洞洞板,火牛电源头,散热硅脂、铝制散热块各一个
         Step2 固件烧录
         2.1机智云烧录GoAgent固件方法参考:
         http://club.gizwits.com/forum.php?mod=viewthread&tid=3551&highlight=8266
         2.2主控烧录
         2.2.1在机智云中添加两个数据点,LED_Switch,Sound_Switch,布尔类型,可写,
         将下载的代码文件夹Gizwits放入Arduino编程器文件目录libraries下。
                   如果开发流程不清楚可以详见官方开发流程!
         2.2.2下载ProtoThreads多线程的库,同上放入libraries。
                   修改Gizwits文件夹下的Gizwits.h头文件,打开头文件,将公有成员函数void process(void);改为bool process(void);
                   同样,在Gizwits.cpp中将函数修改为bool类型,还需对代码修改,如下:https://www.arduino.cn/images/2018/kit.pngkittenblock中小学创客名师推荐的图形化编程软件


bool Gizwits::process(void)


{


      uint8_t readChar = 0;


    uint16_t i=0,num = 0;


    num = Serial.available();


    if(0 < num)


    {


      for(i=0; i<num; i++)


      {


            readChar = Serial.read();


            gizPutData(&readChar, 1);


      }


                gizwitsHandle((dataPoint_t *)¤tDataPoint);


                return 1;





    }


      gizwitsHandle((dataPoint_t *)¤tDataPoint);


      return 0;


}



                   解释一下为什么,在我的代码中有一行:
                   PT_WAIT_UNTIL(pt,myGizwits.process());
                   这个函数的第二个参数是布尔类型的参数,所以需要修改Gizwits的源代码,当串口无数据是该线程阻塞的,当串口接收到数据时,线程运行,这样可以节省CPU查询if语句的资源。
         2.3总体代码

[*]移植networkConfig中的部分代码,按键1的代码去掉(基本用不到),修改按键2为D4,方便随时都配置网络。
[*]声音传感器使用中断触发的方式,连接在D3(外部中断1),使用计算时差的方式过滤掉一些杂音或避免多次重复触发开关。
[*]由于单片机的IO提供电流太小,所以LED灯通过继电器控制,继电器低电平驱动,连接在D5。

         附上代码:
         https://www.arduino.cn/images/2018/kit.pngkittenblock中小学创客名师推荐的图形化编程软件





#define PT_USE_TIMER//任务挂起要用


#include "pt.h"


#include <Gizwits.h>


#include <Wire.h>


#include <SoftwareSerial.h>


#define   KEY2            4


#define   KEY2_SHORT_PRESS4


#define   KEY2_LONG_PRESS   8


#define   NO_KEY            0


#define   KEY_LONG_TIMER    3 //约3秒





#define   LED_PIN         5 //LED引脚


#define   SND_PIN         3 //声音检测开关引脚





//实例化类


SoftwareSerial mySerial(A2, A3); // A2 -> RX, A3 -> TX


Gizwits myGizwits;





//**全局变量


static struct pt thread1,thread2;


unsigned long Last_KeyTime = 0;


unsigned long Last_SoundTime = 0;


bool varR_LED_Switch = 0;


bool varR_Sound_Switch = 0;





//秒获取


unsigned long gokit_time_s(void)


{


return millis() / 1000;


}





char gokit_key2down(void)


{


int unsigned long keep_time = 0;


if (digitalRead(KEY2) == 0)


{


    delay(100);


    if (digitalRead(KEY2) == 0)


    {


      keep_time = gokit_time_s();


      while (digitalRead(KEY2) == 0) //until open the key


      {





      if ((gokit_time_s() - keep_time) > KEY_LONG_TIMER)


      {


          Last_KeyTime = gokit_time_s();


          return KEY2_LONG_PRESS;


      }


      }





      if ((gokit_time_s() - Last_KeyTime) > KEY_LONG_TIMER)


      {


      return KEY2_SHORT_PRESS;


      }


      return 0;


    }


    return 0;


}


return 0;


}


//只保留按键2的处理


char gokit_keydown(void)


{


char ret = 0;


ret |= gokit_key2down();


return ret;


}


//只保留了AirLink配网方式,SoftAP去掉,改为开关控制


void KEY_Handle(void)


{


/*Press for over than 3 second is Long Press*/


switch (gokit_keydown())


{


    case KEY2_SHORT_PRESS://短按


      if(varR_LED_Switch == 0)//若为关


      {


      digitalWrite(LED_PIN, 0);//则打开


      varR_LED_Switch = 1;//标记为打开


      }


      else//若为开


      {


      digitalWrite(LED_PIN, 1);//则关闭


      varR_LED_Switch = 0;//标记为关闭


      }


      break;


    case KEY2_LONG_PRESS://长按


      //mySerial.println(F("KEY2_LONG_PRESS ,AirLink mode"));


      myGizwits.setBindMode(WIFI_AIRLINK_MODE);


      //AirLink mode


      break;


    default:


      break;


}


}





void setup() {


// put your setup code here, to run once:


mySerial.begin(115200);





pinMode(LED_BUILTIN, OUTPUT);


pinMode(KEY2, INPUT_PULLUP);//按键上拉输入


pinMode(5, OUTPUT);


digitalWrite(5, 1);//关闭继电器





myGizwits.begin();





mySerial.println("GoKit initOK \n");


//初始化线程


PT_INIT(&thread1);


PT_INIT(&thread2);


}





void SoundDetection()


{


int unsigned long start_time = 0;





detachInterrupt(1);//关中断


//可以试一下以下这个,要配合底部那句一起


//进入临界模式,所有中断关闭


//noInterrupts();


delay(3000);





if(digitalRead(SND_PIN) == LOW)


{


    delay(1000);


    if(digitalRead(SND_PIN) == LOW)


    {


      start_time = gokit_time_s();


      if ((Last_SoundTime - start_time) > 0.1)//防止极短时间内重复开关


      {      


      if(varR_LED_Switch == 0)//若为关


      {


          digitalWrite(LED_PIN, 0);//则打开


          varR_LED_Switch = 1;//标记为打开


      }


      else//否则为开


      {


          digitalWrite(LED_PIN, 1);//则关闭


          varR_LED_Switch = 0;//标记为关闭


      }


      Last_SoundTime = gokit_time_s();


      }


    }


}


attachInterrupt(1, SoundDetection, FALLING);//开中断


//退出临界模式


//interrupts();


}


//系统闪烁灯,按键处理


static int thread1_entry(struct pt *pt)


{


PT_BEGIN(pt);


while (1)


{


    KEY_Handle();//按键处理,网络配置


    digitalWrite(13,!digitalRead(13));


    PT_TIMER_DELAY(pt,500);//挂起线程500ms


}


PT_END(pt);


}


//机智云串口数据处理


static int thread2_entry(struct pt *pt)


{


PT_BEGIN(pt);


while (1)


{


    PT_WAIT_UNTIL(pt, myGizwits.process());


    if(myGizwits.hasBeenSet(EVENT_LED_Switch))


    {


      myGizwits.read(EVENT_LED_Switch,&varR_LED_Switch);//Address for storing data


      if(varR_LED_Switch == 1){


      digitalWrite(5, 0);//开灯


      }else{


      digitalWrite(5, 1);//关灯


      }


    }





    if(myGizwits.hasBeenSet(EVENT_Sound_Switch))


    {


      myGizwits.read(EVENT_Sound_Switch,&varR_Sound_Switch);//Address for storing data


      if(varR_Sound_Switch == 1)


         attachInterrupt(1, SoundDetection, FALLING);//开中断


      else


         detachInterrupt(1);//关中断


    }


    PT_TIMER_DELAY(pt,100);//挂起线程100ms





}


PT_END(pt);


}





void loop() {


//Check each thread by priority


thread1_entry(&thread1);


thread2_entry(&thread2);


}






         烧录时由于Pro mini没有自带串口,所以要用FTD1232串口模块下载,若用其它的开发板可以不用FTD1232。
         Step 2 模型设计
         2.1灯的改造
         这是买来时的灯:
          https://www.arduino.cn/data/attachment/forum/201710/16/165251mws10zzwusigeroo.jpg
         拆了后如图:
          https://www.arduino.cn/data/attachment/forum/201710/16/165246pzpqezj6u0ykggbq.jpg
         这样,把固定灯的环壳用钩刀裁剪下来
          https://www.arduino.cn/data/attachment/forum/201710/16/165241ze985k8sszkync1n.jpghttps://www.arduino.cn/data/attachment/forum/201710/16/165243rnm7ijjunkl4lq5m.jpg
         在LED灯板上用钻孔机(这个东西实验实有)钻两个孔,涂上硅脂,固定在散热块上
          https://www.arduino.cn/data/attachment/forum/201710/16/165249v1px4js0stbphyzj.jpghttps://www.arduino.cn/data/attachment/forum/201710/16/165248unzus7mjsjjz3nuy.jpg
         最后,当当当~~~,拼装起来
          https://www.arduino.cn/data/attachment/forum/201710/16/165250u3mo6g1g1h8ddcmz.jpg
         
         2.2外壳设计
         由于灯的最大直径为60mm,所以四面的长方形块大小为60x73mm,顶部的方形块大小为60x60mm,都用钩刀裁剪就可以了。
         2.3顶部电源设计
         如图想办法挖槽吧,用钻孔机+钩刀,是的,楼主我只有这些工具。
          https://www.arduino.cn/data/attachment/forum/201710/16/165244v6kitv306l13ttlp.jpg
         然后把开关,按钮等东西用热熔胶粘上去
          https://www.arduino.cn/data/attachment/forum/201710/16/165245m67zzzeo7y6s2i2u.jpg
         Step 3 安装模型
         先用热熔胶粘两个侧面,然后固定LED灯。再把元器件也粘进去
          https://www.arduino.cn/data/attachment/forum/201710/16/165247ho2a8i5z58d24vb4.jpg
         接下来把其它两块也粘上去,这样大体就差不多了
          https://www.arduino.cn/data/attachment/forum/201710/16/165242obcwz0nztss2ov0b.jpg
         以上步骤在做的时候边粘边连线的!最后,盖上顶部的盖子。
          https://www.arduino.cn/data/attachment/forum/201710/16/165247dyx4w88fgr4xcjcj.jpg
         呐~~~酱紫的~~~
          https://www.arduino.cn/data/attachment/forum/201710/16/165249pbb87u8lyguxee8c.jpg
         现在轮到懒人支架上场表演了,先把脚跺了再说,如下图
          https://www.arduino.cn/data/attachment/forum/201710/16/165246affea1qj8a7l68dq.jpghttps://www.arduino.cn/data/attachment/forum/201710/16/165243x3exd3xekz9ke0hx.jpg
         再把脚粘在灯的顶部
          https://www.arduino.cn/data/attachment/forum/201710/16/165707nwjwwawlaicsznnl.jpg
         Step 4 装饰一下
         以前做了个大别野,剩了点贴纸,就给敷上去了,字不重要,看下图
          https://www.arduino.cn/data/attachment/forum/201710/16/165250fcltt17e1lg1tkvz.jpg

         说一下感悟吧:
         用心做好一个灯         不只是电科的专业与执着         更是使命         用实在的原料         佐以专业独运的焊接工艺         所融入的不只是优美代码         还有与之相得益彰的模型         让人陶醉,更令人沉迷的         电科精神
         打包,懒人声控致瞎灯         以亚克力熔制的躯壳         融入困、懒、惰、倦之气         让每一次起床开关灯的想法万念俱灰         声控也更为庸人自扰         懒得到豆腐渣工艺         更享受到无比诚意
         ——修改于匠汤海鲜面
         题外话:本来想做花样七彩+白色LED灯的(WS2812B RGB七彩转圈圈的,很漂亮,美滋滋),后来发现驱动RGB灯需要占用极大的CPU使用率,又由于Arduino 串口库的原因(不能中断收发数据,即实时性低),从而使得机制云传来的数据丢失或网络连接常断开或APP无法控制灯的开关,了用户的体验感,只能舍弃了。
          https://www.arduino.cn/data/attachment/forum/201710/16/170045d87aqr53lfvwqk75.jpg         楼主我走过一些弯路,烧过一些芯片,这是取经之路必定会发生的事情,这是我完美的一面,为各位网友踮脚啦

         项目代码,ProtoThreads库源码打包下载:
         视频地址:http://v.youku.com/v_show/id_XMzA4OTQzMzcwOA==.html
         本帖子允许转载,务必注明作者以及来源。
         这里开源给大家互相学习
页: [1]
查看完整版本: 转载:基于机智云的懒人声控灯