Arduino+W5100 应用集锦-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 73919|回复: 39

Arduino+W5100 应用集锦

[复制链接]
发表于 2014-12-5 17:46 | 显示全部楼层 |阅读模式

各位Arduino Maker,大家好!我在本帖搜集整理了一些Arduino+W5100的应用,对这方面感兴趣的朋友可以参考一下~  首先声明一下,我搜集的资源均来自网络,非原创的内容都会附上原文链接,若有不明白的地方,请参考原文。

本帖持续更新中,敬请关注!


一、测试除夕炮竹对空气的影响     

采用乐联网-arduino w5100 框架实现,具体内容参考 http://www.geek-workshop.com/thread-3381-1-1.html
                                      


观测曲线:http://open.lewei50.com/home/gatewaystatus/69

简单说明:
1  测试除夕鞭炮对颗粒物的影响,主要观察第一个曲线“小颗粒物”,使用dylos进行测试

2  测试  ppd42ns  的一致性,主要是对比第二个和第三个曲线的一致性

3  测试ppd42ns  与dylos的相关性,找出对比关系。





代码实现:
ARDUINO 代码复制打印

  • #include <LeweiClient.h>
  • #include <SPI.h>
  • #include <Ethernet.h>
  • #include <Wire.h> //BH1750 IIC Mode
  • uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
  • #define LW_USERKEY "xxxxxxxxxxxxxxxxxxxxxxx"
  • #define LW_GATEWAY "01"
  • //delay between updates
  • #define POST_INTERVAL (10*1000)
  • LeWeiClient *lwc;
  • LeWeiPPDSensor the_PM1Sensor("M1", "M_sensor", "M1sensor", 8);
  • LeWeiPPDSensor the_PM1Sensor2("M2", "M_sensor", "M1sensor", 7);
  • void setup() {
  •     Serial.begin(9600);
  •     if (Ethernet.begin(mac) == 0)
  •     {
  •         Serial.print("Failed to configure Ethernet using DHCP\r\n");
  •     }
  •     else
  •     {
  •         Serial.print("Ethernet configuration OK\r\n");
  •     }
  •     // hope no exception here
  •     lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY);
  •     lwc->registerSensor(the_PM1Sensor);
  •     lwc->registerSensor(the_PM1Sensor2);
  • }
  • void loop() {
  •     if (lwc) {
  •         Serial.print("*** start data collection\r\n");
  •         lwc->scanDevices();
  •         Serial.print("*** start data send\r\n");
  •         lwc->send();
  • /*
  • *        Serial.print("*** start log send\r\n");
  • *        lwc->sendLog("I'm alive.");
  • *
  • */
  •         //delay(POST_INTERVAL);
  •     }
  • }



测试结束,数据地址 http://open.lewei50.com/home/gatewaystatus/69


结论如下:
1 两个PPD42NS 基本曲线一致(选择一周作为时间间隔)
2 由于没有用风扇,颗粒物相对较少的时候,无法向dylos一样反应空气质量变化,也就是不加风扇基本上只能在国内用了。
                                             
原帖来自:Geek-workshop

二、Arduino学习笔记:2560+W5100试验实时室温对Pachubbe.com推送

试验名称:2560+W5100试验实时室温对Pachubbe.com推送
试验时间:2012-02-18
控制板:arduino 2560
元器件:LM-35 DZ模拟传感器一只,正对标示,从左往右,+5V,模拟输出,GND
连接方法:接好+5V,GND,将LM35的模拟输出接2560的模拟PIN4
                W5100连接至你的路由器,路由器连接互联网,PC连接2560便于观察网络连接以及数据采集情况

结果运用 : Tep= ** C;将实时室温传感器数据推送至www.pachube.com,每10秒刷新一次
代码原型:(1)官方例程pachubeout(-使用 ERxPachube 库的实例. )
                 (2)弘毅教程--学习笔记11,
                 (3)其它结合网络资源整理
* 本实例创建于2011.04.22,作者是Jeffrey Sun
* 开源项目详见http://code.google.com/p/pachubelibrary/
所需要的库在此处下载http://code.google.com/p/pachube ... ip&can=2&q=,释放至此处:

