macsbug

Just another WordPress.com site

Control the ESP8266 in iPad

with 3 comments

iPad で ESP8266 をコントロールする iPadアプリを作りました。      2016.07.28
電子工作で iPad や iPhone との連携が容易に出来る様になります。
開発は iOSデバイス上で動作する統合開発環境 Pythonista 3 を使用します。


 

機能と動作:
1:iPad   :押したスイッチの信号をESP8266へ送る。
2:ESP8266:iPadからの信号でLEDの状態を把握しLEDをオンかオフにする。
3:ESP8266:LEDのオンオフ状態をiPadへフィードバックする。
4:iPad   :LEDがオンならスイッチを橙色、オフなら灰色にする。
5:iPad   :All Clear スイッチで全てのLEDをオフにし、2,3,4 を行う。
6:iPad   :Raed スイッチで ESP8266 LED の状態を読み込み 表示する。


 

iPhone, iPad の iOSアプリに Pythonista 3 (パイソニスタ)開発言語があります。

Pythonista 3:
_ iPad 上で編集し動作も可能。
_ Apple に開発費を支払う必要がない。
_ Pythonista 3 上や サイトに 詳細な Document がある。
_ Python の多くの記事やサンプルが使用できる。
_ サンプルが多数有り、UI 編集機能 の道具もあります。(以下の画像)
:
ユーザーインターフェース( UI )編集機能:
_ パネルデザイン:以下の様に UI 編集機能を使用しパネルのデザインを行います。
_ 部品の色や名前、アクション名(例:sw1)を設定し命令と接続できるようにします。


 

準備:
1. iPad:Pythonista 3 をインストール。(1200円)
_ パネルデザイン:UI 編集機能を使用し パネルのデザインを行います。
2. ESP8266 + LED:GPIO端子にLEDを接続。
3. WiFi 環境
4. iPad:UDP_test 又は UDP Tool+:UDP通信の確認。必要に応じで使用します。
_ UDP通信の物は 幾つかありますので無料のアプリを試してみてください。
5. Pythonista 3 の使用方法を練習してください。


 

通信方法と信号の流れ:
UDP通信( socket )で行い 家庭内のネットを使用します。
例:iPad IP = 192.168.100.22 , ESP8266 IP = 192.168.100.47
iPad 送信 → IP,PORT → ESP8266 : iPadからESP8266へ信号を送信する。
_ 例:iPad(192.168.100.22, 送信port=7000) →
_      → ESP8266(192.168.100.47, 受信port=9000)
iPad 受信 ← IP,PORT ← ESP8266 : ESP8266の信号をiPadで受信する。
_ 例:iPad(192.168.100.22, 受信port=9000) ←
_      ← ESP8266(192.168.100.47, 送信port=7000)


 

UDP通信の基礎

iPad UDP送信
例:”1″ を送信する。受信側のESP8266 の IP は ‘192.168.100.47’, Port=7000

import socket

HOST, PORT = '192.168.100.47', 7000
tx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tx.sendto(bytes('1', 'utf-8'), (HOST, PORT))

iPad UDP受信
例:変数 d1 へ受信データーを入れる。受信の長さは 12 とした。Port=9000

import socket

rx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
rx.bind(('', 9000))
d1 = str(rx.recv(12), 'utf-8')

メモ:UDP通信が それぞれ たったの4行で出来ます。
メモ:SOCK_DGRAM:UDPに使用する。21.21.4.2. socketserver.UDPServer Example
メモ:Pythonista 3 の編集は文字間のスペースや行間のスペースが必要です。


 

UDP通信の確認:
以下のiOSアプリでUDP通信の確認ができます。必要に応じて実施してみてください。
iPad:UDP_test アプリ(無料)による確認:
_ ESP8266への送信やESP8266からの受信の確認ができます。
_ このアプリが無ければ別のUDPアプリを探してください。

例:ESP8266 へ BME280 センサーを接続しUDP通信を行う。
上が iPadの送信:Sendボタンで “1” を IP=192.168.100.47,Port=7000 に送信。
下が iPadの受信:”1″ → ESP8266 → iPad(192.168.100.22,Port=9000) で受信。
_ ”1″ に対する受信内容は:t/1/ /
_ センサー の受信内容は:d/30.91/52.25/1007.13


Pythonista リスト:

import ui
import socket
import time

