Lecture 11/21– WiFi
FC Tien, YP Liu
Dept. IE&M, Taipei Tech
WiFi vs Bluetooth
IP位址與NAT
實體 IP (Public IP):代表你的 IP 可以公開在網際網路中,屬於一個實體的身份,可以用來連入連出,但 是數量有限。
虛擬 IP (Private IP):這部份的 IP 一開始是規劃供架設區域網路使用,可以重覆使用這部份的 IP,但是 由於是給區域網路使用,此部份的 IP 封包是出不了路由器的,也就是不能上網際網路。
虛擬 IP 的範圍:
A 級網路:10.0.0.0 – 10.255.255.255 B 級網路:172.16.0.0 – 172.31.255.255 C 級網路:192.168.0.0 – 192.168.255.255
NAT(Network Address Translation),也就是 IP 分享器的功能,把虛擬 IP 對應到路由器 的實體 IP 埠,也就是一個虛擬 IP 可對應到 路由器的一個埠,以路由器的實體 IP 對外通 訊
WiFi Chip ESP8266
ESP8266是深圳樂鑫資訊(信息)科技公司開發的Wi-Fi晶片,只有32個 接腳,而深圳安信可科技用這顆晶片開發出多種小型模組。
參考資料:
https://www.ai-thinker.com/product/esp8266
安信可 ESP 8266 模組類型
型號 ESP-01S ESP-01M ESP-07S ESP-12F ESP-12S
封裝 DIP-8 SMD-18 SMD-16 SMD-22 SMD-16
尺寸(mm) 24.7*14.4*11
.0 18*18*2.8 17.0*16.0*3.
0 24.0*16.0*3.
0 24.0*16.0*3.
0
板層 2 4 4 4 4
Flash 8Mbit 8Mbit 32Mbit 32Mbit 32Mbit
認證 - FCC/CE FCC/CE FCC/CE/IC FCC/CE/SRR
C
天線 PCB天線 PCB天線 IPEX PCB天線 PCB天線
指示燈 GPIO2 - - GPIO2 GPIO2
可用IO 2 11 9 9 9
ESP-01S 接線方式
P10 P11
GND
+3.3V
P11 Tx
P10 Rx
AT指令測試 1/2
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
void loop() { // run over and over if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
} }
已經改為9600
AT指令測試 2/2
4. AT+UART=9600,8,1,0,0 設置連線速度為9600bps 5. AT+CWMODE=1 設定為Station模式
6. AT+CWLAP 掃描附近的AP
WiFiEsp Library
https://github.com/bportaluri/WiFiEsp
Example
1. _ESP8266_SPP 序列埠監控視窗傳送資料到模組
2. _ESP8266_ConnectWPA 連線有加密的WiFi
3. _ESP8266_ScanNetworks 掃描附近的無線網路
4. _ESP8266_UdpNTPClient Network Time Protocol (時間與頻率國家標準實驗室)
5. _ESP8266_WebServer 網頁伺服器,網頁顯示類比輸入A0數值
6. _ESP8266_WebServerAP 具有網路AP功能的網頁伺服器,網頁顯示類比輸入A0數值
7. _ESP8266_WebServerLed 網頁伺服器,控制LED亮暗
WEMOS D1 vs. Arduino UNO
https://wiki.wemos.cc/products:d1:d1
An Arduino UNO Compatible wifi board based on ESP8266EX
11 digital input/output pins, all pins have interrupt/pwm/I2C/one- wire supported(except for D0)
1 analog input(3.2V max input)
Micro USB connection
Power jack, 9-24V power input.
Compatible with Arduino
WEMOS D1 開發環境建立
安裝 ARDUINO IDE --> 已經安裝則免
安裝 D1 CH340G USB to UART driver
在Arduino IDE中安裝 D1 板子
https://www.arduino.cc/
https://wiki.wemos.cc/_media/file:ch341ser_win.zip
http://arduino.esp8266.com/stable/package_esp8266com_index.json
安裝 D1 CH340G USB to UART driver
在Arduino IDE中安裝 D1 板子
在Arduino IDE中安裝 D1 板子
esp8266
在Arduino IDE中安裝 D1 板子
設定D1參數
Blink 測試
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output }
// the loop function runs over and over again forever void loop() {
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because
// it is acive low on the ESP-01) delay(1000); // Wait for a second
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH
delay(2000); // Wait for two seconds (to demonstrate the active low LED) }
D1_Blink
D1 規格 注意事項
Microcontroller ESP-8266EX
Operating Voltage 3.3V
Digital I/O Pins 11
Analog Input Pins 1(Max input: 3.2V)
Clock Speed 80MHz/160MHz
Flash 4M bytes
Length 68.6mm
Width 53.4mm
Weight 25g
Technical specs
感測器 - 光敏電阻
光敏電阻(Photoresistor),簡稱光電阻,又名光導 管。它的電阻和光線的強弱有直接的關係,隨著入射 光強度越強則電阻值下降。
它被廣泛的應用在低成本 的光感元件,比如說攝影 用的測光計、火災及煙霧 警報器、防盜警報器、工 業上控制電路中或者是燈 具的自動開關上。
光敏電阻元件圖與實體圖
光敏電阻實驗
電阻值 10k Ω WEMOS D1
3.3V A0
GND
int sensorPin = 0;
int value = 0;
void setup() {
Serial.begin(9600);
}
void loop(){
value = analogRead(sensorPin);
Serial.print("Read:");
Serial.println(value, DEC);
delay(500);
}
光敏電阻實驗
D1_PhotoResistor
ThingSpeak
IoT 雲端資料庫 https://thingspeak.com/
申請 ThingSpeak 帳號
申請 ThingSpeak 帳號
建立 Channels
將資料傳送至ThingSpeak
update?key=[THINGSPEAK_KEY]&field1=[data 1]&filed2=[data 2]...
http://api.thingspeak.com/update?key=69R40VH2WEKSBCC6&field1=25
問題! D1連那個網路?
使用手機連接 WEMOS D1設定 http://10.0.1.1
直接指定連線方式
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500);
Serial.print(".");
}Serial.println("");
Serial.println("WiFi connected.");
WEMOS D1 連接 WiFi
安裝 WiFiManager Library
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino //needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager;
//reset saved settings
//wifiManager.resetSettings();
//set custom ip for portal
wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name //here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration wifiManager.autoConnect("myD1AP");
//or use this for auto generated name ESP + ChipID //wifiManager.autoConnect();
//if you get here you have connected to the WiFi Serial.println("connected... :)");
}
void loop() {
// put your main code here, to run repeatedly:
}
WiFi Manager 程式
D1_WIFI_Manager
ThingSpeak 傳遞亮度資料
void UpdateThingSpeak() {
// 設定 ESP8266 作為 Client 端 WiFiClient client;
if( !client.connect( "api.thingspeak.com", 80 ) ) {
Serial.println( "connection failed" );
return;
} else {
// 準備上傳到 ThingSpeak IoT Server 的資料 // 已經預先設定好 ThingSpeak IoT Channel 的欄位 // field1:光強度
String getStr = GET + "&field1=" + String((int)lightness) +
" HTTP/1.1\r\n";;
client.print( getStr );
client.print( "Host: api.thingspeak.com\n" );
client.print( "Connection: close\r\n\r\n" );
delay(10);
client.stop();
} }
傳送亮度資料到ThingSpeak
D1_WIFI_Thingspeak_photoresistor
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
int Sensor=A0;
String GET = "GET /update?key=XXXXXXXXXXXXXXXX";
int lightness;
WiFiClient client;
void setup() {
Serial.begin(115200);
//WiFiManager
WiFiManager wifiManager;
wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
wifiManager.autoConnect("myD1AP");
Serial.println("WiFi connected");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
void loop() {
lightness = analogRead(Sensor);
//傳送資料
Serial.print( "lightness: " );
Serial.println( lightness );
UpdateThingSpeak(); //更新 ThingSpeak 資料 // 每隔20Sec傳送一次資料,不可太短
delay( 20000 );
}
安裝 ThingSpeak Library
thingspeak
使用 ThingSpeak Library
#include <ThingSpeak.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
int Sensor=A0;
int lightness;
WiFiClient client;
unsigned long myChannelNumber = 204774;
const char * myWriteAPIKey = "69R40VH2WEKSBCC6";
void setup() {
Serial.begin(115200);
//WiFiManager
WiFiManager wifiManager;
wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
wifiManager.autoConnect("myD1AP");
Serial.println("WiFi connected");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
ThingSpeak.begin(client);
}
void loop() {
lightness = analogRead(Sensor);
ThingSpeak.writeField(myChannelNumber, 1, lightness, myWriteAPIKey);
Serial.print("Lightness: ");
Serial.println(lightness);
delay( 20000 );
}
D1_WIFI_Thingspeak_photoresistor_post
WiFi連線控制LED 1/2
#include <ESP8266WiFi.h>
const char* ssid = “YPLIU_AP”;
const char* password = “123456789”;
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(10);
pinMode(BUILTIN_LED, OUTPUT);
digitalWrite(BUILTIN_LED, HIGH);
// Connect to WiFi network Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.print("Use this URL : ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop() {
// Check if a client has connected WiFiClient client = server.available();
if (!client) { return;
}
// Wait until the client sends some data Serial.println("new client");
while(!client.available()){
delay(1);
}
D1_WebServer_LED
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();
// Match the request int value = LOW;
if (request.indexOf("/LED=ON") != -1) { digitalWrite(BUILTIN_LED, LOW);
value = LOW;
}
if (request.indexOf("/LED=OFF") != -1){
digitalWrite(BUILTIN_LED, HIGH);
value = HIGH;
}
// Return the response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(""); // do not forget this one client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.print("Led pin is now: ");
if(value == LOW) { client.print("On");
} else {
client.print("Off");
}
client.println("<br><br>");
client.println("Click <a href=\"/LED=ON\">here</a> turn the LED on pin 4 ON<br>");
client.println("Click <a href=\"/LED=OFF\">here</a> turn the LED on pin 4 OFF<br>");
client.println("</html>");
delay(1);
Serial.println("Client disconnected");
Serial.println("");
}
WiFi連線控制LED 2/2
AJAX 網頁
D1_WIFI_Manager_WebServer_photoresistor
AJAX即「Asynchronous JavaScript and XML」(非同步的JavaScript與XML技術)
https://zh.wikipedia.org/wiki/AJAX
ajax.htm
<html>
<head>
<meta charset = "UTF-8">
<title>Arduino Web Server</title>
<script type = "text/javascript">
function send2arduino(){
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest();
} else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
element=document.getElementById("light");
if (element.innerHTML.match("Turn on")) {
element.innerHTML="Turn off";
xmlhttp.open("GET","?on",true);
} else
{
element.innerHTML="Turn on";
xmlhttp.open("GET","?off",true);
}
xmlhttp.send();
}
function getBrightness(){
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("brightness").innerHTML=xmlhttp.responseText;
} }
xmlhttp.open("GET","?getBrightness",true);
xmlhttp.send();
}
window.setInterval(getBrightness,5000);
</script>
</head>
<body>
<div align = "center">
<h1>Arduino Web Server</h1>
<div>brightness:</div>
<div id = "brightness">??</div>
<button id = "light" type = "button">Turn on</button>
<button type = "button">About</button>
</div>
</body>
</html>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
int Light=2;
int Sensor=A0;
WiFiServer server(80);
WiFiClient client;
String readString= "" ; void setup() {
Serial.begin(115200);
pinMode(Light,OUTPUT);
digitalWrite(Light, HIGH);
//WiFiManager
WiFiManager wifiManager;
wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
wifiManager.autoConnect("myD1AP");
Serial.println("");
Serial.println("WiFi connected");
server.begin();
Serial.println("Server started");
Serial.print("Server IP: ");
Serial.println(WiFi.localIP());
}
void loop() {
// 監聽連入的客戶端
client = server.available();
if (client) {
Serial.println( "new client" );
boolean currentLineIsBlank = false ; while (client.connected()) {
if (client.available()) { char c = client.read();
readString += c;
if (c == '\n' ) {
Serial.println(readString);
//檢查收到的信息中是否有”on”,有則開燈 if (readString.indexOf( "?on" ) >0) {
digitalWrite(Light, LOW);
Serial.println( "Led On" );
break ; }
//檢查收到的信息中是否有”off”,有則關燈 if (readString.indexOf( "?off" ) >0) {
digitalWrite(Light, HIGH);
Serial.println( "Led Off" );
break ; }
//檢查收到的信息中是否有”getBrightness”,有則讀取光敏模擬值,並返回給瀏覽器 if (readString.indexOf( "?getBrightness" ) >0) {
client.println(analogRead(Sensor));
break ; }
//發送HTML文本 SendHTML();
break ; } }
}
delay(100);
client.stop();
Serial.println( "client disonnected" );
readString= "" ; }
}
D1 Arduino.ino 1/2
// 用於輸出HTML文本的函數 void SendHTML()
{
client.println( "HTTP/1.1 200 OK" );
client.println( "Content-Type: text/html" );
client.println( "Connection: close" );
client.println();
client.println( "<!DOCTYPE HTML>" );
client.println( "<html><head><meta charset=\"UTF-8\"><title>Arduino Web Server</title><script type=\"text/javascript\">" );
client.println( "function send2arduino(){var xmlhttp;if (window.XMLHttpRequest)xmlhttp=new XMLHttpRequest();else xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\");element=document.getElementById(\"light\");if (element.innerHTML.match(\"Turn
on\")){element.innerHTML=\"Turn off\"; xmlhttp.open(\"GET\",\"?on\",true );}else{ element.innerHTML=\"Turn on\";xmlhttp.open(\"GET\",\"?off\",true); }xmlhttp.send();}" );
client.println( "function getBrightness(){var xmlhttp;if (window.XMLHttpRequest)xmlhttp=new XMLHttpRequest();else xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\");xmlhttp.onreadystatechange=function(){if (xmlhttp.readyState==4 &&
xmlhttp.status==200)document.getElementById(\"brightness\").innerHTML=xmlhttp.responseText;};xmlhttp.open(\"GET\",\"?getBrightness\" ,true);
xmlhttp.send();}window.setInterval(getBrightness,1000);</script>" );
client.println( "</head><body><div align=\"center\"><h1>Arduino Web Server</h1><div>brightness:</div><div id=\"brightness\" >" );
client.println(analogRead(Sensor));
client.println( "</div><button id=\"light\" type=\"button\" onclick=\"send2arduino()\">Turn on</button><button type=\"button\"
onclick=\"alert('Arduino Web Server')\">About</button></div></body></html>" );
}