第一步:
      如果你还没有一个 Pachube 账户, 先去注册一个 (http://www.pachube.com/).注意,有一个开发账号和一个通讯组讨论账号,我们需要前者。注册成功后,我们将获得一个API key
     pahube.com是一个免费的提供给开发者的实时数据上送、展示的网站。内置API,使用者只需要调用API(给出feed的ID),就可以将传感器数据推送至你自己独享的feed数据库。然后以图形方式进行丰富展示。


第二步:创建一个类似http://www.pachube.com/feeds/23408这样的素材库(feed)
          为了测试,我们只需要创建一个ID为0的数据流
以下就是我建立的一个ID号码为49030的feed,需要设置项目名称、简介、关键词(便于检索)、项目的位置(经纬度、海拔、室内还是室外、移动还是固定等等)、数据表ID编号、表述、单位等。支持多数据ID。你可以在一个素材中推送多个传感器数据,数据格式有长型、字符型等。


第三步:
   将以太网扩展板(W5100)堆叠至2560板上。LM35接2560的模拟输入(PIN 4)


第四步:输入、编译代码
代码一共分为个部分:
1、设置MAC地址、IP地址,API KEY以及FEED ID
2、连接互联网,将温度传感器数据转换为摄氏度,然后推送至pachube.com
3、在串口助手中,监视网络连接情况,以及传感器数据,状态值为200则连接成功,否则不成功

第五步:在www.pachube.com中观察你的数据
为了引起温度波动,图中的两处波动是我用手指贴近FM35后造成的波动。




后记:
    本实例学习过程中,先后遇到了W5100不能稳定工作、无线路由器损坏、找不到一个实时推送数据的网站等问题,感谢弘毅、HEAVEN、小强、张丹、风的孩子等高手支持。我是以arduino为兴趣的一个软硬件基础都很薄弱的初学者,但是兴趣是最大的推动力。这个实例的学习仅仅是将一个开源项目与弘毅笔记简单的组合,即便是一个简单的尝试也感到很多困难,里面如有理解错误的地方敬请指正。

附代码:
  • /*项目名称M35温度传感器连接2560向www.pachube,cin推送数据试验
  • 试验时间:2012-02-18
  • * 本实例创建于2011.04.22,作者是Jeffrey Sun
  • * 开源项目详见http://code.google.com/p/pachubelibrary/
  • */
  • #include <Arduino.h>
  • #include <HardwareSerial.h>
  • #include <ERxPachube.h> //调用ERxPachube库
  • #include <Ethernet.h>
  • #include <SPI.h>
  • byte mac[] = { 0xCC, 0xAC, 0xBE, 0xEF, 0xFE, 0x91 }; // 确认这是你网络中唯一的MAC地址,用小强的话说,你就是网卡厂商,自己定一个
  • byte ip[] = { 192, 168, 1, 177   };                  // 设置以太网扩展板的IP地址
  • #define PACHUBE_API_KEY                                "Your API_KEY" // 填写你自己的 API key
  • #define PACHUBE_FEED_ID                                Your Feed Id // 填写你自己的素材ID( feed id)
  • //定义三个FM35用的变量
  • int potPin = 4;                     //设置模拟口4为LM35的信号输入端口
  • float temperature = 0;                //设置temperature为浮点变量
  • long val = 0;                       //设置val为长整数变量
  • ERxPachubeDataOut dataout(PACHUBE_API_KEY, PACHUBE_FEED_ID);
  • void PrintDataStream(const ERxPachube& pachube); //在COM口监测本地温度传感器推送情况
  • void setup() {
  •         Serial.begin(9600);
  •         Ethernet.begin(mac, ip);  //访问以太网扩展板
  •         dataout.addData(0);       //向www.pachube.com推送数据序列0(转换后的温度)
  • }
  • void loop() {
  •         Serial.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
  •         val = analogRead(potPin);//温度传感器LM35接到模拟PIN4上;val变量为从LM35信号口读取到的数值
  •         temperature = (val*0.0048828125*100);
  •         //把读取到的val转换为温度数值,系数一:0.00488125=5/1024,0~5V对应模拟口读数
  •         //1~1024,系数二:100=1000/10,1000是毫伏与伏的转换;10是每10毫伏对应一度温升。
  •         dataout.updateData(0, temperature);
  •         int status = dataout.updatePachube();
  •         Serial.print("sync status code <OK == 200> => ");
  •         Serial.println(status);   //如果状态码是200,则互联网连接成功
  •         PrintDataStream(dataout);
  •         delay(10000);
  • }
  • void PrintDataStream(const ERxPachube& pachube)
  • {
  •         unsigned int count = pachube.countDatastreams();
  •         Serial.print("data count=> ");
  •         Serial.println(count);
  •         Serial.println("<Feed id>,<Temp value>");
  •         Serial.print(pachube.getIdByIndex(0));
  •         Serial.print(",");
  •         Serial.print(pachube.getValueByIndex(0));
  •         Serial.println();
  • }

[color=rgb(51, 102, 153) !important]复制代码


原帖来自:Geek-workshop

三、用arduino+w5100 把网页上的颜色输出到RGB LED上显示


web led 利用arduino+w5100 把网页上的颜色输出到RGB LED上显示

先找一个有RGB颜色的LED灯



LED上有三个引脚分别是对应红绿蓝三个颜色,为了分电压,也在三个引脚中串上三个560欧电阻



三个不同颜色引线对应三种颜色,黑色为地线


接上arduino + W5100 模块


看代码上的引脚,对应接线


接上网线和电源


然后打开电脑的IE浏览器
地址栏上输入192.168.1.178按回车(这个IP地址是在arduino代码上设定的服务器地址,可自行更改)




看到调色板了,如果你用鼠标点击上边的颜色值arduino上的LED就会显示相应的颜色。除了图片这几个颜色外,还可以自己输入颜色值按submit使LED生成颜色。

原理:
通过arduino + W5100模块,组合成WEB服务器,把网页代码发送到IE浏览器上,如果点击调成板上的颜色,利用POST发送颜色代码值到arduino上,arduino再分析代码,把代码转换成PWM值输出到引脚。

代码: web_led_RGB.rar (2.97 KB, 下载次数: 630)



原帖来自:Geek-workshop




四、arduino+w5100+继电器,代替门禁卡,控制可视对讲

家里的门禁开门要按最下面的按钮,开通之后,会保持5秒左右通,然后自动关。
在门开通的情况下,继续按开门键会“哔哔”叫。
把门禁对讲拆开,将开门键的开关引出2个引线,接到放arduino的柜子里的继电器模块上。
arduino上面加了w5100模块和继电器模块,w5100模块负责网络通信,arduino负责解析收到的http请求,将解析的结果转换成对应的操作,我这里是开门操作(继电器低电平保持1秒后恢复高电平)。在有局域网的情况下,可以迅速实现在家门内按开关的操作。
注:我家1楼,在门口的门禁处就能访问到家里的wifi。如果想在外面通过gprs控制家里的门禁,请在论坛里搜“乐联网”或“yeelink”的反向控制,一样可以实现,但要求家里的网具有公网IP或从外网可访问家里。

相关帖子:
门禁改造:arduino模拟按键,通过继电器控制直流电问题
http://www.geek-workshop.com/thread-4406-1-1.html
这样就出门就可以不用带门禁卡了。家里的wifi有密码,也不用太担心这样操作带来的安全问题。


原帖来自:Geek-workshop


五、Arduino uno+w5100+yeelink实现红外转码与网络控制

先贴两张作品图


      最近双蛋大学搞了个arduino竞赛,开学之初稍有空闲就报了个名。初中时曾玩过一阵AVR,之后一直忙于学业,现在总算有自由时间重拾单片机。好久不关注这一领域,顿时发现这几年来,单片机还是进步不少的。这是我第一次接触arduino,顿时发现软硬件方面开发系统都简约亲切不少,还是挺容易上手的。首个arduino项目,也不指望太复杂,实现个简单功能就行。
      淘宝上买了个初学者套件,整套一百七十多。原来以为各器件都是arduino专用,后来才发现市面上大多元件arduino都可以支持,而且套件中有许多不需要的器件,这样一想感觉还是挺贵的,推荐新手们分元件单独购买。


      客服还是挺好的,提供了一套详尽的资料。在看教程时,突然对红外发射接收感兴趣,于是就结合之前的想法,想做一个红外控制器。只需一个遥控器就可控制家中所有用红外控制的家电,后来知道这就是红外转码功能。
      通过程序设计控制遥控器各键功能,红外接收器接收到控制遥控器的按键后,经arduino按预先设定的对应关系,发射相应的红外指令。
      本项目使用的库文件在最后会有汇总并提供下载!

      使用IRromote库中的IRrecvDump与IRsendDemo例子分别举例了接受、发射红外代码的使用方法,基于这两个程序,构成了我的红外转码程序。
      鉴于家中和寝室的红外控制设备有限,仅针对格力空调、美的电扇、iptv创维电视设计红外转码。

开发流程
(1)红外转码部分
1.使用IRrecvDump接受各电器红外编码
普及一下知识,红外遥控器发射的其实是一连串的方波信号,接收器根据信号有无及其间隔的时间长度计算所代表的1/0信号。
下图是常用的NEC编码方式(也是本项目中电扇和iptv的编码方式)。NEC编码由十六位二进制数构成,前八位是地址,后八位是命令。


发送信号时,首先是一段9ms高电平和一段4.5ms低电平作为开始标记,随后是信号内容。
先是8位的地址及其反向编码(确保信息准确),再是8位的命令编码及其反向编码。最后以一小段高电平结束。
知道了NEC的编码形式,我们就可以通过读取遥控器的红外指令,得到各个信号的代码,并依照其编码方式发射NEC信号。
硬件部分:
连接非常简单,只需将三个引脚接到指定位置即可。

红外接收头及接法:
软件部分:
好在IRromte库十分强大,其IRrecvDump的example可以将读取的红外信息直接打印到Serial Monitor。
例如,项目中的总控制遥控器的第一个按钮的dump结果如下:
FFA25D
Decoded NEC: FFA25D (32 bits)
Raw (72): 18448 8900 -4450 550 -550 600 -500 600-550 550 -550 600 -500 600 -550 550 -550 550 -550 600 -1600 600 -1650 600 -1650550 -1650 600 -1650 550 -1650 600 -1600 600 -1650 550 -1650 600 -550 550 -1650600 -550 550 -550 550 -550 600 -1600 600 -550 600 -500 600 -1650 550 -550 550-1650 600 -1650 600 -1650 550 -500 600 -1650 600 26086 8900 -2200 600

“FFA25D”就是转换成16进制的编码,之后只要用它发射就行了。“NEC”代表程序已判断出这种型号的形式是NEC格式的。“32 bits”代表编码长度。后面的Raw是每个方波的长度。正值代表高电平,负值代表低电平,数值大小代表持续长度。根据NEC规则,一高一低的一组电平变化代表一个数。若560us高电平1690us低电平代表1,560us高电平560us低电平代表0,由于程序精度限制,只能以50us为倍数测量,所以只能看到近似的结果,但是这样的分辨率下分辨1与0自然是没有问题的。程序已经帮我们计算好信号的编码了,只要用就行。


一个个按钮点过去,获取各键编码
具体请见附件:编码表 遥控器编码(正式).rar (10.6 KB, 下载次数: 60)

注意:有些编码形式特殊(如格力空调),将在第三步中阐述。
注意:有些编码长度很长,需要修改IRremote.h#define RAWBUF 200的数值以使得编码能完整dump出。


2.发射红外编码
收集完所有编码后,就可以尝试发射编码了。
硬件部分:


一开始一直感觉功率不够,一定要很近才行。。于是尝试改小电阻,增加发射头数量等方式。


提示:红外线虽然肉眼不可见,但在镜头下是可以看到的!用此方法可以快速判断线路通断。
改小电阻对单片机有危险,而增加发射头效果依然不理想,于是考虑用三极管放大。下图所示为电路连接图及实际测试各点电压:

不解的是为什么一直处在饱和区,哪怕减小R2也不行。。正在求教:http://www.geek-workshop.com/thread-7536-1-1.html
欢迎高手们继续指点!


经大神点拨,好像红外信号是要处在饱和区的,从效果上来看还是不错的。


软件部分:
IRromte库提供了多种发射编码的函数,具体可以打开头文件和cpp文件查看,代码都很容易懂。
因为是NEC编码,所以使用的是voidIRsend::sendNEC(unsigned long data, int nbits),直接将刚才得到的十六进制编码值给这个函数就可以了。data代表发送的NEC编码值,nbits是编码长度。在刚才的dump中都已经告诉你了。
例如
IRsend irsend;
irsend.sendNEC(0xFFA25D ,32);

另一种发射的函数是void IRsend::sendRaw(unsigned int buf[], int len, int hz),有些不使用编码协议的信号要用它发射。
三个参数分别代表要发送的数组,数组长度,和发送红外光的频率(一般都是38(khz))。
例如创维电视开机信号:
unsigned int tvonoff[68]={4500, 4400,600, 550,550,1650,600, 1600,600, 1650,550, 550,600, 500,600, 500,600, 550,550, 550,600,1600,600, 1600,600, 1650,600, 500,600, 500,600, 500,600, 550,600, 500,600,500,600, 1600,600, 1650,600, 500,600, 500,600, 500,600, 550,600, 1600,600,1600,600, 550,600, 500,600, 1600,600, 1650,550, 1650,600, 1600,600};//已去除第一个值
IRsend irsend;
irsend. sendRaw (tvonoff,68,38);


注意:
dump中RAW的第一个值是不需要的。因为NEC编码的规范是在9ms高4.5ms低电平之后才开始,所以之前的值不是信号一部分,若加上会导致错误。同样,因为NEC一定以低电平结尾,最后一个高电平值也不是信号的一部分,但加上也不会影响发射。
注意:
有些编码虽然解码结果显示为NEC但只能用sendRaw发射,例如创维电视!
注意:
每一次发射红外信号后,一定一定需要记得加上irrecv.enableIRIn();这句来重新开启红外接收功能,否则下一个按键就不会被接收!查过代码,发射的时候好像是为了保证信号不受干扰,把Timer2 的时钟关闭了,但没有时钟,根本就不能进行红外接收(红外接收主要就是靠对高低信号计时),enableIRIn函数中有一句就是开启时钟,所以才能正常接收。


3.格力空调的编码方式及发射方式
开发中遇到的一大问题就是格力空调的编码问题。
格力空调不知是出于什么样的心态,特立独行地设计了自己的一套编码方式,但奇怪之处在于通过sendRaw也不能实现控制。在琢磨这点上我花了不少时间,走了不少弯路。
后来在
的启发下总算明白了编码机制。
竟然在一个信号中间部分空出一段低电平!!前后两部分还有某种特殊关系。所以用红外接收头dump出的就是有问题的代码,当然发射不出正确的。
而且与风扇等信号不同,空调遥控器发射的是状态信号,不是功能信号。每一个信号中完整包含了空调状态的所有信息(温度、模式、扫风……)所以按下升温降温后,发射的不是升降温的指令,而是当前状态加减一度后的新状态编码。编码中每一位数起什么功能都是定好的,比如说温度信息就体现在第3、4和第17、18位上。
根据上述两个例子的代码,自己改了改,总算成功实现控制。心情无比激动!

4.加装温湿度传感器
想法是检测室温(湿度),当达到一定温度时自动开启风扇空调。
实际操作时发现实践起来十分简单,几乎没花什么时间一次就成功了。
硬件部分:
使用的是DHT11的温湿度传感器。


注意:引脚3不用接线!
软件部分:
从网上找了一个库,直接照它的代码用就行了。
获取温度:
int dat;
int chk = DHT11.read(DHT11PIN);
return dat=(float)DHT11.temperature;

获取湿度:
int dat;
  int chk = DHT11.read(DHT11PIN);
  return dat=(float)DHT11.humidity;


5.加装蜂鸣器提示
总不能一直用串口查看运行状态吧,最后需要实现的是用电池驱动,所以一定要加上一个指示装置表达当前运行状态,否则功能一多一定搞不清了。当时还不会lcd,就用最简单的无源蜂鸣器。

设定蜂鸣器声音含义
程序调用void warning(int freq, int time)发声,通过改变两个参数实现不同声音。freq代表声音频率,1最高4最低,time代表声音时长,25最短100最长
  
  
int freq
int time
Typechangebuzz(repeat times is mode  number)
1
25
Signal sending
2
50
Cannot find number_in_mp3
3
50
Temperature incorrect
4
100
Other no function button
Silent
Silent

6.加装lcd屏幕
硬件方面:
之前初学者套间里提供了一块lcd1602的液晶屏,但是看到那么多接口和教程里的复杂接线就望而生畏了。后来在淘宝店里发现一块适用于1602的转I2C口芯片,将十几个口简化为四个口,就果断买下,并以我拙劣的焊接水平勉强将芯片焊上。
在连线上又遇到问题了,搜了半天才发现arduino unoI2C口在模拟口45
四条线从上到下分别接GND5VA4A5


软件部分
线总算连接好了,但屏幕上半片黑,下半片白,库文件找了好多都没解决,搜了好多资料,总算找到个能用的。
下面这篇写得很详细,使用方法也很简单,相信看了库中示例后都能学会。最后总算在它的指导下完成了!
http://forum.arduino.cc/index.php?topic=128635.msg967608
之后又遇到了一个很郁闷的事情,在我信心满满把程序中需要输出结果的地方都加上lcd指令后发现输入arduino后什么动静都没了,就像死机了一样。原来以为是冲突的问题,就一条条试代码,一条条删除直到正常为止。发现保留某几条lcd指令是可以正常问题的,而另一些一旦加入必定出事。研究了好几天,一直没有明白,在我几乎放弃之际,偶然间屏幕出现了“Temperature:”这竟然是我Serial.print出来的东西!!!顿时明白Serial输出与lcd输出之间必然有冲突!!!删除所有Serial后,一切正常。
切记:Serial.print与lcd.print不能同时使用!!!

7.设计的控制遥控器使用方法:
  
空调开关
  



电扇开关
改变
  
风类


Iptv开关








风扇
  
摇头


频道
  
频道
  

温度
  
温度
  



改变
  
风速

电视
  
开关
音量
  
音量
  
0
模式
  
切换



模式
  
切换



模式
  
切换
待机
  
确认
1
2
3








4
5
6








7
8
9








          Mode1:Air-conditioner                                      Mode2:Fan                                   Mode3:Iptv  
空调模式下数字需要连续输入两个,先十位数后个位数,且范围在18-30度之间,否则报警且需重新输入

注意:IDE中的1.0.5虽然是稳定版,但引用的一些库好像不能正常通过编译,1.5.1却可以,建议使用。

(2)网络控制部分
红外控制的功能已经实现,接下来就是项目的优化过程。
最先想到的就是基于网络实现远程控制。后来知道,这就是物联网的概念。思路是这样的,通过温湿传感器反馈当前环境的温湿度,将数据上传到网络,如果到了警示值,通过邮件、微博通知用户,用户打开控制页面,发送指令(如开空调),uno定时访问网络,当发现需要执行指令时,发射相应的红外指令(空调开启)。
看了几篇相关的文章,发现在实现网络控制方面,以亿联(yeelink)和乐联网两个网站最为热门,且都提供相应的现成程序上传下载数据。
有了网站的支持和网友们经验的分享,看似高霸上的网络控制其实还是可以完成的,就是与之前遇到的一样,总有一些意想不到的困难。
硬件方面:
联网的组件比较流行的有两种。一是本项目使用的w5100,还有就是ENC28J60。W5100使用的人比较多,而且程序提供的比较多,容易上手,但缺点是价格有点昂贵,都和uno一个价了。相比之下ENC28J60十几元的价格还是挺实惠的。另外,w5100还有microSD接口(注意不是SD,尽管大多网店都说是SD)可以实现文件读取。令人欣喜的是,我们亲爱的学校提供500元经费支持项目,那么毫不犹豫,果断w5100。
W5100是uno的扩展,直接在uno上叠起来就可以使用。
但是马上遇到的是端口占用问题。也不知道w5100是怎么样的设计,端口被占用不少,至少我发现D10以上端口是没法用的,也不排除有其他端口。反正,把原来的接线接上后完全没法用了。这又让我郁闷了很久,反复调试都没法解决。
之前发过贴问过,还是没能解决。
http://www.geek-workshop.com/thread-7377-1-1.html
最后我灵机一动,经费充足,干脆就用两块uno算了。(我不是土豪)两者的通信方式就直接用红外了。也就是,原有的uno(控制uno)接线不变,新的uno搭载w5100(网络uno),并用红外发射管向红外接收器发射信号,实现单向的信息传输,且传送的信息就是控制遥控器的按键信息,发射头就放在接收头下。单向传输的特性决定了温湿度传感器不能向网络uno传输数据,所以就调整到网络uno上接收温湿度传感器值。
最后加上一个重复发射按钮发射上一个信号以便调试时测试响应距离。
这样就完成了硬件部分的所有连接。
      附上局部图:其中下侧黄色和蓝色线连接网络uno

软件方面:
必须承认,网络控制方面,最主要和最烦人的是程序和配置的问题。
由于资料比较多,一开始使用的是乐联网,但是发现网关配置的东西一直搞不清楚,不仅需要网关地址还要公网地址,不知道是什么意思,不知道怎么配置,搞了半天没弄明白,就放弃了。
改用亿联(yeelink),虽然功能没有乐联网那么全,但是亿联不用设置网关,而且没有传感器数量限制。
Yeelink有官方库,但是我试了半天,总是不能同时上传与下载,最后还是根据某大神的代码更改完成了功能。
这篇文章对我帮助很大
http://hi.baidu.com/mizuda/item/fdd9c38a8e8237d9d1f8cdf6
首先要了解上传下载的流程,这需要涉及到http的知识。基本原理是,连入网络后
如需下载某开关值,需要先用client,print以http格式发送设备、开关编号及你的U-ApiKey号码(为了身份认证),服务器会返回一串Json代码,通过读取某一特定位置(倒数第二位)的值来判断开关的状态;如需上传,需要用client.print将待上传的值以特定的http格式,连同设备、传感器号及U-ApiKey发送。
需要注意的是,下载是分发送与接收两个步骤进行的。
注意:yeelink要求两次上传有最小时间间隔10s!否则传了也没用。
Yeelink在警示方面做得也是不错的,主要有邮件与微博警报,可以在yeelink用户中心进行设置,方法很简单,这里也不再阐述。

原帖来自:Geek-workshop

发表于 2016-12-13 00:27 | 显示全部楼层
大神 我想问问为什么那个调色板网页为什么打不开
 楼主| 发表于 2014-12-25 17:14 | 显示全部楼层


八、W5100+arduino+乐联网平台实现反向控制


1 说明
案例说明:使用Arduino+W5100来实现一个乐联网的应用,即通过乐联网手机App控制连接到Arduino+W5100上的LED的开关。
硬件:Arduino UNO W5100 shield
APP:乐联网 APP open.lewei50.com/home/sitecontent/ydkhd
系统平台:乐联网开放平台
2 反向控制硬件连线
硬件连线如下图,将LED灯的两个引脚线连接到Arduino转接板上的端口6和7上面(端口是根据Arduino程序里面自己选择定义的,如果选择其它端口,则硬件连线必须一致连接到相同端口上)。

3 Arduino模板程序获得与修改
3.1 获得arduino 代码
乐联网的相关Arduino代码托管在Github上,地址https://github.com/lewei50/leweiclient, 打开链接,点击Zip下载按钮,将名称为master.zip的文件下载到本地。

下载后解压,打开你电脑里的Arduino IDE所在文件夹里的libraries文件夹,在里面新建一个leweiclient的文件夹,将master压缩包解压缩后LeweiClient-master文件夹里的文件全部拷贝到这个文件夹里。

3.2 修改usrkey
运行Arduino.exe,在顶部菜单File—Examples—Leweiclient里面能看到control和upload,打开control即是反向控制的编程代码。


在执行代码前,首先需要到乐联网(http://www.lewei50.com/)上注册用户名和密码,在主页右上角有注册按钮,点击后填写账号、密码和邮箱以后,再登录到邮箱里面激活账号即可。登录进入系统后,通过点击左边管理菜单下“我的账号”—“设置个人信息”里面可以看到你的userkey,这个userkey是每个用户唯一的。

如上图,这是第一处需要修改的地方将程序里面的define LW_USERKEY后面的数值改成你实际个人账号的userkey
其它的变量基本不需要修改,解释如下:
LW_GATEWAY:乐联网的配置的网关标识;
MY_NAME:网关名称;
MY_NAME:网关介绍;
my_addr[50]:被控制的Arduino UNO板可以采取由无线路由器DHCP自动分配IP地址的方式来获取IP,也可以采用手动输入的静态的IP地址,如果采用静态IP地址,则这里输入http://静态IP地址/api,如图中,则表示静态的IP地址为192.168.1.221。
port:给Arduino UNO这个网络终端分配的控制端口号(跨网络控制时候有意义);

程序中上面的代码中,如果是“if 0”,则表示不采用静态IP地址的方式,如果是“if 1”,则表示采用静态IP地址,则继续执行下面代码,解释如下:
IPAddress myip:这里需要输入手动配置给Arduino UNO板的IP地址,与前面的my_addr[50]里的IP地址要保持一致;
IPAddress dnsip:这里需要输入与W5100相连接的路由器的DNS的IP地址,查询方法,登录进入路由器配置界面,查看WAN口状态(不同厂商的路由器查询方法不一致,但都能看到WAN口状态)里面的DNS服务器选项。
IPAddress dnsip:这里需要输入与W5100相连接的路由器的IP地址;
IPAddress gateway:这里需要输入与W5100相连接的路由器的DNS的IP地址
3.3 选择不同的控制方式
这里是第二处需要修改的地方,下面看后面的这几行代码,根据具体情况选择网关注册方式:
     lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr, (LeWeiClient::flag)((LeWeiClient::isControlled)|(LeWeiClient::internetAvailable)));
   // lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr, (LeWeiClient::flag)(LeWeiClient::isControlled));
// lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr, (LeWeiClient::flag)(LeWeiClient::none));
   上面的代码其中LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr等变量的定义前文已有叙述。这里的三条语句分别适用于三种不同的场景:
3.3.1不设置控制的情况
如果设置网关不具备反向控制的功能的话,则运行下面语句,其它语句可以注释掉:
lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr, (LeWeiClient::flag)(LeWeiClient::none)); 运行程序后网关配置如下:

