1.1網路氣象站

本實作利用有線網路,在區域網路內建立一個溫濕度氣象站

有線網路反應速度與長時間穩定度皆高於esp8266無線氣象站

(但是對於不方便拉網路線的地方,還是有賴於esp8266氣象站)

[實作1.1]區域網路氣象站

本頁面可以在網址列輸入http://192.168.1.101 的方式顯示

#include "SPI.h"

#include "Ethernet.h"

#include "WebServer.h"

#include "Streaming.h" // 引用處理字串的程式庫(參閱下文說明)

#include "dht11.h"

dht11 DHT11; // 宣告 DHT11 程式物件

const byte dataPin = 2; // 宣告 DHT11 模組的資料輸入腳位

static byte mac[] = { 0xF0, 0x7B, 0xCB, 0x4B, 0x7C, 0x9F };

IPAddress ip(192, 168, 1, 101);

IPAddress subnet(255, 255, 255, 0);

IPAddress gateway(192, 168, 1, 1);

WebServer webserver("", 80);

P(htmlHead) =

"<!doctype html><html>"

"<head><meta charset=\"utf-8\">"

"<title>Arduino 溫濕度計</title>"

"</head><body>" ;

P(htmlFoot) = "</body></html>";

void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool)

{

int chk = DHT11.read(dataPin);

server.httpSuccess();

if (type != WebServer::HEAD){

server.printP(htmlHead);

if (chk == 0) {

server << "<h1>溫濕度計</h1>";

server << "<p>溫度:" << DHT11.temperature << "&deg;C</p>";

server << "<p>濕度:" << DHT11.humidity << "%</p>";

} else {

server << "<h1>無法讀取溫濕度值</h1>";

}

server.printP(htmlFoot);

}

}

void setup() {

Ethernet.begin(mac, ip, gateway, subnet);

webserver.setDefaultCommand(&defaultCmd); // 處理「首頁」請求

webserver.begin();

}

void loop() {

webserver.processConnection();

}

[實作1.2]區域網路氣象站(效率改進版)

本頁面可以在網址列輸入http://192.168.1.101 的方式顯示

對於網頁的標頭檔,網頁類型,編碼,和網頁內文不便的地方先讀入記憶體區

每次只刷新溫度與濕度那兩行

這樣可以減少伺服器的資料傳輸量

#include "SPI.h"

#include "Ethernet.h"

#include "WebServer.h"

#include "Streaming.h" // 引用處理字串的程式庫(參閱下文說明)

#include <DHT.h>

#define DHTPIN 2 //將DHT11連接到2腳位

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

static byte mac[] = { 0xF0, 0x7B, 0xCB, 0x4B, 0x7C, 0x9F };

IPAddress ip(192, 168, 1, 101);

IPAddress subnet(255, 255, 255, 0);

IPAddress gateway(192, 168, 1, 1);

WebServer webserver("", 80);

P(htmlHead) =

"<!doctype html><html>"

"<head><meta charset=\"utf-8\">"

"<title>Arduino 溫濕度計</title>"

"</head><body><h1>溫濕度計</h1>" ;

P(htmlFoot) = "</body></html>";

void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool){

char buffer[5] = "";

server.httpSuccess();

if (type != WebServer::HEAD){

server.printP(htmlHead);

server << "<p>溫度:" << dht.readTemperature() << "&deg;C</p>";

server << "<p>濕度:" << dht.readHumidity() << "%</p>";

server.printP(htmlFoot);

}

}

void setup() {

Ethernet.begin(mac, ip, gateway, subnet);

webserver.setDefaultCommand(&defaultCmd); // 處理「首頁」請求

webserver.begin();

}

void loop() {

webserver.processConnection();

}

[實作1.3]區域網路氣象站(自動更新頁面)

本頁面可以在網址列輸入http://192.168.1.101 的方式顯示

可加入 <meta http-equiv= "refresh" content= "3"> 表示每3秒更新一次頁面

其中因為此行已經在引號" "內,

因此必須把 "refresh" 改為 \"refresh\" 且把 "3" 改為 \"3\"

程式碼

#include "SPI.h"

#include "Ethernet.h"

#include "WebServer.h"

#include "Streaming.h" // 引用處理字串的程式庫(參閱下文說明)

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

#include <DHT.h>

#define DHTPIN 2 //將DHT11連接到2腳位

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

static byte mac[] = { 0xF0, 0x7B, 0xCB, 0x4B, 0x7C, 0x9F };

