2019年8月12日月曜日

ESP-WROOM-02(ESP8266)で,9軸センサーBMX055から取得した値をパソコン(mac)にOSCフォーマットで送信する.

前の記事で,9軸センサーの値をUDPでテキスト形式でパソコンに送信できたので,いよいよESP-WROOM-02でBMX055から取得した9軸データをOSCフォーマットでパソコン(mac)に送信することにします.

Arduino用のOSCライブラリーはここの物を使いました.「Clone or Download」ボタンをクリックしてzipファイルをダウンロードし,Arduinoの「Sketch」メニュー→「Include Library」→「Add .ZIP Library...」を選択してzipファイルを指定し,「Choose」ボタンをクリックしてインストールします.再度「Sketch」メニュー→「Include Library」を選択すると,「Contributed libraries」の下の方に「OSC」が表示されます.

ESP-WROOM-02のプログラムを以下のように書き換えます.

//================================================================//
//  AE-BMX055             ESP8266                            //
//    3V3                    +3.3V(1)                                  //
//    GND                    GND(17)                                  //
//    SDA                    IO4(12)                              //
//    SCL                    IO5(16)                              //
//                                                                //
//   (JP6,JP4,JP5はショートした状態)                              //
//   http://akizukidenshi.com/catalog/g/gK-13010/                 //
//   -> 3.3Vで使うのでJP6はショートしない
//================================================================//

// 2019/8/12
// send accel,gyro,compass data to the destination port
// by text data
// add OSC library from https://github.com/CNMAT/OSC

#include 
#include 
#include 
#include 
#include  // OSC library https://github.com/CNMAT/OSC
#include  // sprintf()

WiFiUDP UDP;

IPAddress HOSTIP(192, 168, 3, 4); // IP address of the destination
const int remoteUdpPort = 30000;  // port number of the destination

IPAddress myIP(192, 168, 3, 100);  // this address is needed for WiFi config
const int localUdpPort = 31000;   // local port number

// since mac is connected to the internet through iPhone,
// iPhone is the WiFi router.
const char *ssid = "iPhone7PlusBlack";
const char *password = "qatacygd60y8u";

// BMX055 加速度センサのI2Cアドレス  
#define Addr_Accl 0x19  // (JP1,JP2,JP3 = Openの時)
// BMX055 ジャイロセンサのI2Cアドレス
#define Addr_Gyro 0x69  // (JP1,JP2,JP3 = Openの時)
// BMX055 磁気センサのI2Cアドレス
#define Addr_Mag 0x13   // (JP1,JP2,JP3 = Openの時)

// センサーの値を保存するグローバル関数
float xAccl = 0.00;
float yAccl = 0.00;
float zAccl = 0.00;
float xGyro = 0.00;
float yGyro = 0.00;
float zGyro = 0.00;
short int   xMag  = 0;
short int   yMag  = 0;
short int   zMag  = 0;

void connectWiFi() {
  Serial.println("WiFi setup start");
  WiFi.begin(ssid, password);
  WiFi.config(myIP, WiFi.gatewayIP(), WiFi.subnetMask());
  Serial.println("WiFi setup done");
  Serial.println("start_connect");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("CONNECTED!");
}

void reconnectWiFi() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.disconnect();
    Serial.println("disconnected! reconnect WiFi.");
    connectWiFi();
  }
}

void setup()
{
  // Wire(Arduino-I2C)の初期化
  Wire.begin();
  // デバック用シリアル通信は9600bps
  Serial.begin(9600);
  //BMX055 初期化
  BMX055_Init();
  delay(300);
  //WiFi初期化
  WiFi.mode(WIFI_STA);
  UDP.begin(localUdpPort);
  connectWiFi();
}

