arduino-tinker 发表于 2013-7-19 14:21:07

Arduino与Yeelink编程

本帖最后由 arduino-tinker 于 2013-7-19 15:10 编辑

潜水了好长时间了,出来冒个泡。最近在用Arduino+Yeelink做能推送微博的智能家居,希望能把制作过程和大家分享下。因为论坛里相关的帖子也比较多,所以在这我就重点分析下代码。(PS:本人学疏才浅,如果有错,还望大家多多包涵)

在制作的过程中主要参考了:
1、lemodd 的《uno+w5100向yeelink传数据,经常会没反应》
2、erjiang 的《arduino+yeelink,用传感器数据触发新浪微博吧!》

制作流程:
(一)硬件准备
1、Arduino UNO 一块


2、W5100 一块(网上买的山寨版,50元,不过支持官方的库文件)


3、DHT11 一个


4、传感器扩展板(选用)


(二)注册yeelink账号
可以参考:
http://www.yeelink.net/develop/quickstart

(三)硬件连接
把板子一个落一个,DHT11接PIN3(PS:是不是因为山寨板子的缘故,板子间会卡住啊!)


(四)程序
这是yeelink提供的程序:http://blog.yeelink.net/?p=34
这是DHT11的程序:DHT11 测试

#include <SPI.h>
#include <Ethernet.h>
#include <math.h>
#include <dht11.h>

dht11 DHT11;
#define DHT11PIN 3// DHT11连接PIN3

// 配置你的yeelink api
#define APIKEY         "xxxxxxxx"// 输入你的 yeelink api key
#define DEVICEID       xx// 输入你的设备ID
#define TEMPERATURE_SENSORID       xx// 输入你的温度传感器ID
#define HUMIDITY_SENSORID       xx// 输入你的湿度传感器ID

byte mac[] = { 0x00, 0x1D, 0x72, 0x82, 0x35, 0x9D};// 为Ethernet分配MAC地址
// 初始化库
EthernetClient client;
char server[] = "api.yeelink.net";   // yeelink API的地址

unsigned long lastConnectionTime = 0;          // 初始化连接时间
boolean lastConnected = false;
const unsigned long postingInterval = 30*1000;

int sensor = 0;   // 初始化传感器编号
                  // 0为温度传感器
                  // 1为湿度传感器
                  
void setup()
{
Serial.begin(9600);//开启串口
// 开启Ethernet的连接
if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    for(;;)
      ;
}
else {
    Serial.println("Ethernet configuration OK");
}
// 打印DHT11的库文件版本
Serial.print("LIBRARY VERSION: ");
Serial.println(DHT11LIB_VERSION);
Serial.println();

}

void loop() {
// 如果有来自互联网的数据,发送到串口
if (client.available()) {
    char c = client.read();
    Serial.print(c);
}

// 如果无连接且存在lastConnected,关闭客户端
if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
}

// 如果当前无连接,10秒后继续连接并发送数据
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
// 分别发送温度、湿度数值
switch(sensor){
      case 0:
          sendData(readSensor(HUMIDITY_SENSORID), HUMIDITY_SENSORID);
          break;
      case 1:
          sendData(readSensor(TEMPERATURE_SENSORID), TEMPERATURE_SENSORID);
          break;
}
if(++sensor > 1) sensor = 0;
}

// 储存经历整个循环的时间
lastConnected = client.connected();
}

// 定义接受数据函数
int readSensor(int sensor_id)
{
Serial.println("\n");

int chk = DHT11.read(DHT11PIN); // 从PIN3读取数值
// 判断传感器是否正常
Serial.print("Read sensor: ");
switch (chk)
{
    case DHTLIB_OK:
                Serial.println("OK");
                break;
    case DHTLIB_ERROR_CHECKSUM:
                Serial.println("Checksum error");
                break;
    case DHTLIB_ERROR_TIMEOUT:
                Serial.println("Time out error");
                break;
    default:
                Serial.println("Unknown error");
                break;
}
// 打印温度、湿度
if(sensor_id == HUMIDITY_SENSORID){
    Serial.print("Humidity (%): ");
    Serial.println(DHT11.humidity);
    return DHT11.humidity;
}else{
    Serial.print("Temperature (oC): ");
    Serial.println(DHT11.temperature);
    return DHT11.temperature;
}
}

