レーザー距離センサとESP32でバーチャル嫁を制御したい

# 注意
急ぎ気味でこの記事を書きました。
投げやりな感じでかつ、どこか間違っている点などがあると思われるので少しずつ修正出来たらなと思います。

# 早速ですが...(毎年恒例の経緯)
12月。
4月から作り始めていたプロジェクト(大人向けなのでここでは出せません...)もほぼ休止状態になり、埃が被ってしまっている始末。
言い訳すると、時間が無い(大嘘)ということだったのです!!
どうにかしなけれればならないと思い、今回はほぼ休止状態のプロジェクトを久しぶりに動かそうと言う企画です。
ただ、アレなのはさすがに出せないので記事用に最適化しました。

今回はUnityちゃんの静止<=>歩く<=>走るを手の距離を測定して制御したいと思います。

通信経路は、距離センサ=>ESP32(UDP経由)=>Unityとなります。

急ぎ気味にこの記事を書いているので所々(結構)省略しています。申し訳ありません。

# 使用したもの
- ESP32 (マイコンボード)
- VL53L0X (距離センサ)
- ブレッドボード
- その他配線用の材料

# 配線
ESP32,ブレッドボード側
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349992/23facdf4-cc79-38d1-6e62-8a315c6a3e54.png)

VL53L0X (距離センサ)側
左側のピンより、VCC(白)GND(黒)SCL(灰)SDA(橙)となります。上記画像を参考に配線すれば動くかと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349992/ac36fdc7-0f6f-9096-7c0a-22ab6817b2c3.png)

# ソースコード
ESP32側

```cpp:dst_udp.ino
#include <Wire.h>
#include <VL53L0X.h>
#include<WiFi.h>
#include <WiFiUDP.h>
int mill;
int led = 2;
//wifi
const char ssid[] = "Test_SSD"; //SSID
const char pass[] = "Test_Password"; //パスワード
IPAddress ip(192, 168, 1, 25);// IP固定
IPAddress gateway(192,168, 1, 1);//ゲートウェイ
IPAddress subnet(255, 255, 255, 0);//サブネット
IPAddress DNS(192, 168, 1, 1);//DNS
IPAddress ipadr;
static WiFiUDP wifiUdp; 
static const char *kRemoteIpadr = "192.168.1.6"; //PCorスマホのローカルIP
static const int kRmoteUdpPort = 30000; //送信先のポート
//

VL53L0X sensor;

static void WiFi_setup()
{
  Serial.println("Running WiFi");
  static const int kLocalPort = 7000;  //自身のポート
  WiFi.config(ip, gateway, subnet, DNS);
  WiFi.begin(ssid, pass);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("WiFi Connect Waiting...");
  }
  Serial.println("WiFi Connected! UDP Start!");
  wifiUdp.begin(kLocalPort);
}
static void Serial_setup()
{
  Serial.begin(115200);
  Serial.println(""); // to separate line  
}
void setup()
{
  Serial_setup();
  WiFi_setup();
  Wire.begin();
  pinMode(led,OUTPUT);
  sensor.init();
  sensor.setTimeout(40);
  sensor.setSignalRateLimit(0.001);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
  sensor.startContinuous();
}

float back_cal = 0;
void loop()
{
  wifiUdp.beginPacket(kRemoteIpadr, kRmoteUdpPort);
  wifiUdp.write(sensor.readRangeContinuousMillimeters());
  wifiUdp.endPacket();
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
  float test_cal = 0.90 * back_cal + (1-0.90) * sensor.readRangeContinuousMillimeters();
  back_cal = test_cal;
  Serial.println((int)test_cal);
  if(sensor.readRangeContinuousMillimeters() < 80){
    digitalWrite(led,HIGH);
    }
  else{
    digitalWrite(led,LOW);
   }
}
```
Unity側

```c#:udp_get.cs
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System;

public class udp_get : MonoBehaviour
{
    //anim
    private Animator animator;
    //
    int LOCA_LPORT = 30000;
    public UdpClient udp;
    Thread thread;
    public float udp_data;
    public float udp_data_conv = 0;
    //
    void Start()
    {
        udp = new UdpClient(LOCA_LPORT);
        thread = new Thread(new ThreadStart(ThreadMethod));
        thread.Start();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        if(udp_data_conv > 80)
        {
            //静止
            animator.SetBool("idl", true);
            animator.SetBool("walk", false);
            animator.SetBool("run", false);

        }
        else
        {
            //動く
            if(udp_data_conv < 20)
            {
                //歩く
                animator.SetBool("idl", false);
                animator.SetBool("walk", false);
                animator.SetBool("run", true);
            }
            else
            {
                //走る
                animator.SetBool("idl", false);
                animator.SetBool("walk", true);
                animator.SetBool("run", false);
            }
            
        }
    }

    void OnApplicationQuit()
    {
        thread.Abort();
    }

    public void ThreadMethod()
    {
        byte[] data;
        while (true)
        {
            IPEndPoint remoteEP = null;
            data = udp.Receive(ref remoteEP);
            //Debug.Log(data[0]);
            udp_data = data[0];
            udp_data_conv = (float)Math.Truncate(udp_data);
        }
        
    }
}
```
Animator Controller側
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349992/df6bb66f-9bbd-5c9d-fcec-4455f478d8f6.png)

Unity側では上記ソースを使い、ESP32から送られてきた測定値をUnity側で受信してUnityちゃんのアニメーションに反映させています。
今回は時間が無いので気が向いたら説明を書きます。

# 動作結果
ハードウェア側
一定の距離まで近づけると青色のLEDが点灯します。
![001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349992/acb8a9bb-94d9-1310-67fe-4597bc0f39b8.gif)
Unity側
距離の値によって動作が変化している事が確認できました。
しかし、精度が良くない事と、試した方法が悪い所為か安定しません。
![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349992/82768e62-cfef-471e-9158-0cb693d3b50d.gif)

# 終わりに
今まで類を見ない速度でこの記事を書いてしまい、全く参考にならない記事となっているかもしれません。
大変、申し訳なく思っております。時間が空いた際には追記と言う形で記事を完成させていこうかと思います。
では、この辺で。

#参考にした記事
ESP32側参考にした所
@7of9様の記事:[ESP8266 > UDPで送信できた / esp8266_151219_udpSender](https://qiita.com/7of9/items/a61999a914ae02673b8d)
# ライセンス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349992/9746d86e-4673-9b6f-577c-4232f6089b5a.png)
この作品は[ユニティちゃんライセンス条項](https://unity-chan.com/contents/license_jp/)の元に提供されています