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 << "°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() << "°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() << "°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() << "°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
}