スポンサーリンク
Translate

ESP32とESP NOWを使って片方向トランシーバーを作ってみた

スポンサーリンク

ESP32はESP NOWという通信方式を使って、ESP32同士でデータのやり取りが簡単にできてしまいます。

今回は、2つESP32を用意して、片方で音を録音したデータをESP NOWで転送して、もう片方で音を再生するという、片方向のトランシーバーを作ってみることしました。とりあえず動けばいいやという感じで、作っていきたいと思います。

ESP32には、便利なESP32 DevKitCを2個使用します。

スポンサーリンク

送信側

回路

マイクとそのアンプ回路を用意して、音声信号をAD入力のピン(33)に入力します。

マイクとマイクアンプ回路はこんな感じです。作るのが面倒な方は、便利なマイクモジュールが売っているので、これが使えると思います。

プログラム

ネットにあったプログラムを適当に変更して、送信プログラムを作ってみました。

送信相手のMACアドレスが必要です。6行目にそのアドレスを入れてください。例としてAA.BB.CC.DD.EE.FFとなっています。

だいたい15kHzでADし、200サンプルたまったところで、ESP NOWを使ってデータを送信しています。

#include <esp_now.h>
#include <WiFi.h>

//Receiver Mac Address
uint8_t broadcastAddress[] = {
  0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};

#define MIC_PIN 33

int buffer_size = 128;//8kib
byte* buffer;

#define LED_PIN 2

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  /*
    Serial.print("\r\nLast Packet Send Status:\t");
    Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  */
}

typedef struct struct_message {// ~ 250byte
  int8_t wave[200];
} struct_message;

struct_message send_data;

int bias = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("hello!");

  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  Serial.print("my mac address : ");
  Serial.println(WiFi.macAddress());

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);

  // Register peer
  esp_now_peer_info_t peerInfo;
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;
  peerInfo.encrypt = false;

  // Add peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }

  adcAttachPin(MIC_PIN);
  analogReadResolution(10);
  //analogSetPinAttenuation(MIC_PIN, ADC_0db);

  pinMode(LED_PIN, OUTPUT);
  delay(100);
  bias = analogRead(MIC_PIN);
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  for (int i = 0; i < 200; i++) {
    int in = analogRead(MIC_PIN);
    int out = (in - bias);
    if (out < -128)out = -128;
    if (out > +127)out = +127;
    send_data.wave[i] = out;
    delayMicroseconds(1000000 / 15000);
  }
  digitalWrite(LED_PIN, LOW);

  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &send_data, sizeof(send_data));
}

 

スポンサーリンク

受信側

回路

出力ピンに、スピーカーを接続します。ただ直接接続すると壊れるので、トランジスタのバッファ回路を間に挟んでいます。

プログラム

#include <esp_now.h>
#include <WiFi.h>

#define SPEAKER_PIN 12

int buffer_size = 128;//8kib
byte* buffer;

#define LED_PIN 2

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

typedef struct struct_message {// ~ 250byte
  int8_t wave[200];
} struct_message;

struct_message receive_data;

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  digitalWrite(LED_PIN, HIGH);
  memcpy(&receive_data, incomingData, sizeof(receive_data));
  for (int i = 0; i < 200; i++) {
    ledcWrite(0, receive_data.wave[i] + 128);
    delayMicroseconds(1000000 / 14500);
  }
  digitalWrite(LED_PIN, LOW);
}

void setup() {
  disableCore0WDT();
  disableCore1WDT();
  
  Serial.begin(115200);
  Serial.println("hello!");

  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  Serial.print("my mac address : ");
  Serial.println(WiFi.macAddress());

  ledcSetup(0, 48 * 1000, 8);
  ledcAttachPin(SPEAKER_PIN, 0);

  pinMode(LED_PIN, OUTPUT);

  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  delay(100);
}

ESP NOWでデータを受信したら、PWMに1サンプルずつ出力していきます。Delayでループしていて、正確な周期が設定できないので、ループの周期が送信側と同じ感じになるように、Delayを調節しました。

スポンサーリンク

結果

送信側で、チキンさんに歌ってもらいました。

タイトルは「チキンの夢物語」です。それではチキンさん。どうぞ。

ブーーーというノイズ音が聞こえます。残念ながらESP32は、WiFi通信をしているときにはA/D変換にノイズが入るようです。通信中は電源電圧も結構変動しているので、このような状態では綺麗なA/D変換は期待できないでしょう。

音質はいまいちですが、遅延はほとんどなくESP32同士を使って、片方向ですがトランシーバーができてしまいました。デジタル無線と言っていいのでしょうか。なんだか面白いです。

送信側にモバイルバッテリーをつないで、家中動き回りましたが、どこにいても受信側に声が届いていました。

試しに受信機を家の中に置いて、送信機を外へ持ち出してみました。家からみ通し30mくらいは電波が届きますが、それ以上だと電波が途切れ途切れになり、他の家の陰に入ってしまうと電波が完全に途切れてしまう感じでした。結構電波飛びますね。

ESP32とESP NOWでトランシーバーを作ってみたという記事でした。