def sw1(s):tx.sendto(bytes('1', 'utf-8'), (HOST, PORT))
	
def sw2(s):tx.sendto(bytes('2', 'utf-8'), (HOST, PORT))
	
def sw3(s):tx.sendto(bytes('3', 'utf-8'), (HOST, PORT))
	
def sw4(s):tx.sendto(bytes('4', 'utf-8'), (HOST, PORT))

def sw5(s):tx.sendto(bytes('5', 'utf-8'), (HOST, PORT))
	
def sw6(s):tx.sendto(bytes('6', 'utf-8'), (HOST, PORT))
	
def clr(s):tx.sendto(bytes('0', 'utf-8'), (HOST, PORT))

def rea(s):tx.sendto(bytes('7', 'utf-8'), (HOST, PORT))
		
v = ui.load_view('cont_pnl')
v.background_color = '#d3dad7'
v.present('sheet')
HOST, PORT = '192.168.100.47', 7000
rx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(1)
rx.bind(('', 9000))
tx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
on = '#ff6161'
of = '#5d5d5d'

while True:
	d1 = str(rx.recv(12), 'utf-8')
	
	if d1.find('1H') > -1:v['button1'].background_color = on
	
	if d1.find('1L') > -1:v['button1'].background_color = of
	
	if d1.find('2H') > -1:v['button2'].background_color = on

	if d1.find('2L') > -1:v['button2'].background_color = of
	
	if d1.find('3H') > -1:v['button3'].background_color = on
	
	if d1.find('3L') > -1:v['button3'].background_color = of
	
	if d1.find('4H') > -1:v['button4'].background_color = on
	
	if d1.find('4L') > -1:v['button4'].background_color = of
	
	if d1.find('5H') > -1:v['button5'].background_color = on
	
	if d1.find('5L') > -1:v['button5'].background_color = of
	
	if d1.find('6H') > -1:v['button6'].background_color = on
	
	if d1.find('6L') > -1:v['button6'].background_color = of
		
	d1 = ''

メモ:v.present(‘sheet’) : UIをデザインした大きさで表示。
メモ:v.present(”)   : UIを全画面の大きさで表示。
メモ:def sw1(s):tx.sendto(bytes(‘1’, ‘utf-8’), (HOST, PORT)):sw1を押したら”1″を送信する。
メモ:v = ui.load_view(‘cont_pnl’):UI cont_pnl を読み込み v と表現する。
メモ;d1 = str(rx.recv(12), ‘utf-8’):ESP8266のデーターを受信し d1 へ入れる。
メモ:if d1.find(‘1H’) > -1:v[‘button1’]:受信に”1H”があるならSW 1を橙色(on)にする。


 

ESP8266スケッチ:

 
// ESP8266 UDP transceiver and Receiver         // 2016.07.28 macsbug
// http://4009.jp/post/2016-04-25-esp-wroom-02/ 
#include <ESP8266WiFi.h>                        //
#include <WiFiUDP.h>                            //

WiFiUDP UDP;                                    //
char buff[32];                                  //
const char ssid[]="xxxx";                       // wifi ssid
const char pass[]="xxxx";                       // wifi password
const char iPhoneIP[]   = "192.168.100.22";     // iPhone iP
const int  iPhoneTxPort = 7000;                 // UDP Tx port
const int  iPhoneRxPort = 9000;                 // UDP Rx port
String all;                                     //
 
void setup()                                    //
  Serial.begin(115200);Serial.println();        //
  pinMode(D0, OUTPUT); digitalWrite(D0, LOW);   // 16, LED off
  pinMode(D1, OUTPUT); digitalWrite(D1, LOW);   //  5, LED off 
  pinMode(D2, OUTPUT); digitalWrite(D2, LOW);   //  4, LED off 
  pinMode(D3, OUTPUT); digitalWrite(D3, LOW);   //  0, LED off 
  pinMode(D4, OUTPUT); digitalWrite(D4, LOW);   //  2, LED off 
  pinMode(D5, OUTPUT); digitalWrite(D5, LOW);   // 14, LED off
  WiFi.softAP(ssid, pass);                      // WiFi connect
  UDP.begin(iPhoneTxPort);                      // iPhoneTxPort
}                                               //
 