IPAddress ip(192, 168, 1, 101);

IPAddress subnet(255, 255, 255, 0);

IPAddress gateway(192, 168, 1, 1);

WebServer webserver("", 80);

P(htmlHead) =

"<!doctype html><html>"

"<head><meta charset=\"utf-8\">"

"<meta http-equiv=\"refresh\" content=\"3\">" //3 表示每3秒更新一次,可修改

"<title>Arduino 溫濕度計</title>"

"</head><body><h1>溫濕度計</h1>" ;

P(htmlFoot) = "</body></html>";

void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool)

{

char buffer[5] = "";

server.httpSuccess();

if (type != WebServer::HEAD){

server.printP(htmlHead);

server << "<p>溫度:" << dht.readTemperature() << "&deg;C</p>";

server << "<p>濕度:" << dht.readHumidity() << "%</p>";

server.printP(htmlFoot);

}

}

void setup() {

Ethernet.begin(mac, ip, gateway, subnet);

webserver.setDefaultCommand(&defaultCmd); // 處理「首頁」請求

webserver.begin();

lcd.init();

lcd.backlight();

lcd.clear();

}

void loop() {

webserver.processConnection();

lcd.setCursor(0,0);

lcd.print("T=");

lcd.print(dht.readTemperature(),1);

lcd.print(" RH=");

lcd.print(dht.readHumidity(),1);

lcd.print("% ");

lcd.setCursor(0,1);

lcd.print("192.168.1.101");

}

[實作1.4]區域網路氣象站(加入mDNS服務)

mDNS是一種不需要知道IP就能連入伺服器的技術,透過APPLE公司的bonjour技術

我們可以在區域網路創建一個微型DNS,透過 http://域名.local/ 的方式連入

本實作可透過 http://tomorrows.local/ 連入氣象站

或透過 http://192.168.1.101/ 連線

桃紅色的字體表示啟動mDNS需加入的程式碼

程式碼

#include "SPI.h"

#include "Ethernet.h"

#include "WebServer.h"

#include "Streaming.h" // 引用處理字串的程式庫(參閱下文說明)

#include <EthernetBonjour.h>

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

#include <DHT.h>

#define DHTPIN 2 //將DHT11連接到2腳位

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

static byte mac[] = { 0xF0, 0x7B, 0xCB, 0x4B, 0x7C, 0x9F };

IPAddress ip(192, 168, 1, 101);

IPAddress subnet(255, 255, 255, 0);

IPAddress gateway(192, 168, 1, 1);

WebServer webserver("", 80);

P(htmlHead) =

"<!doctype html><html>"

"<head><meta charset=\"utf-8\">"

"<meta http-equiv=\"refresh\" content=\"3\">" //3 表示每3秒更新一次,可修改

"<title>Arduino 溫濕度計</title>"

"</head><body><h1>溫濕度計</h1>" ;

P(htmlFoot) = "</body></html>";

void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool)

{

char buffer[5] = "";

server.httpSuccess();

if (type != WebServer::HEAD){

server.printP(htmlHead);

server << "<p>溫度:" << dht.readTemperature() << "&deg;C</p>";

server << "<p>濕度:" << dht.readHumidity() << "%</p>";

server.printP(htmlFoot);

}

}

void setup() {

Ethernet.begin(mac, ip, gateway, subnet);

webserver.setDefaultCommand(&defaultCmd); // 處理「首頁」請求

webserver.begin();

EthernetBonjour.begin("tomorrows"); //紅字的tomorrows 可以修改

EthernetBonjour.addServiceRecord("tomorrows.Web._http", //紅字可以修改

80,

MDNSServiceTCP);

lcd.init();

lcd.backlight();

lcd.clear();

}

void loop() {

EthernetBonjour.run();

webserver.processConnection();

lcd.setCursor(0,0);

lcd.print("T=");

lcd.print(dht.readTemperature(),1);

lcd.print(" RH=");

lcd.print(dht.readHumidity(),1);

lcd.print("% ");

lcd.setCursor(0,1);

lcd.print("192.168.1.101");

}

[實作1.5]區域網路氣象站(Tingspeak 物聯網網站)

#include <SPI.h>

#include <Ethernet.h>

// Local Network Settings

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // BIA or Physical mac address of W5100 Shield

byte ip[] = { 192, 168, 1, 101 }; // IP ADDRESS of your device

byte gateway[] = { 192, 168, 1, 1 }; // internet access via router