这就表示这种配置下的网关是不可控的。
3.3.2手机与Arduino+W5100在同一网段下
如果控制的手机和Arduino+W5100的IP地址在同一网段下,则运行下面的语句,
lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr, (LeWeiClient::flag)(LeWeiClient::isControlled));
LeWeiClient::isControlled:配置网关是可控的;
设置后运行该程序后,则在乐联网的管理菜单“我的物联网”的“我的网关列表”点击“编辑”网关后里面可以看到网关的配置情况如下图,可以看到“是否可控”选项已经勾选,但是“公网访问”没有勾选“允许”。

3.3.3手机与Arduino+W5100 跨网段
手机通过公网控制Arduino+W5100则需要运行以下语句:
lwc = new LeWeiClient(LW_USERKEY, LW_GATEWAY,MY_NAME, MY_DESC, my_addr, (LeWeiClient::flag)((LeWeiClient::isControlled)|(LeWeiClient::internetAvailable)));其它语句注释,其中LeWeiClient::internetAvailable设置是否允许访问公网。运行程序后网关配置如下:

需要说明的是:如果想要实现跨网段控制,arduino+w5100接入的网络路由器要有公网地址,可以在路由器上面做到Arduino+W5100的NAT映射。(联通基本上符合条件,小区宽带的用户基本上都不符合要求)。NAT映射的设置需要在路由器配置界面里进行配置(一般在“转发规则”里的“虚拟服务器设置”),如下图:

3.4 修改实际的应用代码
这是最后一处需要修改的地方,红色部分是我写的应用代码,可以按照自己的应用编写实际的代码。
这里建立了两个执行器,名称分别为DADA2。描述分别为dummy2 dummy1
dummy_act the_act("DA", "dummy actuator", "dummy2");
dummy_act the_act2("DA2", "dummy actuator", "dummy1");
class dummy_act: public LeWeiActuator
{
   private:char led;  
   public:
        dummy_act(
                const char *id,
                const char *type,  
                const char *name) : LeWeiActuator(id, type, name)
    {};
        virtual bool updateValue(char* id,int val)
        {
            Serial.print("dev id = ");  
            Serial.println(id);
            if(!strcmp(id,"DA"))
            {
              Serial.println("handle da routin");
            
              digitalWrite(ledPin_da, val);
            }
            if(!strcmp(id,"DA2"))
            {
              Serial.println("handle da2 routin");
                  digitalWrite(ledPin_da2, val);
            }
            Serial.print("update actuator ");
            Serial.println(val);
            led=val;
            return val;
        }
        virtual bool getValue(int *val)

        {

            static int i = 0;

            *val = led;

            return true;

        }

};
3.5 通过app来控制arduino
下载乐联网手机App:http://open.lewei50.com/home/sitecontent/ydkhd
同一网段:
安装后使用乐联网的账号密码登录进去,手机和Arduino+W5100在同一网段,选择反向控制,进入反向控制界面,App会自动找到API地址(如果没有手动输入也可以),点击右上角“查找可控设备”,则进入控制界面,如果你的LED灯已经在Arduino板上连线好了,就可以点击可控设备列表的相关设备进行LED亮灭控制了。  
               