void loop() {                                   //
  ESP.wdtDisable();                             //
  int rx = UDP.parsePacket();                   // packet size
  if (rx){                                      // recive
    int len = UDP.read(buff, rx);               // rx lengs
    if (len > 0){                               // rx action
      buff[len] = '\0';                         // Termination char
      int c = buff[0];                          // head haracter
      if ( c == '0' ){ all_clear();}            // 0, all off
      if ( c == '1' ){ sw(16, 1);}              // 1, LED 1 on/off
      if ( c == '2' ){ sw( 5, 2);}              // 2, LED 2 on/off
      if ( c == '3' ){ sw( 4, 3);}              // 3, LED 3 on/off
      if ( c == '4' ){ sw( 0, 4);}              // 4, LED 4 on/off
      if ( c == '5' ){ sw( 2, 5);}              // 5, LED 5 on/off
      if ( c == '6' ){ sw(14, 6);}              // 6, LED 6 on/off
      if ( c == '7' ){ allread();}              // 7, all read
      c = '9';                                  //
    }                                           //
  }                                             //
}                                               //

void sw(int gpio, int n){                       // gpio feed back
  if ( digitalRead(gpio) == 0 ){                // gpio ck = LOW
       digitalWrite(gpio, HIGH);                // SET LED ON 
       UDP.beginPacket(iPhoneIP, iPhoneRxPort); // UDP
       UDP.print( String(n) + "H");             // return LED ON 
       UDP.endPacket();                         // UDP
  } else {                                      // gpio ck = HI
       digitalWrite(gpio, LOW );                // SET LED OFF
       UDP.beginPacket(iPhoneIP, iPhoneRxPort); // UDP
       UDP.print( String(n) + "L");             // return LED OFF 
       UDP.endPacket();                         // UDP
  }                                             //
}                                               //

void all_clear(){                               // led all cler
  ESP.wdtDisable();                             //
  all = "";                                     //
  digitalWrite(D0, LOW); io(16, 1);             // 16 = LOW
  digitalWrite(D1, LOW); io( 5, 2);             //  5 = LOW 
  digitalWrite(D2, LOW); io( 4, 3);             //  4 = LOW 
  digitalWrite(D3, LOW); io( 0, 4);             //  0 = LOW 
  digitalWrite(D4, LOW); io( 2, 5);             //  2 = LOW 
  digitalWrite(D5, LOW); io(14, 6);             // 14 = LOW
  UDP.beginPacket(iPhoneIP, iPhoneRxPort);      // UDP feed back
  UDP.print( all );                             // 1L2L3L4L5L6L
  UDP.endPacket();                              // UDP
}

void allread(){                                 //
  ESP.wdtDisable();                             //
  all = "";                                     //
  io(16, 1);                                    // 16 = read
  io( 5, 2);                                    //  5 = read
  io( 4, 3);                                    //  4 = read 
  io( 0, 4);                                    //  0 = read
  io( 2, 5);                                    //  2 = read 
  io(14, 6);                                    // 14 = read
  UDP.beginPacket(iPhoneIP, iPhoneRxPort);      // UDP feed back
  UDP.print( all );                             // 1x2x3x4x5x6x
  UDP.endPacket();                              // UDP
}                                               //

参照:
Pythonista 3:A Full Python IDE for iOS
Pythonista 3:Pythonista Documentation
ひとりぶろぐ:iOS上で動作する革命的ものづくり環境「Pythonista 3」の魅力をとくと語る
りんごがでている:PythonistaのためのJulia100問100答
hanaken_Nirvana:~Pythonistaより愛をこめて贈る入門者のためのTips①~
hanaken_Nirvana:~Pythonistaより愛をこめて贈る入門者のためのTips②~
scipy-lectures.org:1.4. Matplotlib: plotting
matplotlib.org:matplotlib


感想:
🍎 iPad や iPhone を電子工作のディスプレーやコントローラーに使用できると
_ 素晴らしい事が出来る。そこで 基本的なUDP通信ソフトを作り動きました。
_ これにより だれでも開発ができる様になれば良いかなと思っています。
🍎 経過:Python言語が全く解らない状態で始め1行の理解に1日かかる状態。
_ それでもなんとか動作する様になると楽しくなってきますね。
_ 理解すれば動くという事。進めて行くと この言語の凄さに驚く!
_ なんと数行で数値計算をグラフやウエブの内容を表示できる事に驚く!
_ グラフではヒストグラムを1行でできる事にも驚嘆する。
_ さらに Python 言語の記事やサンプルは多数有り 先人の知識を使用できる。

