4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ESP8266(ESP-WROOM-02)で、OTA使いながら、UDP(もといOSC)で送受信できるようにするテスト

Last updated at Posted at 2017-12-10

背景

各所でESP8266でUDPを使うソースが出回っているのだけど、
若干バージョンの違いにより使えなかったり、使えたり、みたいなのがあったので、
現行で動くことが確認できたソースを残しておきます。

検証環境

仕様

  • OTA経由でファームを更新できる
  • UDPでデータの送受信ができる

ソース

メインのプログラム

testOTA.ino
/**
 * ESP8266(ESP-WROOM-02)で、
 * OTAでネットワーク越しにファイルをアップデートできる仕組みにしつつ
 * UDPのデータの送受信を可能にするテスト用プログラム
 **/
#include <OSCBundle.h>
#include <OSCData.h>
#include <OSCMessage.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const char* ssid = "xxxxx";
const char* password = "xxxxxx";

void setup() {
  Serial.begin(115200);

  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // switch off all the PWMs during upgrade
  ArduinoOTA.onStart([]() {
    Serial.println("start");
  });
  // do a fancy thing with our board led at end
  ArduinoOTA.onEnd([]() {
    Serial.println("end");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });

  // setup the OTA server
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // setup UDP port
  oscSetup();

  mainSetup();
}

void loop() {
  ArduinoOTA.handle();
  oscLoop();
  mainLoop();
}

Arduino的な処理をする部分のソース

MainOTA.ino
/**
 * 一般的なArduinoで処理するような処理をココに書く
 *
 **/
int ledPin = 13;

int ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 2500;

void mainSetup() {
  // configure dimmers, and OTA server events
  // via http://makers-with-myson.blog.so-net.ne.jp/2017-01-14
  analogWriteRange(1000);
}

void mainLoop() {
  // 一定周期でLEDを点滅
  /*if (millis() - previousMillis >= interval) {
    if (ledState == LOW) {
      ledState = HIGH;
    }
    else {
      ledState = LOW;
    }
    analogWrite(ledPin, ledState == HIGH ? 990 : 0);
    previousMillis = millis();
  }*/
}

UDPの処理をする部分のソース

ESP8266UDP.ino
/**
 * ESP8266でUDP操作するテスト
 *
 **/

// 自分のポート番号
char myIP[16];
#define MY_OSC_PORT 8091

// 相手のIPアドレスとポート番号
const IPAddress TARGET_IP(192, 168, 11, 3);
#define TARGET_PORT 8090

WiFiUDP Udp;
OSCErrorCode error;

/**
 * 初期設定
 */
void oscSetup() {
  Udp.begin(MY_OSC_PORT);

  // 送信テスト(自分のIPアドレスを通知)
  {
    sprintf(myIP, "IP is %d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3] );
    OSCMessage smsg("/ip");
    smsg.add(myIP);
    Udp.beginPacket(TARGET_IP, TARGET_PORT);
    smsg.send(Udp);
    Udp.endPacket();
    smsg.empty();
  }
}

/**
 * dispatchのテスト(/tone宛に来た場合のみ処理)
 */
void dispatchTone(OSCMessage &msg) {
  int ledState = msg.getInt(0);
  if (ledState == 1) {
    analogWrite(13, 990);
  }
  else {
    analogWrite(13, 0);
  }

  // 受信できたよ応答
  OSCMessage _msg("/got_it");
  _msg.add(ledState);
  Udp.beginPacket(TARGET_IP, TARGET_PORT);
  _msg.send(Udp);
  Udp.endPacket();
  _msg.empty();
}

/**
 * 繰り返し処理
 */
void oscLoop() {
  // 受信処理
  // ここがキモ(OSCBundleではなく、OSCMessageにする)
  // rmsg.routeではなく、rmgs.dispatchなとこも重要
  OSCMessage rmsg;
  int size = Udp.parsePacket();
  if (size > 0) {
    while (size--) {
      rmsg.fill(Udp.read());
    }
    if (!rmsg.hasError()) {
      // アドレスごとに処理を振り分ける
      rmsg.dispatch("/tone", dispatchTone, 0);
      //rmsg.dispatch("/led", dispatchLED, 0);
      rmsg.empty();
    }
    else {
      error = rmsg.getError();
      Serial.print("error: ");
      Serial.println(error);
    }
  }
}

補足説明

このプログラムをOTA経由で書き込んで、
同一ネットワークに接続したPCのIPアドレスを192.168.11.3に設定して、
UDPのポートを8090にして待ち受けていると、
ESP-WROOM-02が起動したタイミングでその子のIPアドレスが/ip宛に送られてきます。

なので、そのIPアドレスの8091ポート宛に、

/tone ,i 1000

みたいな感じのOSCを送ってあげると、LEDの明るさが変わるようになります。
(現状では、1000のとこを1とするとLED点灯、それ以外だと消灯)

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?