极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 91763|回复: 47

【翻译教程】enc28J60 和 Arduino (14)——获取数据存储到服务器并显示图表

[复制链接]
发表于 2013-5-13 21:10:06 | 显示全部楼层 |阅读模式
终于等到原作者出第14篇教程了,我又可以来挣极客工坊淘宝杂货铺的¥5元的消费劵了,很多人还不知道吧,这儿帮极客工坊论坛宣传下吧,发表高质量文章就有可能获取金币的哦,而这个金币就可以在极客工坊的淘宝杂货铺当钱用哦,1金币=¥1元。hoho,看看你们有多少金币吧。好了,言归正传,原文在这儿,英文好的帮我校正下。。。多谢!




在本教程中,我将介绍如何开发一个小网站从Arduino的(使用Enc28j60盾)获取数据,存储并显示出图标曲线。

逻辑架构

您的网站将会由两页:

  • saveTemp.php,从Arduino获取数据,并将其存储在文本文件;
  • displayTemp.php,读取文本文件,并显示数据。




在这个例子中,Arduino使用SD18B20传感器获取房间的温度,我已经在博客的这篇文章介绍了该传感器。

对于网页编程,我选择了在网络上广泛使用PHP。

注意:为了保持简单的例子,数据被存储在一个CSV(逗号分隔值)文件,在实际应用中,最好使用一个数据库,例如MySQL。

发送数据

我使用的HTTP协议的GET方法将数据发送到Web服务器。这种方法请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:login.php?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。



为了防止其他用户发送数据,除了温度参数,你也必须发送到该网页的密码,使用pwd参数。

我的代码读取温度传感器,将其转换成字符串类型,并把它“print”到一个Stash对象:
  1. sensors.requestTemperatures();
  2. float float_temp = sensors.getTempCByIndex(0);

  3. char string_temp[7];
  4. dtostrf(float_temp, 4, 2, string_temp);

  5. Stash stash;
  6. byte sd = stash.create();
  7. stash.print(string_temp);
  8. stash.save();
复制代码
然后在另外一个Stash对象中准备请求(Http Get 请求),并用tcpSend()方法发送到服务器:
  1. Stash::prepare(PSTR("GET /demo/saveTemp.php?temp=$H&pwd=$F HTTP/1.0" "\r\n"
  2.     "Host: $F" "\r\n" "\r\n"),
  3.     sd, password, website);
  4. session_id = ether.tcpSend();
复制代码
由于会话标识符(SESSION_ID),你可以得到一个来自服务器的响应,并检查它是否包含错误消息(“KO”):
  1. const char* reply = ether.tcpReply(session_id);
  2. [...]
  3. if(strstr(reply, "KO - ") != 0) Serial.println(strstr(reply, "KO - "));
复制代码
在PHP中,你可以通过关联数组$_GET获得这些HTTP GET发送过来的数据:
  1. $temp = $_GET["temp"];
  2. $pwd = $_GET["pwd"];
复制代码
验证密码后,温度值以及对应的时间戳一起存储在文件中:
  1. define("LOG_FILE", "./temperatures.csv");
  2. [...]
  3. $file_handler = fopen(LOG_FILE, "a+");
  4. fwrite($file_handler, time() . "," . $temp . "\n");
复制代码
旁白请忽略,版主如果觉得不合适可以删除:哎要不要给我的维基拉点流量嘞。。。算了,还是让各位看官直接在这儿爽完吧。。。因为我饱受那样的痛苦。。。从此直接忽略掉这类文章。。。

数据显示

为了使这个例子更有趣,我决定把这些数据显示在图表上。

对于PHP,有一个很好的开源的图表库可供选择:JpGraph。要使用它,你必须把库文件上传到您的网站的子文件夹中,通常为“/JpGraph”:



在PHP代码中,你就必须包括需要的库,这取决于你要创建的图表类型:
  1. require_once('jpgraph/jpgraph.php');
  2. require_once('jpgraph/jpgraph_line.php');