不同网段:

3.6 通过web的控制arduino(需要跨网支持)
如果已经可以完成app跨网段的控制,可以再近一步进行这个通过web控制arduino的实验。为后面制定阶段性任务执行打基础(比如说在web上面定义一个执行计划,每天6点关灯,18点开灯)
添加两个控制设备,缩写分别为DA 和 DA2(与前面建立的两个执行器缩写名一定要一致)

如果一切正常,设备应该显示在线状态(已打开或者已关闭)


发表于 2014-12-5 18:05 | 显示全部楼层
太详细了,辛苦。。。。
 楼主| 发表于 2014-12-11 13:30 | 显示全部楼层

六、可视化网络电表搭建攻略

×友情提示,修改电路前,一定要断开电源总开关×

你想象过看着家里的电器用电的样子吗?
你知道你每月那几天交的钱都去了哪里了吗?
你知道是什么东东在偷偷的用你的电吗?

如果你感兴趣,下面的文章适合你。

电,对于很多人来说是个很神秘,很危险,很神奇的东西。现在通过下面的攻略,你也可以拥有这样神奇的超能力,看到家里的电跑到哪里去了,是不是很想要?

你需要:
一个测电笔
一个十字口螺丝刀
一个平口螺丝刀
一把尖嘴钳
一个电量测量模块
一个通讯底板(我用的乐联网的E-KIT),你也可以使用任何一种arduino+w5100模块来搭建。

