SeeeduinoXIAOでEnOceanを使ってみる

# やってみたこと
SeeeduinoXIAOを使って、EnOcean通信を試してみました。
SeeeduinoXIAOには、WiFi/Bluetoothなどが付いていないので、いわゆるIoTみたいなことは出来ないのですが、EnOceanのコンタクトセンサをトイレのドアに設置して、リアルな表示灯として使用状況が遠くから見たいといった使い方なら、今回の構成で十分だと思います。
あとは、SeeeduinoXIAO用の拡張ボードを使えば、とてもコンパクトに作れるのでお勧めです（設計のお手伝いをしたのでちょっと宣伝）。

こんな感じです。
センサ部分に磁石を近づけたり遠ざけたりすることで、LEDの色が変わります。

https://twitter.com/i/status/1387322541451010050

#材料
* Seeeduino XIAO

https://www.switch-science.com/catalog/6335/

* Seeeduino XIAO用変換モジュール for Grove

https://www.switch-science.com/catalog/7105/

* EnOcean用送受信モジュール

https://www.switch-science.com/catalog/6776/

* M5Stack用NeoPixel互換LED搭載 六角形ユニット

https://www.switch-science.com/catalog/6058/


# 例）ソースコード
```c:
#include <Adafruit_NeoPixel.h>

#define TEMPID 0xAAAAAAAA // EnOceanモジュールID（適宜読み替えて下さい）
#define SYNC 0x55         // SYNCバイト

#define PIN            5
#define NUMPIXELS      37
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(9600);
  Serial1.begin(57600);

  pixels.begin();
  pixels.setBrightness(32);
}

void loop() {

  /********* EnOcean add *********/
  unsigned char dataReceive = 0; //受信確認フラグ
  unsigned char data = 0;       //データ格納用変数
  unsigned char pos = 0;         //ESPデータ位置
  unsigned long senderID = 0;    //モジュールのID
  unsigned short dataLength = 0; //データ長
  unsigned char optLength = 0;   //オプションデータ長
  unsigned char packettype = 0;  //パケットタイプ
  unsigned char doorStatus = 0;  // ドアの状態
  char buf[8];
  bool isOpen = true;

  // EnOceanからのデータ受信
  while (Serial1.available() > 0)
  {
    //delay(5);
    data = Serial1.read();

    switch (pos)
    {
      case (0):
        if (SYNC == data)
        { // SYNCバイトだったら受信開始
          delay(5);
          pos++;
          dataReceive = 1;
        }
        break;
      case (1):
        dataLength = 0x00FF & data;
        pos++;
        break;
      case (2):
        dataLength = (dataLength << 8) + data;
        pos++;
        break;
      case (3):
        optLength = data;
        pos++;
        break;
      case (4):
        packettype = data;
        pos++;
        break;
      case (5):
        pos++;
        break;
      case (6):
        pos++;
        break;
      case (7):
        senderID = 0x0000FF & data;
        pos++;
        break;
      case (8):
      case (9):
      case (10):
        senderID = (senderID << 8) + data;
        pos++;
        break;
      case (11):
        if (TEMPID == senderID)
        {
          // ドアビット
          doorStatus = data;
        }

        pos++;
        break;
      case (12):
        pos++;
        break;
      case (13):
        pos++;
        break;
      case (14):
        pos++;
        break;
      case (15):
        pos++;
        break;
      default:
        pos++;
        break;
    }
    // デバッグ用のシリアルモニタ出力
    Serial.print(data, HEX);
    Serial.print("  ");
  }

  // データ受信時の処理
  if (dataReceive == 1)
  {
    if (TEMPID == senderID)
    {
      // ドア状態の判定
      if (doorStatus == 0x08)
      {
        Serial.println("Open");
        pixels.clear();
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(128, 0, 0));
          pixels.show();
        }
      }
      else if (doorStatus == 0x09)
      {
        Serial.println("Close");
        pixels.clear();
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(0, 0, 128));
          pixels.show();
        }
      }
    }
  }
  delay(100);
}
```

EnOcean用送受信モジュールのサンプルは、こちらを参考にしています。

https://github.com/yukima77/EnOceanModule

#注意事項
EnOcean用送受信用モジュールは、[GroveSystem](https://wiki.seeedstudio.com/Grove_System/)のTX/RXが入れ子になっているので、ケーブル上でクロスさせて下さい。SoftwareSerialを使用する場合は、ポートを指定できるのでそのままで使用できるのですが（言い訳）。