复制代码
JpGraph库不负责获取图表所需的数据而是通过PHP代码,打开文件 - 按行 - 把数据保存到两个数组中:
  1. $file_lines = file(LOG_FILE, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
  2. foreach($file_lines as $line_num => $line_value) {
  3.         $line_elements = explode(",", $line_value);
  4.         $times[] = date("H:i:s", $line_elements[0]);
  5.         $values[] = $line_elements[1];
  6. }
复制代码
JpGraph可以为每组数据创建许多不同类型的图表, 你可以做很多的自定义:有关使用该库的例子和教程,请参考官方手册

运行

Arduino的草图和PHP网页的源代码可以在GitHub上我的存储库中下载,这里有两个截图显示运行状态:






翻译结束!

下面是我的验证过程:

软件准备

1.php服务站点,托破砖的福。。帮我建了一个——demo.microduino.net;
2.下载JpGraph库,下载地址在这儿
为保持完整也可直接从下面下载

3.解压缩后,将文件夹内的src文件夹更名为JpGraph,并上传到demo.microduino.net对应的根目录下;
4.下载例程所需文件,下载地址在这儿
也可直接从这儿下载

5.将displayTemp.php,saveTemp.php 2个文件拷贝到demo.microduino.net对应的根目录下;
可以更改saveTemp.php中的password。
  1. define("PASSWORD", "password");
复制代码
比如可更改为:
  1. define("PASSWORD", "xxxxxxx");
复制代码
硬件准备

1.microduino-core(也可用uno 或者nano);
2.Microduino-FT232R(如果用uno或者nano就不用这个了);
3.Microduino-ENC28J60-RJ45(也可用别的ENC28J60盾或者模块);
4.Test-Microduino
5.自制的18B20温度传感器(当然你也可以用现成的18B20温度传感器模块)。

开始试验

各个模块叠加,并插入Test-Microduino实验底板,并在底板上连接传感器:



恩,大家可以看到ENC28J60模块的片选是连接到D8,温度传感器模块数据端口是连接到A0的。
恩,如果用别的模块的请注意连线别连接错了哦。

我先休息10分钟,等大家连线,抽根烟,泡杯茶。。。。。

恩,大家连好了吧,我们继续:

插入网线和usb线:



下载代码:

[pre lang="arduino" line="1" file="_14_WebTemperature.ino"]#include <EtherCard.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define SEND_INTERVAL  5000
#define TIMEOUT        5000
#define ONE_WIRE_BUS   A0
#define STATUS_IDLE    0
#define STATUS_SENT    1

// ethernet interface mac address
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
// ethernet interface ip address
static byte myip[] = { 10,21,0,195 };
// gateway ip address
static byte gwip[] = { 10,21,0,1 };
// dns ip address
static byte mydns[] = { 10,11,5,25 };

byte Ethernet::buffer[700];

char website[] PROGMEM = "demo.microduino.net";
char password[] PROGMEM = "xxxxxxxx";

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

unsigned long previousMillis = 0;
static byte session_id;
byte actual_status;

void setup () {

  Serial.begin(57600);
  Serial.println("WebTemperature demo");
  Serial.println();

  if (!ether.begin(sizeof Ethernet::buffer, mymac)) {
    Serial.println( "Failed to access Ethernet controller");
    while(1);
  } else Serial.println("Ethernet controller initialized");

  if (!ether.staticSetup(myip, gwip,mydns)) {
    Serial.println("Failed to get configuration from DHCP");
    while(1);
  } else Serial.println("DHCP configuration done");

  if (!ether.dnsLookup(website)) {
    Serial.print("Unable to resolve Website IP");
    while(1);
  } else Serial.println("Website IP resolved");
  
  Serial.println();
  ether.printIp("IP Address:\t", ether.myip);
  ether.printIp("Netmask:\t", ether.mymask);
  ether.printIp("Gateway:\t", ether.gwip);
  ether.printIp("Website IP:\t", ether.hisip);
  Serial.println();
}
  
void loop() {

  ether.packetLoop(ether.packetReceive());
  unsigned long currentMillis = millis();
  
  switch(actual_status) {
    case STATUS_IDLE:
      if(currentMillis - previousMillis > SEND_INTERVAL) {
        previousMillis = currentMillis;
        sendTemperature();        
      }
      break;
    case STATUS_SENT:
      if(currentMillis - previousMillis > TIMEOUT) {
        Serial.println("No response");
        previousMillis = currentMillis;
        actual_status = STATUS_IDLE;
      }
      checkResponse();
  }
}   
  
void sendTemperature() {
  
  sensors.requestTemperatures();
  float float_temp = sensors.getTempCByIndex(0);
  
  char string_temp[7];
  dtostrf(float_temp, 4, 2, string_temp);
  
  Stash stash;
  byte sd = stash.create();
  stash.print(string_temp);
  stash.save();

  Stash::prepare(PSTR("GET /saveTemp.php?temp=$H&pwd=$F HTTP/1.0" "\r\n"
    "Host: $F" "\r\n" "\r\n"),
    sd, password, website);
  session_id = ether.tcpSend();
  Serial.print("Temperature ");
  Serial.print(string_temp);
  Serial.print(" sent to website... ");
  actual_status = STATUS_SENT;
}

void checkResponse() {
  
  const char* reply = ether.tcpReply(session_id);
  if(reply > 0) {
    if(strstr(reply, "KO - ") != 0) Serial.println(strstr(reply, "KO - "));
    else Serial.println("OK");
    actual_status = STATUS_IDLE;  
  }
}
[/code]

上传后,成功显示曲线

你们的成功了么?什么?还在接线啊。。。

返回目录

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1 +5 收起 理由
幻生幻灭 + 5 很给力!

查看全部评分

回复

使用道具 举报

发表于 2013-5-13 21:32:39 | 显示全部楼层
越来越难了啊
回复 支持 反对

使用道具 举报

发表于 2013-5-13 21:59:23 | 显示全部楼层
6点40分和7点40分,气温突然升高了5度,请问张老师当时在干什么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-5-13 22:03:40 | 显示全部楼层
Tiki 发表于 2013-5-13 21:59
6点40分和7点40分,气温突然升高了5度,请问张老师当时在干什么?

用手摸了下
回复 支持 反对

使用道具 举报

发表于 2013-5-13 22:49:57 | 显示全部楼层
php页面曲线是张图,不是很理想。不过这篇教程是个好的开始,这样利用服务器相对节省了Arduino的资源
回复 支持 反对

使用道具 举报

发表于 2013-5-13 22:56:21 | 显示全部楼层
Tiki 发表于 2013-5-13 21:59
6点40分和7点40分,气温突然升高了5度,请问张老师当时在干什么?

...你是暗示我们张老师在做什么热血沸腾的事情么?

哈哈~~~~ 气温五度 如果不是直接触摸或者是在附近用热源,让大范围(比如一个房间)空气上升短时间上升五度需要很大能量的
回复 支持 反对

使用道具 举报

发表于 2013-5-13 22:57:17 | 显示全部楼层
张老师。 帖子不错啊~~~ 精品啊~~
回复 支持 反对

使用道具 举报

发表于 2013-5-13 22:59:20 | 显示全部楼层
darkorigin 发表于 2013-5-13 22:56
...你是暗示我们张老师在做什么热血沸腾的事情么?

哈哈~~~~ 气温五度 如果不是直接触摸或者是在附近用 ...

说的这么具体。。。
回复 支持 反对

使用道具 举报

发表于 2013-5-13 23:00:26 | 显示全部楼层
城砖君好像正在开放 demo.microduino.net 的开放注册啊,是不是大家都可以试一试这个玩法了?
回复 支持 反对

使用道具 举报

发表于 2013-5-13 23:01:09 | 显示全部楼层
其实,感觉这个WEB服务器给的图比YEELINK看的舒服多了。而且这个算是私有传感器的服务端了。
话说YEELINK的话,很多人用摄像头传感器。。。万一在家里做点少儿不宜的运动。。。(宅男都懂的)被人看到了,就贻笑大方了哈哈
私有的服务器架设的传感器,首先限制少(不会数据间隔>15S 否则就.406 Err) 而且安全性好
回复 支持 反对

使用道具 举报

发表于 2013-5-13 23:04:43 | 显示全部楼层
本帖最后由 弘毅 于 2013-5-13 23:08 编辑

{:soso_e129:}新的一篇出来了。。。。果断加精。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-5-13 23:12:20 | 显示全部楼层
弘毅 发表于 2013-5-13 23:04
新的一篇出来了。。。。果断加精。。。

多谢郝老板
回复 支持 反对

使用道具 举报

发表于 2013-5-13 23:13:17 | 显示全部楼层
wasdpkj 发表于 2013-5-13 22:49
php页面曲线是张图,不是很理想。不过这篇教程是个好的开始,这样利用服务器相对节省了Arduino的资源

最好是个FLASH。但是那个涉及的东西又多了。 呵呵

可以再HTML里面加刷新的代码,每2S自动刷新。这样浏览起来图片就在跟着数据动了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-5-13 23:15:50 | 显示全部楼层
darkorigin 发表于 2013-5-13 23:01
其实,感觉这个WEB服务器给的图比YEELINK看的舒服多了。而且这个算是私有传感器的服务端了。
话说YEELINK的 ...

但是私有服务器成本会比较高,对个人来说难度会比较大,相对来说yeelink等物联网服务提供商让忘记能更快更容易上手,至于私密性,我想付费会员应该可以解决这个问题,其实给空间费域名费和给会员费道理是一样的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-5-13 23:18:59 | 显示全部楼层
Tiki 发表于 2013-5-13 23:00
城砖君好像正在开放 demo.microduino.net 的开放注册啊,是不是大家都可以试一试这个玩法了?

开放这个其实应该是可以实现的,开放ftp注册,每人限定一定的空间量。hoho。具体得看破砖这个专家了。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 18:42 , Processed in 0.048308 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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