====广告结束===

先看看效果图(据说近期会有新版的展示界面)
在线链接:
http://www.lewei50.com/u/g/1979


新版展示界面:


看到下面的锯齿状图形了吗?那就是你的冰箱在努力保持西瓜的新鲜。
几个用电高峰,是空调们在为主人降温。
用电量怎么总是高于0呢?那是你的无线路由器在保持家里的网络时刻畅通。

现在分步骤来实现它:
1断电
要断开家里空气开关的总闸,如果有室外的总闸,那就拉室外的总闸,保证家里是没有电的。
操作时严禁一只手碰火线,一只手碰零线。

2接线
打开家里的配电箱,找到总的进户的火线,拆开,把电量测量模块的圈圈套在这个火线上,专业术语是“互感器”。并把火线按照原来的位置接回去。

按照接线说明图,连接好测量模块、通讯模块和arduino。
3通电
如果你的操作正确,这时候推上你家的空气开关总闸,是不会有任何反应的。如果有问题,会跳闸。
4注册网站及设置对应传感器
http://www.lewei50.com/
注册及配置传感器过程不详细说明了。简单说下我的传感器的命名,你也可以有你自己的。

5刷代码
刷代码是为了从通讯模块里面把电量等数据读出来,并上传到乐联网上。
代码中使用了乐联网的类库,从这里下载:
http://www.github.com/lewei50/LeWeiClient/


[mw_shl_code=c,true]// LeWei AC Power Meter trail success2013.06.25
// LeWei AC Power Meter (ZongBiao60A)trail syccess 2013.06.30 18:50pm
// 4 Parameter: watt / kwh / Amp / Voltage / Pf

/* FIXME: not yet being used */
unsigned long interframe_delay = 2;  /* Modbus t3.5 = 2 ms */

/*
* preset_multiple_registers: Modbus function 16. Write the data from an
* array into the holding registers of a slave.
* INPUTS
* slave: modbus slave id number
* start_addr: address of the slave's first register (+1)
* reg_count: number of consecutive registers to preset
* data: array of words (ints) with the data to write into the slave
* RETURNS: the number of bytes received as response on success, or
*         0 if no bytes received (i.e. response timeout)
*        -1 to -4 (modbus exception code)
*        -5 for other errors (port error, etc.).
*/

int preset_multiple_registers(int slave, int start_addr,
int reg_count, int *data);

/*
* read_holding_registers: Modbus function 3. Read the holding registers
* in a slave and put the data into an array
* INPUTS
* slave: modbus slave id number
* start_addr: address of the slave's first register (+1)
* count: number of consecutive registers to read
* dest: array of words (ints) on which the read data is to be stored
* dest_size: size of the array, which should be at least 'count'
* RETURNS: the number of bytes received as response on success, or
*         0 if no valid response received (i.e. response timeout, bad crc)
*        -1 to -4 (modbus exception code)
*        -5 for other errors (port error, etc.).
*/

int read_holding_registers(int slave, int start_addr, int count,
int *dest, int dest_size);


/*
   open.lewei50.com  sensor  client
*/



#include <SPI.h>
#include <Ethernet.h>
#include <LeweiClient.h>

#define USERKEY          "Your API Key" // replace your key here
#define LW_GATEWAY       "Your Gateway No."

LeWeiClient *lwc;


unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 30*1000; //delay between updates to cosm.com


int pin = 8;
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 30000;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
double concentration = 0;

void setup() {

   // start serial port:
   Serial.begin(4800);
   pinMode(8,INPUT);

  delay(10000);               

   lwc = new LeWeiClient(USERKEY, LW_GATEWAY);

   starttime = millis();
}
/* filter program : 20130521 */
#define FILTERLEN 10

unsigned long Array_Average( unsigned long* Array,int length)
{
    int x;
    unsigned long returnVal;
    unsigned long result=0;
    for(x=0;x<length;x++)
    {
      result+=Array[x];
      Serial.print("result=");
      Serial.println(result);
    }
    returnVal=result/length;
    return returnVal;
}

unsigned long Filter1(unsigned long lowpulse)
{
  static unsigned long sfiterArray[FILTERLEN];
  static int sindex=0;
  int x;
   Serial.println("filter1 begin:");
  if(FILTERLEN>sindex)
  {
      sindex++;
      Serial.println(sindex);
      sfiterArray[sindex]=lowpulse;
         Serial.println("filter1 END");
      return lowpulse;
  }
  else
  {
      for(x=0;x<FILTERLEN-1;x++)
      {
        sfiterArray[x]=sfiterArray[x+1];
      }
      sfiterArray[FILTERLEN-1]=lowpulse;
      for(x=0;x<FILTERLEN;x++)
      {
         Serial.println(sfiterArray[x]);
      }
      Serial.println("Aver:");
       Serial.println(Array_Average(sfiterArray,FILTERLEN));
       Serial.println("filter1 END");
      return(Array_Average(sfiterArray,FILTERLEN));

  }


}
/*END: filter program : 20130521 */