// 定义发送数据函数
void sendData(int thisData) {
// 如果成功连接
if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // 发送HTTP PUT请求
    client.print("POST /v1.0/device/");
    client.print(DEVICEID);
    client.print("/sensor/");
    client.print(SENSORID);
    client.print("/datapoints");
    client.println(" HTTP/1.1");
    client.println("Host: api.yeelink.net");
    client.print("Accept: *");
    client.print("/");
    client.println("*");
    client.print("U-ApiKey: ");
    client.println(APIKEY);
    client.print("Content-Length: ");

    // 计算http包里面内容部分的长度,即content-length长度
    int thisLength = 10 + getLength(thisData);
    client.println(thisLength);

    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.println();

    // PUT回复内容
    client.print("{\"value\":");
    client.print(thisData);
    client.println("}");
}
else {
    // 如果连接失败
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
}
   // 标注连接时间
lastConnectionTime = millis();
}

// 以下内容没看懂啊,还望大虾指点
// This method calculates the number of digits in the
// sensor reading.Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:
int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
    dividend = dividend /10;
    digits++;
}
// return the number of digits:
return digits;
}

(五)连接及网页设定
可以参考:
http://www.yeelink.net/develop/quickstart
http://www.geek-workshop.com/forum.php?mod=viewthread&tid=1294


(PS:微博授权时间太短了,有木有啊!隔三差五就要去授权一次)

(六)评价
因为目前只有温度、湿度传感器,且上网时间不固定,所以没发挥出太大的作用,基本处于试运行阶段。等楼主9月开始去南航上学,有固定的场所和网络,再加一些传感器,相信不仅可以服务自己,也可以给大家提供便利。

附:
1、我的yeelink主页:板栗家的小A(昆明站)
2、用于推送数据的微博:@板栗家的小A(新浪微博)

sangyingahua 发表于 2013-7-20 10:14:49

请问enc28j60用法也一样吗?为什么我的就是不能成功

arduino-tinker 发表于 2013-7-20 23:48:09

sangyingahua 发表于 2013-7-20 10:14 static/image/common/back.gif
请问enc28j60用法也一样吗?为什么我的就是不能成功

你可以参考一下这里 http://www.geek-workshop.com/forum.php?mod=viewthread&tid=1165 这就是用ENC28J60的!

hp198969 发表于 2013-7-21 21:54:03

最后代码为计算发送数据的长度,用于yeelink端校验。

arduino-tinker 发表于 2013-7-21 23:03:36

hp198969 发表于 2013-7-21 21:54 static/image/common/back.gif
最后代码为计算发送数据的长度,用于yeelink端校验。

明白,非常感谢!我再去研究下!

jjkason 发表于 2013-10-11 15:39:16

sendData函数缺了一个变量

机智的小学生 发表于 2014-6-20 16:24:04

jjkason 发表于 2013-10-11 15:39 static/image/common/back.gif
sendData函数缺了一个变量

请问这个问题解决了吗?

akzono 发表于 2014-12-21 17:23:39

为啥我编译不能通过提示sendData()没有声明

雨轩 发表于 2015-5-30 17:13:35

编译出错!。。。

wunaidexiaoanyi 发表于 2015-9-10 09:18:03

sendData()编译出错怎么解决

Vac 发表于 2016-4-15 22:27:00

您好,请问W5100的库文件能给一个么?我实在是找了很久找不到:Q
页: [1]
查看完整版本: Arduino与Yeelink编程