void loop()
{
  char buf[128];
  Serial.println("--------------------------------------"); 

  //BMX055 加速度の読み取り
  BMX055_Accl();
  sprintf(buf, "/ZIGSIM/hh3-zig/accel: (%f, %f, %f)",
          xAccl, yAccl, zAccl);
  Serial.println(buf);
  OSCMessage msgAccel("/ZIGSIM/hh3-zig/accel");
  msgAccel.add(xAccl).add(yAccl).add(zAccl);
  UDP.beginPacket(HOSTIP, remoteUdpPort);
  msgAccel.send(UDP);
  UDP.endPacket();
  msgAccel.empty();  
  delay(100);
  reconnectWiFi();

  //BMX055 ジャイロの読み取り
  BMX055_Gyro();
  sprintf(buf, "/ZIGSIM/hh3-zig/gyro: (%f, %f, %f)",
          xGyro, yGyro, zGyro);
  Serial.println(buf);
  OSCMessage msgGyro("/ZIGSIM/hh3-zig/gyro");
  msgGyro.add(xGyro).add(yGyro).add(zGyro);
  UDP.beginPacket(HOSTIP, remoteUdpPort);
  msgGyro.send(UDP);
  UDP.endPacket();
  msgGyro.empty();
  delay(100);
  reconnectWiFi();
  
  //BMX055 磁気の読み取り
  BMX055_Mag();
  sprintf(buf, "/ZIGSIM/hh3-zig/mag: (%d, %d, %d)",
          xMag, yMag, zMag);
  Serial.println(buf);
  OSCMessage msgMag("/ZIGSIM/hh3-zig/mag");
  msgMag.add(xMag).add(yMag).add(zMag);
  UDP.beginPacket(HOSTIP, remoteUdpPort);
  msgMag.send(UDP);
  UDP.endPacket();
  msgMag.empty();
  delay(100);
  reconnectWiFi();

  delay(700);
}