int x=0; //simulated sensor output
int sampling=1;
int transfering=0;

/* Modbus para */
int retval;
int data[10];
int tt[30];  //int changed to unsigned int

void loop() {

  int i;     
  /* example, this will write some data in the first 10 registers of slave 1  */
  //                retval = preset_multiple_registers(1,1,10, data);

  //                data[0] = retval;
  //                data[1]++;
  //                data[8]=0xdead;
  //                data[9] = 0xbeaf;
  //                delay(500);
  //int read_holding_registers(int slave, int start_addr, int count,int *dest, int dest_size);               
  //                retval = read_holding_registers(2,1, 1,tt,6);      
  retval = read_holding_registers(1, 0x49, 6, tt, 1); // 1:5,2:7,3:9
  //                delay(1000);
  //                Serial.print("receve flag=");               
  //                Serial.println(retval);


  int     Voltage  = tt[0];
          Voltage  = Voltage / 100;
  float   Amp      = tt[1];
          Amp      = Amp / 1000;
  int     Watt     = tt[2];
  //long y=x0*65536+x1;
  unsigned   int Kwhh = (unsigned int)tt[3];
  //unsigned int Kwhh = (unsigned int)65535; //test maximum
  unsigned   int Kwhl = (unsigned int)tt[4];
  unsigned   long kwhA = (unsigned long) Kwhh *65536 + Kwhl;
  //    unsigned  long kwhA = Kwhh <<16 + Kwhl;
  float Kwh = kwhA;
  Kwh = Kwh / 3200;
  //    double Kwh  = kwhA / 3200; //Kwh  = kwh / 32;
  //    int Kwh     = tt[4];
  float Pf = tt[5];
        Pf = Pf / 1000;
  float Cabon  = tt[5];
        Cabon  = Cabon / 1000;


  Serial.print(Voltage);
  Serial.print(Amp);
  Serial.print(Watt);
  Serial.print(Kwh);
  Serial.print(Pf);
  Serial.print(Cabon);


// 4 Parameter: watt / kwh / Amp / Voltage / Pf
// 这里的名字要跟你之前在网站上设置的对应起来

      lwc->append("kwh", Kwh);
      lwc->append("w", Watt);
      lwc->append("a", Amp);
      lwc->append("v", Voltage);
      lwc->append("pf", Pf);
//      lwc->append("06", Cabon);


        lwc->send();   
        delay(15000);
}

// this method makes a HTTP connection to the server:


/****************************************************************************
* BEGIN MODBUS RTU MASTER FUNCTIONS
****************************************************************************/

//#define TIMEOUT 1000          /* 1 second */
#define TIMEOUT 10000          /* 10 second */
#define MAX_READ_REGS 125
#define MAX_WRITE_REGS 125
#define MAX_RESPONSE_LENGTH 256
#define PRESET_QUERY_SIZE 256
/* errors */
#define PORT_ERROR -5

/*
CRC

INPUTS:
buf   ->  Array containing message to be sent to controller.           
start ->  Start of loop in crc counter, usually 0.
cnt   ->  Amount of bytes in message being sent to controller/
OUTPUTS:
temp  ->  Returns crc byte for message.
COMMENTS:
This routine calculates the crc high and low byte of a message.
Note that this crc is only used for Modbus, not Modbus+ etc.
****************************************************************************/

unsigned int crc(unsigned char *buf, int start, int cnt)
{
  int i, j;
  unsigned temp, temp2, flag;

  temp = 0xFFFF;

  for (i = start; i < cnt; i++) {
    temp = temp ^ buf;

    for (j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp = temp >> 1;
      if (flag)
        temp = temp ^ 0xA001;
    }
  }

  /* Reverse byte order. */

  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;

  return (temp);
}


/***********************************************************************
*
*      The following functions construct the required query into
*      a modbus query packet.
*
***********************************************************************/

#define REQUEST_QUERY_SIZE 6     /* the following packets require          */
#define CHECKSUM_SIZE 2          /* 6 unsigned chars for the packet plus   */
/* 2 for the checksum.                    */

void build_request_packet(int slave, int function, int start_addr,
int count, unsigned char *packet)
{
  packet[0] = slave;
  packet[1] = function;
  start_addr -= 1;
  packet[2] = start_addr >> 8;
  packet[3] = start_addr & 0x00ff;
  packet[4] = count >> 8;
  packet[5] = count & 0x00ff;

  //below test only
  //        packet[0] =0x01;
  //        packet[1] = 0x03;
  //        packet[2] = 0;
  //        packet[3] = 0x48;
  //        packet[4] = 0;
  //        packet[5] = 0x02;
}

/*************************************************************************
*
* modbus_query( packet, length)
*
* Function to add a checksum to the end of a packet.
* Please note that the packet array must be at least 2 fields longer than
* string_length.
**************************************************************************/

void modbus_query(unsigned char *packet, size_t string_length)
{
  int temp_crc;

  temp_crc = crc(packet, 0, string_length);

  packet[string_length++] = temp_crc >> 8;
  packet[string_length++] = temp_crc & 0x00FF;
  packet[string_length] = 0;
}



/***********************************************************************
*
* send_query(query_string, query_length )
*
* Function to send a query out to a modbus slave.
************************************************************************/

int send_query(unsigned char *query, size_t string_length)
{

  int i;

  modbus_query(query, string_length);
  string_length += 2;

  for (i = 0; i < string_length; i++) {
    //                Serial.print(query, HEX); //Orginal
    Serial.write(query); //JingLi

  }
  /* without the following delay, the reading of the response might be wrong
   * apparently, */
  delay(200);            /* FIXME: value to use? */

  return i;           /* it does not mean that the write was succesful, though */
}


/***********************************************************************
*
*      receive_response( array_for_data )
*
* Function to monitor for the reply from the modbus slave.
* This function blocks for timeout seconds if there is no reply.
*
* Returns:     Total number of characters received.
***********************************************************************/

int receive_response(unsigned char *received_string)
{

  int bytes_received = 0;
  int i = 0;
  /* wait for a response; this will block! */
  while(Serial.available() == 0) {
    delay(1);
    if (i++ > TIMEOUT)
      return bytes_received;
  }
  delay(200);
  /* FIXME: does Serial.available wait 1.5T or 3.5T before exiting the loop? */
  while(Serial.available()) {
    received_string[bytes_received] = Serial.read();
    //                Serial.print(bytes_received);                       //only test
    //                Serial.print("-");                                //only test
    //                Serial.println(received_string[bytes_received]);  //only test
    bytes_received++;
    if (bytes_received >= MAX_RESPONSE_LENGTH)
      return PORT_ERROR;
  }   
  //Serial.print("bytes_received=");
  //Serial.println(bytes_received);
  return (bytes_received);
}


