廢話不多說,開始介紹ESP8266應用
會有人問我,ESP8266 有這麼多塊板子,有甚麼推薦與差異嗎??
其實Farmer也不太懂硬體的部分,就是傻傻地買了,不過大家可以去露天看看並且比較一下CP,我是有固定與一家購買,在這就不打廣告了,如果有想知道去哪買再偷偷問我啊~
對了,如果家中沒有 USB轉 TTL、USB轉 Serial等名稱的轉換器,請記得順便購買。
Farmer 購買 ESP 8266 ESP-01 這塊,如下圖,
參考圖:google,如有問題,馬上刪除,謝謝。 |
[ 一、韌體 更新/退回 版本 & AT測試 Realterm ]
剛送來的時候 胞率 115200,所以硬體的韌體要刷一下啦!當然不是每個人的應用都需要刷韌體,請自行參考應用。在刷韌體中有遇到狀況,朋友也遇到很多狀況,在這裡提醒一下大家,再刷韌體的時候,
電源電流!電源電流!電源電流!
一定要穩定3.3V,電流也一定要穩,請外接電源,以免刷韌體失敗,
而AT測試,可使用 Realterm 做測試,
以上這些可參考兩位神人文章:
【技術教學】打造Wifi遙控車(之一):使用 ESP8266進行 Wifi無線通訊
http://lets-make-games.blogspot.tw/2015/04/wifi-esp8266-wifi.html小狐狸事務所 - ESP8266 更新韌體
http://yhhuang1966.blogspot.tw/2015/08/esp8266.html
(Farmer很懶,有巨人在,就參考巨人吧 :D )
[ 二、 ARDUINO CODE]
#include <SoftwareSerial.h>
#define DEBUG true
/*
Farmer使用mega版,所以RXTX使用Serial1(D19、D18)
如果使用uno版可以修改下方註解,因為預設RXTX是電腦燒入時會應用,
所以使用的話,燒入記得要拔除,但怕麻煩,可以改變腳位使用,即可避免燒入衝突。
*/
HardwareSerial& esp8266=Serial1;
//SoftwareSerial esp8266(10,11);
void setup()
{
Serial.begin(9600);
esp8266.begin(9600); // esp韌體的胞率,若為115200,請記得修改
// 使用13LED先做測試
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
sendCommand("AT+RST\r\n",2000,DEBUG); // reset module
sendCommand("AT+CWMODE=1\r\n",1000,DEBUG); // configure as access point
/***************************************************************/
/*SSID、PASSWD請輸入您要連接的AP(如家中數據機或是手機分享網路),這邊一定要修改*/
sendCommand("AT+CWJAP=\"SSID\",\"PASSWD\"\r\n",3000,DEBUG);
delay(10000);
sendCommand("AT+CIFSR\r\n",1000,DEBUG); // get ip address
sendCommand("AT+CIPMUX=1\r\n",1000,DEBUG); // configure for multiple connections
sendCommand("AT+CIPSERVER=1,80\r\n",1000,DEBUG); // turn on server on port 80
Serial.println("Server Ready");
}
void loop()
{
if(esp8266.available()) // 檢查ESP是否有傳送
{
if(esp8266.find("+IPD,"))
{
delay(1000); // wait for the serial buffer to fill up (read all the serial data)
// get the connection id so that we can then disconnect
int connectionId = esp8266.read()-48; // ASCII 48 十進制 為 0
esp8266.find("pin="); // advance cursor to "pin="
int pinNumber = (esp8266.read()-48);
int secondNumber = (esp8266.read()-48);
if(secondNumber>=0 && secondNumber<=9)
{
pinNumber*=10;
pinNumber +=secondNumber;
}
digitalWrite(pinNumber, !digitalRead(pinNumber)); // toggle pin
// build string that is send back to device that is requesting pin toggle
String content;
content = "Pin ";
content += pinNumber;
content += " is ";
if(digitalRead(pinNumber))
{
content += "ON";
}
else
{
content += "OFF";
}
sendHTTPResponse(connectionId,content);
// make close command
String closeCommand = "AT+CIPCLOSE=";
closeCommand+=connectionId; // append connection id
closeCommand+="\r\n";
sendCommand(closeCommand,1000,DEBUG); // close connection
}
}
}
/*
* Name: sendData
* Description: Function used to send data to ESP8266.
* Params: command - the data/command to send; timeout - the time to wait for a response; debug - print to Serial window?(true = yes, false = no)
* Returns: The response from the esp8266 (if there is a reponse)
*/
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
int dataSize = command.length();
char data[dataSize];
command.toCharArray(data,dataSize);
esp8266.write(data,dataSize); // send the read character to the esp8266
if(debug)
{
Serial.println("\r\n====== HTTP Response From Arduino ======");
Serial.write(data,dataSize);
Serial.println("\r\n========================================");
}
long int time = millis();
while( (time+timeout) > millis())
{
while(esp8266.available())
{
// The esp has data so display its output to the serial window
char c = esp8266.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.print(response);
}
return response;
}
/*
* Name: sendHTTPResponse
* Description: Function that sends HTTP 200, HTML UTF-8 response
*/
void sendHTTPResponse(int connectionId, String content)
{
// build HTTP response
String httpResponse;
String httpHeader;
// HTTP Header
httpHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n";
httpHeader += "Content-Length: ";
httpHeader += content.length();
httpHeader += "\r\n";
httpHeader +="Connection: close\r\n\r\n";
httpResponse = httpHeader + content + " "; // There is a bug in this code: the last character of "content" is not sent, I cheated by adding this extra space
sendCIPData(connectionId,httpResponse);
}
/*
* Name: sendCIPDATA
* Description: sends a CIPSEND=<connectionId>,<data> command
*
*/
void sendCIPData(int connectionId, String data)
{
String cipSend = "AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend +=data.length();
cipSend +="\r\n";
sendCommand(cipSend,1000,DEBUG);
sendData(data,1000,DEBUG);
}
/*
* Name: sendCommand
* Description: Function used to send data to ESP8266.
* Params: command - the data/command to send; timeout - the time to wait for a response; debug - print to Serial window?(true = yes, false = no)
* Returns: The response from the esp8266 (if there is a reponse)
*/
String sendCommand(String command, const int timeout, boolean debug)
{
String response = "";
esp8266.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(esp8266.available())
{
// The esp has data so display its output to the serial window
char c = esp8266.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.print(response);
}
return response;
}
[ 三、 ANDROID STUDIO CODE]
Manifest File
這裡主要是追加這行,這樣才可以開啟網路權限使用
<uses-permission android:name="android.permission.INTERNET" />
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.roy.arduinowifitext">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.roy.arduinowifitext.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="IP Address:"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="e.g. 192.168.0.10"
android:text="192.168.43.176"
android:id="@+id/editTextIPAddress"
android:layout_marginTop="25dp"
android:layout_below="@+id/textView"
android:layout_alignParentEnd="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Port Number:"
android:id="@+id/textView2"
android:layout_below="@+id/editTextIPAddress"
android:layout_centerHorizontal="true"
android:layout_marginTop="23dp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:hint="e.g. 80"
android:text="80"
android:id="@+id/editTextPortNumber"
android:layout_below="@+id/textView2"
android:layout_alignParentEnd="true"
android:layout_marginTop="22dp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Pin 13"
android:id="@+id/buttonPin13"
android:layout_marginBottom="48dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
Main
package com.example.roy.arduinowifitext;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
public class MainActivity extends AppCompatActivity {
public final static String PREF_IP = "PREF_IP_ADDRESS";
public final static String PREF_PORT = "PREF_PORT_NUMBER";
// declare buttons and text inputs
private Button buttonPin13;
private EditText editTextIPAddress, editTextPortNumber;
// shared preferences objects used to save the IP address and port so that the user doesn't have to
// type them next time he/she opens the app.
SharedPreferences.Editor editor;
SharedPreferences sharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sharedPreferences = getSharedPreferences("HTTP_HELPER_PREFS",Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
// assign buttons
buttonPin13 = (Button)findViewById(R.id.buttonPin13);
// assign text inputs
editTextIPAddress = (EditText)findViewById(R.id.editTextIPAddress);
editTextPortNumber = (EditText)findViewById(R.id.editTextPortNumber);
// set button listener (this class)
buttonPin13.setOnClickListener(btnOnOffClickListener);
// get the IP address and port number from the last time the user used the app,
// put an empty string "" is this is the first time.
editTextIPAddress.setText(sharedPreferences.getString(PREF_IP,""));
editTextPortNumber.setText(sharedPreferences.getString(PREF_PORT,""));
}
View.OnClickListener btnOnOffClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
// get the pin number
String parameterValue = "";
// get the ip address
String ipAddress = editTextIPAddress.getText().toString().trim();
// get the port number
String portNumber = editTextPortNumber.getText().toString().trim();
// save the IP address and port for the next time the app is used
editor.putString(PREF_IP, ipAddress); // set the ip address value to save
editor.putString(PREF_PORT, portNumber); // set the port number to save
editor.commit(); // save the IP and PORT
// get the pin number from the button that was clicked
if (view.getId() == buttonPin13.getId()) {
parameterValue = "13";
}
// execute HTTP request
if (ipAddress.length() > 0 && portNumber.length() > 0) {
new HttpRequestAsyncTask(
view.getContext(), parameterValue, ipAddress, portNumber, "pin"
).execute();
}
}
};
/**
* Description: Send an HTTP Get request to a specified ip address and port.
* Also send a parameter "parameterName" with the value of "parameterValue".
* @param parameterValue the pin number to toggle
* @param ipAddress the ip address to send the request to
* @param portNumber the port number of the ip address
* @param parameterName
* @return The ip address' reply text, or an ERROR message is it fails to receive one
*/
public String sendRequest(String parameterValue, String ipAddress, String portNumber, String parameterName) {
String serverResponse = "ERROR";
try {
HttpClient httpclient = new DefaultHttpClient(); // create an HTTP client
// define the URL e.g. http://myIpaddress:myport/?pin=13 (to toggle pin 13 for example)
URI website = new URI("http://"+ipAddress+":"+portNumber+"/?"+parameterName+"="+parameterValue);
HttpGet getRequest = new HttpGet(); // create an HTTP GET object
getRequest.setURI(website); // set the URL of the GET request
HttpResponse response = httpclient.execute(getRequest); // execute the request
// get the ip address server's reply
InputStream content = null;
content = response.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(
content
));
serverResponse = in.readLine();
// Close the connection
content.close();
} catch (ClientProtocolException e) {
// HTTP error
serverResponse = e.getMessage();
e.printStackTrace();
} catch (IOException e) {
// IO error
serverResponse = e.getMessage();
e.printStackTrace();
} catch (URISyntaxException e) {
// URL syntax error
serverResponse = e.getMessage();
e.printStackTrace();
}
// return the server's reply/response text
return serverResponse;
}
/**
* An AsyncTask is needed to execute HTTP requests in the background so that they do not
* block the user interface.
*/
private class HttpRequestAsyncTask extends AsyncTask<Void, Void, Void> {
// declare variables needed
private String requestReply,ipAddress, portNumber;
private Context context;
private AlertDialog alertDialog;
private String parameter;
private String parameterValue;
/**
* Description: The asyncTask class constructor. Assigns the values used in its other methods.
* @param context the application context, needed to create the dialog
* @param parameterValue the pin number to toggle
* @param ipAddress the ip address to send the request to
* @param portNumber the port number of the ip address
*/
public HttpRequestAsyncTask(Context context, String parameterValue, String ipAddress, String portNumber, String parameter)
{
this.context = context;
alertDialog = new AlertDialog.Builder(this.context)
.setTitle("HTTP Response From IP Address:")
.setCancelable(true)
.create();
this.ipAddress = ipAddress;
this.parameterValue = parameterValue;
this.portNumber = portNumber;
this.parameter = parameter;
}
/**
* Name: doInBackground
* Description: Sends the request to the ip address
* @param voids
* @return
*/
@Override
protected Void doInBackground(Void... voids) {
alertDialog.setMessage("Data sent, waiting for reply from server...");
if(!alertDialog.isShowing())
{
alertDialog.show();
}
requestReply = sendRequest(parameterValue,ipAddress,portNumber, parameter);
return null;
}
/**
* Name: onPostExecute
* Description: This function is executed after the HTTP request returns from the ip address.
* The function sets the dialog's message with the reply text from the server and display the dialog
* if it's not displayed already (in case it was closed by accident);
* @param aVoid void parameter
*/
@Override
protected void onPostExecute(Void aVoid) {
alertDialog.setMessage(requestReply);
if(!alertDialog.isShowing())
{
alertDialog.show(); // show dialog
}
}
/**
* Name: onPreExecute
* Description: This function is executed before the HTTP request is sent to ip address.
* The function will set the dialog's message and display the dialog.
*/
@Override
protected void onPreExecute() {
alertDialog.setMessage("Sending data to server, please wait...");
if(!alertDialog.isShowing())
{
alertDialog.show();
}
}
}
}
這邊可能會發生警告狀況,因為沒有帶入lib,所以Org.apache皆無法使用,聽說在android studio 6 就將 org.apache.http.legacy 換至 HTTP URL CONNECTION。
但Farmer還是使用org.apache.http.legacy,且做法跟上圖有所差異,我是直接去X:\Android\sdk\platforms\android-23\optional,可以利用電腦的搜尋 "org.apache.http.legacy.jar"
或是,在這裡直接下載
如果以上都沒有問題,各位就可以試試看,是否可以使用
以下為Farmer的code file
以上皆參考
資料測試改寫,如有任何版權問題,請告知,立即刪除,謝謝
沒有留言:
張貼留言