ESP-Nowを使い、ESP8266からESP8266へ連続データを送る実験。

#はじめに
先日行ったESP-Nowの実験では、通信が非常に不安定で、かなりの確率でパケット脱落する結果になってしまいました。原因は良く分らなかったのですが、別の情報を参考に、違うやり方で試してみたところ、あっさりと上手くいったので投稿しておきます。[HarringayMakerSpace/ESP-Now](https://github.com/HarringayMakerSpace/ESP-Now)。　前はどこがまずかったのかは、後日、調べてみたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266665/a2394b4f-953f-429d-1b04-5ca831ca7726.png)

#結論
いろいろ試行錯誤の結果、安定した動作を得る事が出来、5msec程度の間隔でコントローラー側からパケットを送出しても、ほぼ脱落なく受信できるようになりました（100％かどうかは未確認です）。スレーブ側に、APモードは使わずCOMBOモードを使ってある例を参考にしました。また、スレーブ側ではpeerを設定せず、来たものは拒まず・・・というスタンスで受信していますので、本格的な利用には、このままではリスクがあると思います。

#スレーブ側
受け取った値を、PWMでサーボモータの値に変換して、回してみましたが、特に問題なくスムーズに動作しました（目に見える確認用として試しただけです）。

```c:
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}

struct __attribute__((packed)) SENSOR_DATA {
  float temperature;
  int val;
} sensorData;

uint8_t bs[sizeof(sensorData)];
int heartBeat;
boolean dbg = false;

void printMacAddress(uint8_t* macaddr) {
  Serial.print("{");
  for (int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(macaddr[i], HEX);
    if (i < 5) Serial.print(',');
  }
  Serial.print("} ");
}

void recv_cb(uint8_t *mac, uint8_t *data, uint8_t len) {
  digitalWrite(13,dbg);
  memcpy(&sensorData, data, sizeof(sensorData));
  Serial.print(sensorData.val);
  //Serial.print(",");
  //Serial.print(sensorData.temperature);
  //Serial.print(" from ");
  //printMacAddress(mac);
  Serial.println("");
  int x = map(sensorData.val, 0,100,100,200);
  analogWrite(12,x);
  heartBeat = millis();
  dbg = !dbg;
}

void setup() {
  Serial.begin(74880);
  Serial.println();
  pinMode(13,OUTPUT);//debug
  pinMode(12,OUTPUT); //PWM1
  pinMode(15,OUTPUT); //PWM2
  analogWriteFreq(100);//100Hz (slowest)
  analogWriteRange(1000);
  Serial.print("This node STA mac: ");
  Serial.println(WiFi.macAddress());
  if (esp_now_init() != 0) {
    Serial.println("*** ESP_Now init failed");
    ESP.restart();
  }
  esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
  esp_now_register_recv_cb(recv_cb);
}

void loop() {
  if (millis() - heartBeat > 30000) {
    Serial.println("Waiting for ESP-NOW messages...");
    heartBeat = millis();
  }
}

```

#コントローラ（マスタ）側
マスター側には、スレーブのMACアドレスを登録して送信先を指定しています。こちらは当然ですがSTAモードで設定しました。
5msec毎に1ずつInc/Decした値を送り、call back関数で 成功したかどうかをprintしていますが、見たところ失敗なく送信できているようです(100%かどうかは、未確認です）。
送るデータ構造は、適当に floatひとつと integerひとつで構成しましたが、最大250byteなので、とりあえず、実験はこれでOKです。当然、スレーブ側で受ける構造体と併せないとおかしなことになります。

```c:
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
struct __attribute__((packed)) SENSOR_DATA {
  float temperature;
  int val;
} sensorData;

#define WIFI_CHANNEL 1
uint8_t slaveMAC[] = {0x12, 0x12, 0x12, 0x12, 0x12, 0x12};

uint8_t bs[sizeof(sensorData)];
int ctr = 0;

void send_cb(uint8_t* mac, uint8_t sendStatus) {
  Serial.printf("send status = %i\n", sendStatus);
}

void setup() {
  Serial.begin(74880);
  Serial.println();
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != 0) {
    Serial.println("*** ESP-Now init failed");
  }

  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_add_peer(slaveMAC, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0);
  esp_now_register_send_cb(send_cb);
}

int direction = 0;
void loop() {
  sensorData.val = ctr;
  sensorData.temperature = ctr * 10.0;
  memcpy(bs, &sensorData, sizeof(sensorData));
  esp_now_send(NULL, bs, sizeof(sensorData)); // NULL means send to all peers
  delay(5);
  if (direction == 0) {
    if (ctr < 100) ctr++;
    else {
      direction = 1;
    }
  } else {
    if (ctr >= 1) ctr--;
    else {
      direction = 0;
    }
  }
}
```

#通信結果
約5msec周期で送り、受け取った値を、そのままグラフにプロットすると以下のような三角波となっており、特におかしな段差は見られないです。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266665/3f023562-3477-8a74-f87b-b37ffcdbd8e0.png)

とりあえず、これで ESP-Nowは便利な通信手段として ESP8266同士で使える事が確認できたことになります。アクセスするWiFiの環境を別途作れない場合、単純なセンサーからのデータであれば、ESP-Nowをつかって集め、集めたスレーブ機から、次のホストへ転送するなりして処理をする形が良いのではと思います。

次は、複数のESP8266から、スレーブとしてESP32を置き、そこからUSB Serialで ラズパイに送ってからNode-REDとの連携をしようと考えています。まずは、ここまで。

#以下を参考にさせて頂きました。

- [ESP-NOW User Guide](https://www.espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf)
- [HarringayMakerSpace/ESP-Now](https://github.com/HarringayMakerSpace/ESP-Now)