🍎 Pythonista 3 : ひとりぶろぐ氏の記事、、
_ 「iOS上で動作する革命的ものづくり環境「Pythonista 3」の魅力をとくと語る
_ で触発されました。是非 お読みください。感謝!
🍎 UDP通信:7of9氏の「UDPで送信できた」を参照させて頂きました。感謝!

🍎 Pythonista 3 編集機能:指やパネルキーで出来る様になっている。
_ キー入力は予想を立てた文字が表示され押すだけで命令を一気に入力できる。
_ 色の数値を設定するにはカーソルを起き 指で押すとカラーパネルが出て来て
_ 色を選択してInstallすると命令に追加される。、、いやはや驚きの連続!

🍎 自作例:ESP8266からの温度,湿度,気圧を iPad で受信し数値で表示できた
_ 事とグラフに表示できました。工夫すれば ThingSpeek等のクラウドを使用
_ した方法は不要になるかも知れません。
_ その後に今回のコントローラーを作り今回の記事にしました。
🍎 フィードバック機能:電子工作で重要な機能はフィードバックが出来る事。
_ それが出来ると自動制御が可能になると言う訳ですね。
🍎 課題:家庭内のネットを使用せず iPad と ESP8266 間で直接通信するには
_ どうような方法でおこなうのか?


 

Written by macsbug

7月 28, 2016 @ 8:42 am

カテゴリー: ESP8266, Pythonista

コメント / トラックバック3件

Subscribe to comments with RSS.

  1. pythonista3というのは知りませんでした。興味を引かれました。
    iPad mini4を持っていますが、UnityソフトをiPadに入れていない理由としてAppleに登録しないといけないためでした。
    pythonista3を入れれば登録なくてもソフト作成できるのですね。
    今かかえている複数の課題を解決して落ち着いた頃にpythonistaを試してみたいと思います。

    > 課題:家庭内のネットを使用せず iPad と ESP8266 間で直接通信するには
    > _ どうような方法でおこなうのか?
    僕が知っている直接通信としてはESP8266がWiFiの親となる「APモード」があります。
    http://qiita.com/7of9/items/c74b7291e27dec09a830
    と記事内でリンクしているQiita記事が参考になるかもしれません。

    APモードでの固定IP割当て方法も教えていただいています。
    http://qiita.com/7of9/items/30508ea8c62f7ee027ba

    7of9

    7月 31, 2016 at 4:53 am

    • 7of9さん、こんにちわ。
      以前 XcodeでiPad用の32bit Digital Analyzer を作り少しは動きましたが
      メモリーとクラッシュの問題で挫折しました。私には Xcodeは難しすぎたようです。
      Pythonista3 ならなんとか出来そうなのでトライしています。

      直接通信のアドバイスをありがとうございます。
      まさに その2つの記事の内容です。すでに試されていたのに驚いています。
      これが目的ですので今の課題ができたら取り組んでみたいと思っています。
      そして その次は 時系列グラフを作りたいと思っています。
      そうしましたら なんと既に 7of9さんの記事に「unity > 時系列グラフの描画 > timeGraph > UDPで “時-分,データ” を受信してグラフ化、、」があるのを発見!。素晴らしいですね。
      これも参考にさせて頂きますね。

      macsbug

      8月 1, 2016 at 9:59 am

      • macsbugさん、こんにちは。
        XcodeでDigital Analyzerというのを実装されたのですね。
        僕はXcodeはさっぱりです。
        メモリやクラッシュの問題というのはデバッグが難しそうですね。

        時系列グラフの記事ですが、線の描画とグラフ軸テキストの描画以降、作業をしていませんでした。
        Unityの座標計算が自分には不明であったのと、他に始めたことに気をとられて、そのままとなっています。
        一応、UDP通信した数値は[-1,1]の範囲でグラフ描画できますので、その点までで参考になりましたら、と思います。

        githubのコードですが、一部そのままでは動かない部分がありました。
        以下の記事で補足しておきました。
        http://qiita.com/7of9/items/642b308f604452a78c5e
        もしUnityで試される場合は、上記の修正が必要となります。

        7of9

        8月 2, 2016 at 6:11 am


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。