はじめに
この記事では,TOPPERS/R2CAによるWifi通信の方法について説明します.タスクは1個のみのシングルタスク版を説明します.
TOPPERS/R2CAの説明とサンプルの動作方法は次の記事を見て下さい.
変更履歴
- 2016/10/23
- ファイルの変更
- 2016/5/05
- アクセスポイントの設定を別ファイルとした.
- 2016/3/31
- ESP8266のドライバの見直しによりサンプルプログラムを変更.
- シングルタスク版について説明
ハードウエア
この記事で説明しているハードウェア以外にESP8266が必要です.
ESP8266のボードは多くの種類が出ています.基本的にはどれでも良いですが,動作確認したものは次の通りです.
-
スイッチサイエンス ESP-WROOM-02
- ブレッドボードを使って接続しました.
-
- ESP8266をXbee互換の基盤にしたものです.
- Arduino ワイヤレスプロトシールドや,NCES CAN シールドを使うと,簡単にArduinoと接続可能です.
- ロゴから分かるようにTOPPERS/R2CA用に作成しました.
#サンプルのビルド
R2CAのパッケージの\examples\WifiEchoにあるサンプルを実行します.このサンプルはポート80に入力された文字列をそのまま返すエコーサーバーです.
まずexamples_gdef.hを開き,アクセスポイントの情報をSSIDとPASSWORDに設定します.
#define STA_SSID ""
#define STA_PASSWORD ""
次にr2ca_app.hを開き,シングルタスク版にするためマクロをコメントアウトします.
//#define MULTI_ECHO_SERVER
ビルドは同じフォルダにあるdo_make.bat をダブルクリックすると開始されます.ファイルが色々作成されますが,rca.elfが出来るとビルド成功です.
#実行
実行はdo_run.batをダブルクリックするとダウンロードが開始され,実行されます.Teratermには次のように表示されます.アクセスポイントに接続して,IPアドレスをDHCPから取得します.取得したアドレスはコンソールに出力されます.下記の例では,192.168.1.27となっています.
PCから上記のIPのポート80に接続して適当な文字を入力してエンターを押すと入力した文字がそのまま送られて来ます.終了するには,Ctrl-Q入力してエンターを押します.
#プログラム
##初期化処理
初期化処理ではアクセスポイントに接続してIPを取得しています.また,ポート番号80番でTCPサーバーを実行します.#define WMODE_STATION の定義をコメントアウトすると,アクセスポイントとして動作します.
void setup()
{
int ret;
Serial.println("Echo Server : Start!");
ret = WiFi.begin(Serial5, 115200);
if(ret == 1) {
Serial.print("Cannot communicate with ESP8266.");
while(1);
} else if(ret == 2) {
Serial.println("FW Version mismatch.");
Serial.print("FW Version:");
Serial.println(WiFi.getVersion().c_str());
Serial.print("Supported FW Version:");
Serial.println(ESP8266_SUPPORT_VERSION);
while(1);
} else {
Serial.print("begin ok\r\n");
}
Serial.print("FW Version:");
Serial.println(WiFi.getVersion().c_str());
#ifdef WMODE_STATION
if (WiFi.setOprToStation()) {
Serial.print("to station ok\r\n");
} else {
Serial.print("to station err\r\n");
}
if (wifi.joinAP(STA_SSID, STA_PASSWORD)) {
Serial.print("Join AP success\r\n");
Serial.print("IP: ");
Serial.println(WiFi.getLocalIP().c_str());
} else {
Serial.print("Join AP failure\r\n");
}
#else /* !WMODE_STATION */
if (WiFi.setOprToSoftAP()) {
Serial.print("to softap ok\r\n");
} else {
Serial.print("to softap err\r\n");
}
if(WiFi.setSoftAPParam(AP_SSID, AP_PASSWORD, 7, 0)){
Serial.print("Set SoftAP success\r\n");
Serial.print("IP: ");
Serial.println(WiFi.getLocalIP().c_str());
}
else {
Serial.print("Set SoftAP failure\r\n");
}
#endif /* WMODE_STATION */
if (WiFi.enableMUX()) {
Serial.print("multiple ok\r\n");
} else {
Serial.print("multiple err\r\n");
}
if (WiFi.startTCPServer(80)) {
Serial.print("start tcp server ok\r\n");
} else {
Serial.print("start tcp server err\r\n");
}
if (WiFi.setTCPServerTimeout(60)) {
Serial.print("set tcp server timout 60 seconds\r\n");
} else {
Serial.print("set tcp server timout err\r\n");
}
Serial.print("setup end\r\n");
setup_done = true;
}
##エコーサーバー処理
まず,コネクションが変化したかをチェックします.コネクションは最大5個あります.このプログラムではコネクション0に対してデータを受け取り,エコーバックを行います.コネクション0に接続があれば,mux_idに0を設定します.
次に,コネクションが確立しているかをチェックして,80番のポートからデータを受け取ります.有効なデータを受け取った場合は,コンソールに出力した後,データをエコーバックしています.また,受信したデータをチェックして,Crtl-Qを受け取った場合は,終了処理も行います.
uint8_t mux_id_ptn;
uint8_t mux_id = MUX_NULL;
uint8_t task1_mux_id = MUX_NULL;
void loop()
{
uint8_t buffer[128] = {0};
uint8_t pre_mux_id_ptn;
uint32_t len;
uint32_t i;
delay(1);
/* Check Connection Status */
pre_mux_id_ptn = mux_id_ptn;
if(!Wifi.getMuxCStatus(&mux_id_ptn)) {
Serial.println("getMuxCStatus(&mux_id_ptn) : Error!");
}
else {
if (pre_mux_id_ptn != mux_id_ptn) {
Serial.print("Connection Status changed! : 0x");
Serial.println(mux_id_ptn, HEX);
if (mux_id_ptn & 0x01) {
mux_id = 0;
}
if (mux_id_ptn & 0x02) {
task1_mux_id = 1;
}
}
}
if (mux_id == MUX_NULL) {
return;
}
if (!WiFi.isConnected(mux_id)) {
Serial.print("Echo Server : Port is closed: ");
Serial.println(mux_id);
mux_id = MUX_NULL;
return;
}
if((len = WiFi.recv(mux_id, buffer, sizeof(buffer))) == 0) {
return;
}
/* Recived Data */
for(i = 0; i < len; i++) {
/* If Recive Ctrl-q(17) */
if(buffer[i] == 17) {
Serial.print("Echo Server : Close port : ");
Serial.println(mux_id);
WiFi.releaseTCP(mux_id);
mux_id = MUX_NULL;
return;
}
}
Serial.print("Echo Server : Recive Data from mux : ");
Serial.println(mux_id);
Serial.print("Echo Server : Recive len : ");
Serial.println(len);
Serial.print("Echo Server : Recive Data : ");
Serial.println((char*)buffer);
if(!WiFi.send(mux_id, buffer, len)) {
Serial.println("Echo Server : send(mux_id, cmd) : Error!");
}
}
##API
ESP8266のライブラリはITEADLIB_Arduino_WeeESP8266をベースとしていますが,API幾つか増やしています.
int begin(HardwareSerial &uart, uint32_t baud = 115200);
bool kick(void);
bool restart(void);
String getVersion(void);
bool setOprToStation(void);
bool setOprToSoftAP(void);
bool setOprToStationSoftAP(void);
String getAPList(void);
bool joinAP(String ssid, String pwd);
bool leaveAP(void);
bool setSoftAPParam(String ssid, String pwd, uint8_t chl = 7, uint8_t ecn = 4);
String getJoinedDeviceIP(void);
String getIPStatus(void);
String getLocalIP(void);
bool enableMUX(void);
bool disableMUX(void);
bool createTCP(String addr, uint32_t port);
bool releaseTCP(void);
bool registerUDP(String addr, uint32_t port);
bool unregisterUDP(void);
bool createTCP(uint8_t mux_id, String addr, uint32_t port);
bool releaseTCP(uint8_t mux_id);
bool registerUDP(uint8_t mux_id, String addr, uint32_t port);
bool unregisterUDP(uint8_t mux_id);
bool setTCPServerTimeout(uint32_t timeout = 180);
bool startTCPServer(uint32_t port = 333);
bool stopTCPServer(void);
bool startServer(uint32_t port = 333);
bool stopServer(void);
bool send(const uint8_t *buffer, uint32_t len);
bool send(uint8_t mux_id, const uint8_t *buffer, uint32_t len);
bool send(String &str);
bool send(uint8_t mux_id, String &str);
uint32_t recv(uint8_t *buffer, uint32_t buffer_size, uint32_t timeout = 1000);
uint32_t recv(uint8_t mux_id, uint8_t *buffer, uint32_t buffer_size, uint32_t timeout = 1000);
uint32_t recv(uint8_t *coming_mux_id, uint8_t *buffer, uint32_t buffer_size, uint32_t timeout = 1000);
bool isDataAvailable(uint8_t mux_id);
bool isDataAvailable(void);
bool isConnected(void);
bool isConnected(uint8_t mux_id);
bool getMuxCStatus(uint8_t *mux_id_ptn);
おわりに
ESP8266を使うと安価に簡単にネットに接続できます.TOPPERS/R2CAを使うと,マルチタスクが使えるので,サーバーで接続待ちになりながら,センサー等の処理を同時に実行出来ます.