/*********************************************************************
*
*      modbus_response( response_data_array, query_array )
*
* Function to the correct response is returned and that the checksum
* is correct.
*
* Returns:     string_length if OK
*           0 if failed
*           Less than 0 for exception errors
*
*      Note: All functions used for sending or receiving data via
*            modbus return these return values.
*
**********************************************************************/

int modbus_response(unsigned char *data, unsigned char *query)
{
  int response_length;
  int i;
  unsigned int crc_calc = 0;
  unsigned int crc_received = 0;
  unsigned char recv_crc_hi;
  unsigned char recv_crc_lo;

  do {        // repeat if unexpected slave replied
    response_length = receive_response(data);
  }
  while ((response_length > 0) && (data[0] != query[0]));
  //      for (i = 0; i <response_length; i++) {           Serial.print(data);Serial.print("---");   Serial.println(query);}                       //only test

  if (response_length) {


    crc_calc = crc(data, 0, response_length - 2);

    recv_crc_hi = (unsigned) data[response_length - 2];
    recv_crc_lo = (unsigned) data[response_length - 1];

    crc_received = data[response_length - 2];
    crc_received = (unsigned) crc_received << 8;
    crc_received =
      crc_received | (unsigned) data[response_length - 1];


    /*********** check CRC of response ************/

    if (crc_calc != crc_received) {
      response_length = 0;
      //                       Serial.println("CRC erro");                       //only test
    }



    /********** check for exception response *****/

    if (response_length && data[1] != query[1]) {
      response_length = 0 - data[2];
    }
  }
  return (response_length);
}


/************************************************************************
*
*      read_reg_response
*
*      reads the response data from a slave and puts the data into an
*      array.
*
************************************************************************/

int read_reg_response(int *dest, int dest_size, unsigned char *query)
{

  unsigned char data[MAX_RESPONSE_LENGTH];
  int raw_response_length;
  int temp, i;

  raw_response_length = modbus_response(data, query);
  if (raw_response_length > 0)
    raw_response_length -= 2;

  if (raw_response_length > 0) {
    /* FIXME: data[2] * 2 ???!!! data[2] isn't already the byte count (number of registers * 2)?! */
    for (i = 0;
               i < (data[2] * 2) && i < (raw_response_length / 2);
               i++) {

      /* shift reg hi_byte to temp */
      temp = data[3 + i * 2] << 8;
      /* OR with lo_byte           */
      temp = temp | data[4 + i * 2];

      dest = temp;
    }
  }
  return (raw_response_length);
}


/***********************************************************************
*
*      preset_response
*
*      Gets the raw data from the input stream.
*
***********************************************************************/

int preset_response(unsigned char *query)
{
  unsigned char data[MAX_RESPONSE_LENGTH];
  int raw_response_length;

  raw_response_length = modbus_response(data, query);

  return (raw_response_length);
}


/************************************************************************
*
*      read_holding_registers
*
*      Read the holding registers in a slave and put the data into
*      an array.
*
*************************************************************************/

int read_holding_registers(int slave, int start_addr, int count,
int *dest, int dest_size)
{
  int function = 0x03;      /* Function: Read Holding Registers */
  int ret;

  unsigned char packet[REQUEST_QUERY_SIZE + CHECKSUM_SIZE];

  if (count > MAX_READ_REGS) {
    count = MAX_READ_REGS;
  }

  build_request_packet(slave, function, start_addr, count, packet);

  if (send_query(packet, REQUEST_QUERY_SIZE) > -1) {
    ret = read_reg_response(dest, dest_size, packet);
  }
  else {

    ret = -1;
  }

  return (ret);
}


/************************************************************************
*
*      preset_multiple_registers
*
*      Write the data from an array into the holding registers of a
*      slave.
*
*************************************************************************/

int preset_multiple_registers(int slave, int start_addr,
int reg_count, int *data)
{
  int function = 0x10;      /* Function 16: Write Multiple Registers */
  int byte_count, i, packet_size = 6;
  int ret;

  unsigned char packet[PRESET_QUERY_SIZE];

  if (reg_count > MAX_WRITE_REGS) {
    reg_count = MAX_WRITE_REGS;
  }

  build_request_packet(slave, function, start_addr, reg_count, packet);
  byte_count = reg_count * 2;
  packet[6] = (unsigned char)byte_count;

  for (i = 0; i < reg_count; i++) {
    packet_size++;
    packet[packet_size] = data >> 8;
    packet_size++;
    packet[packet_size] = data & 0x00FF;
  }

  packet_size++;
  if (send_query(packet, packet_size) > -1) {
    ret = preset_response(packet);
  }
  else {
    ret = -1;
  }

  return (ret);
}
[/mw_shl_code]






 楼主| 发表于 2014-12-19 15:23 | 显示全部楼层


第一部分 在使用微博播报室内温度之前,需要先将温度传感器连接到Yeelink平台。
1、硬件

2、软件

(1) 注册Yeelink账号;

(2) 下载Yeelink移动客户端APP;

(3) 安装Arduino IDE。

3、在Yeelink平台上添加设备和传感器

(1) 进入用户中心

2. 增加新设备

3. 增加传感器
4、修改调试软件
1.安装yeelink SDK
下载完成后解压,并将文件夹复制到Arduino安装目录下的libraries目录下,复制完成之后重启Arduino IDE。
2.将代码复制到Arduino编译器中


3. 在程序中相应的位置替换自己的API KEY、设备编号和传感器编号

4、连接电路

(1)将W5100扩展版对应安插在Arduino上

2)按下图连接线路

3). 用USB数据线将Arduino与电脑连接起来

(4)用网线将W5100连接到路由器
( 5)将准备好的程序传输到Arduino开发板上
大功告成!我们可以通过手机APP和网页来监测温度变化了!
5、通过手机APP或者网页控制LED
(1) 通过手机APP监测
2. 通过Yeelink网页平台监测

在用户中心中选择“我的设备”—“管理设备”选择相应的设备即可看到温度的变化曲线


1、添加动作

现在我们已经成功添加了一个名为“微博播报”的动作


2、增加触发


3、微博播报
经过我们的设置,当传感器温度大于30度的时候yeelink就会自动发送微博


Code.zip

785 Bytes, 下载次数: 76

发表于 2014-12-26 11:28 | 显示全部楼层
很有意思{:soso_e179:}很受启发。
发表于 2015-2-13 18:58 | 显示全部楼层
甘多好耶点样消化
发表于 2015-2-24 14:08 | 显示全部楼层
慢慢学习{:soso_e179:}
 楼主| 发表于 2015-2-25 17:36 | 显示全部楼层

一起学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 00:48 , Processed in 0.422204 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表