byte subnet[] = { 255, 255, 255, 0 }; // 24bit Subnet Mask

//EthernetServer server(80); //server port

//byte gateway[] = { 192, 168, 0, 1 }; //Internet access via router

//byte subnet[] = { 255, 255, 255, 0 }; //24 Bit Subnet Mask

//byte myserver[] = { 208, 104, 2, 86 }; // zoomkat web page server IP addre

// ThingSpeak Settings

char thingSpeakAddress[] = "api.thingspeak.com";

String writeAPIKey = "Mwrite_API_key";

const int updateThingSpeakInterval = 25 * 1000;

// Time interval in milliseconds to update ThingSpeak (number of seconds * 1000 = interval)

// Setup the variable

long lastConnectionTime = 0;

boolean lastConnected = false;

int failedCounter = 0;

// Initialize Ethernet Client

EthernetClient client;

#include <DHT.h>

#define DHTPIN 2 // Analog 0 which is the sensor will be place

#define DHTTYPE DHT11 // DHT 11

//#define DHTTYPE DHT22 // DHT 22

DHT dht(DHTPIN, DHTTYPE);

float te, te0;

float has, has0;

int te1, te2;

int has1, has2;

void setup()

{

// Start Serial for debugging on the Serial Monitor

Serial.begin(9600);

// start the Ethernet connection and the server:

Ethernet.begin(mac, ip, gateway, subnet);

// server.begin();

Serial.print("server is at ");

Serial.println(Ethernet.localIP());

dht.begin(); // Humidity Sensor Initialize

// Start Ethernet on Arduino

startEthernet();

}

void loop()

{

// Read value from Analog Input Pin 0

// String analogValue0 = String(analogRead(A0), DEC);

te = dht.readTemperature(); // read temperature

te0 = 10*te; // multiplied with 10

te1 = te0/10; // integer value

te2 = te0 - te1*10; // value after point

if (te2<0) te2=-te2; // if temperature is negative

has = dht.readHumidity();

has0 = 10*has;

has1 = has0/10; // integer value

has2 = has0 - has1*10; // value after point

//String analogValue0 = String(te, DEC);

//String analogValue1 = String(has, DEC);

String analogValue0 = String(te1, DEC);

analogValue0 += ".";

analogValue0 += String(te2, DEC);

String analogValue1 = String(has1, DEC);

analogValue1 += ".";

analogValue1 += String(has2, DEC);

//String analogValue0 = String(24.5, DEC);

//String analogValue1 = String(37, DEC);

// Print Update Response to Serial Monitor

if (client.available())

{

char c = client.read();

Serial.print(c);

}

// Disconnect from ThingSpeak

if (!client.connected() && lastConnected)

{

Serial.println("...disconnected");

Serial.println();

client.stop();

}

// Update ThingSpeak

if(!client.connected() && (millis() - lastConnectionTime > updateThingSpeakInterval))

{

// updateThingSpeak("field1="+analogValue0);

updateThingSpeak("field1="+analogValue0+"&field2="+analogValue1);

}

// Check if Arduino Ethernet needs to be restarted

if (failedCounter > 3 ) {startEthernet();}

lastConnected = client.connected();

}

void updateThingSpeak(String tsData)

{

if (client.connect(thingSpeakAddress, 80))

{

client.print("POST /update HTTP/1.1\n");

client.print("Host: api.thingspeak.com\n");

client.print("Connection: close\n");

client.print("X-THINGSPEAKAPIKEY: "+ writeAPIKey +"\n");

client.print("Content-Type: application/x-www-form-urlencoded\n");

client.print("Content-Length: ");

client.print(tsData.length());

client.print("\n\n");

client.print(tsData);

lastConnectionTime = millis();

if (client.connected())

{

Serial.println("Connecting to ThingSpeak Server");

Serial.println();

failedCounter = 0;

}

else

{

failedCounter++;

Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");

Serial.println();

}

}

else

{

failedCounter++;

Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");

Serial.println();

lastConnectionTime = millis();

}

}

void startEthernet()

{

client.stop();

Serial.println("Connecting to current network please wait...");

Serial.println();

delay(1000);

// Connect to network amd obtain an IP address using DHCP

if (Ethernet.begin(mac) == 0)

{

Serial.println("DHCP Failed, reset the device and try again");

Serial.println();

}

else

{

Serial.println("Connected to network w/d DHCP");

Serial.println();

}

delay(1000); // Delay at 1 Seconds

}