//=====================================================================================//
void BMX055_Init()
{
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x0F); // Select PMU_Range register
  Wire.write(0x03);   // Range = +/- 2g
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x10);  // Select PMU_BW register
  Wire.write(0x08);  // Bandwidth = 7.81 Hz
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x11);  // Select PMU_LPW register
  Wire.write(0x00);  // Normal mode, Sleep duration = 0.5ms
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x0F);  // Select Range register
  Wire.write(0x04);  // Full scale = +/- 125 degree/s
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x10);  // Select Bandwidth register
  Wire.write(0x07);  // ODR = 100 Hz
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x11);  // Select LPM1 register
  Wire.write(0x00);  // Normal mode, Sleep duration = 2ms
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4B);  // Select Mag register
  Wire.write(0x83);  // Soft reset
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4B);  // Select Mag register
  Wire.write(0x01);  // Soft reset
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4C);  // Select Mag register
  Wire.write(0x00);  // Normal Mode, ODR = 10 Hz
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4E);  // Select Mag register
  Wire.write(0x84);  // X, Y, Z-Axis enabled
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x51);  // Select Mag register
  Wire.write(0x04);  // No. of Repetitions for X-Y Axis = 9
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x52);  // Select Mag register
  Wire.write(0x16);  // No. of Repetitions for Z-Axis = 15
  Wire.endTransmission();
}
//=====================================================================================//
void BMX055_Accl()
{
  unsigned char data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(Addr_Accl);
    Wire.write((2 + i));// Select data register
    Wire.endTransmission();
    Wire.requestFrom(Addr_Accl, 1);// Request 1 byte of data
    // Read 6 bytes of data
    // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data to 12-bits
  xAccl = ((data[1] * 256) + (data[0] & 0xF0)) / 16;
  if (xAccl > 2047)  xAccl -= 4096;
  yAccl = ((data[3] * 256) + (data[2] & 0xF0)) / 16;
  if (yAccl > 2047)  yAccl -= 4096;
  zAccl = ((data[5] * 256) + (data[4] & 0xF0)) / 16;
  if (zAccl > 2047)  zAccl -= 4096;
  xAccl = xAccl * 0.0098; // renge +-2g
  yAccl = yAccl * 0.0098; // renge +-2g
  zAccl = zAccl * 0.0098; // renge +-2g
}
//=====================================================================================//
void BMX055_Gyro()
{
  unsigned char data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(Addr_Gyro);
    Wire.write((2 + i));    // Select data register
    Wire.endTransmission();
    Wire.requestFrom(Addr_Gyro, 1);    // Request 1 byte of data
    // Read 6 bytes of data
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xGyro = (data[1] * 256) + data[0];
  if (xGyro > 32767)  xGyro -= 65536;
  yGyro = (data[3] * 256) + data[2];
  if (yGyro > 32767)  yGyro -= 65536;
  zGyro = (data[5] * 256) + data[4];
  if (zGyro > 32767)  zGyro -= 65536;

  xGyro = xGyro * 0.0038; //  Full scale = +/- 125 degree/s
  yGyro = yGyro * 0.0038; //  Full scale = +/- 125 degree/s
  zGyro = zGyro * 0.0038; //  Full scale = +/- 125 degree/s
}
//=====================================================================================//
void BMX055_Mag()
{
  unsigned short int data[8];
  for (int i = 0; i < 8; i++)
  {
    Wire.beginTransmission(Addr_Mag);
    Wire.write((0x42 + i));    // Select data register
    Wire.endTransmission();
    Wire.requestFrom(Addr_Mag, 1);    // Request 1 byte of data
    // Read 6 bytes of data
    // xMag lsb, xMag msb, yMag lsb, yMag msb, zMag lsb, zMag msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xMag = ((data[1] <<8 data="">>3));
  if (xMag > 4095)  xMag -= 8192;
  yMag = ((data[3] <<8 data="">>3));
  if (yMag > 4095)  yMag -= 8192;
  zMag = ((data[5] <<8 data="">>3));
  if (zMag > 16383)  zMag -= 32768;
}


OSCデータを受け取って表示するパソコン側のPythonプログラムは以下のとおりです.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Python 3.7.3 on macOS 10.15 Catalina Beta
# 2019/8/7
# receive OSC data by UDP

import argparse
from socket import *
from pythonosc import dispatcher
from pythonosc import osc_server

def handle_zigsim_osc_message(addr, *args):
    try:
        print("{0}: {1}".format(addr, args))
    except ValueError:
        print("ValueError occrurred")

def start_OSC_server(ip_addr, port_num):
    print("starting on address {}, port {}".format(ip_addr, port_num))

    # OSC dispatcher
    dispatch = dispatcher.Dispatcher()
    dispatch.map("/ZIGSIM/*", handle_zigsim_osc_message )

    server = osc_server.ThreadingOSCUDPServer(
        (ip_addr, port_num), dispatch)
    print("Serving on {}".format(server.server_address))
    server.serve_forever()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", default="127.0.0.1",
                        help="IP address to listen on")
    parser.add_argument("--port", type=int, default=30000,
                        help="port to listen on")
    args = parser.parse_args()
    start_OSC_server(args.ip, args.port)


動作環境は以下のとおりです.

  • パソコン側のIPアドレス:192.168.3.4
  • OSCデータを受け取るUDPポート番号:30000
  • 送信側ESP-WROOM-02のUUID:hh3_zig
パソコン側のターミナルソフトで以下のようにPythonプログラムを動かします.

% ./UDPserver2.py --ip 192.168.3.4 --port 30000


ESP-WROOM-02にプログラムを書き込んでリセットボタンを押すと,パソコンで以下のようにデータが受信できていることが確認できました.

/ZIGSIM/hh3-zig/accel: (-0.11760000139474869, 0.2547999918460846, 9.790200233459473)
/ZIGSIM/hh3-zig/gyro: (-0.3571999967098236, -0.20520000159740448, -0.04179999977350235)
/ZIGSIM/hh3-zig/mag: (2049, -762, -237)
/ZIGSIM/hh3-zig/accel: (-0.09799999743700027, 0.24500000476837158, 9.829400062561035)
/ZIGSIM/hh3-zig/gyro: (-0.47119998931884766, -0.2013999968767166, 0.11779999732971191)
/ZIGSIM/hh3-zig/mag: (1822, -762, -237)


0 件のコメント:

コメントを投稿