今回は、マイクとアンプを接続します。接続は、サーバー側をAP接続。クライアント側をIPアドレス固定で行います。先ずはサーバー側のスケッチ
#include "WiFi.h"
#include <WiFiUdp.h>
#include <driver/i2s.h>
const char * ssid = "ESP32UDP"; // SSID
const char * password = "12345678"; // password
WiFiUDP wifiUdp;
static const int RmoteUdpPort = 9000;
static const int LocalPort = 9000;
// AMP Port
#define I2S_NUM_AMP I2S_NUM_0
#define I2S_PIN_WS_AMP 4
#define I2S_PIN_CLK_AMP 16
#define I2S_PIN_DOUT_AMP 17
#define I2S_PIN_DIN_AMP I2S_PIN_NO_CHANGE
// MIC Port
#define I2S_NUM_MIC I2S_NUM_1
#define I2S_PIN_CLK_MIC 27
#define I2S_PIN_WS_MIC 25
#define I2S_PIN_DOUT_MIC I2S_PIN_NO_CHANGE
#define I2S_PIN_DIN_MIC 26
#define I2S_SAMPLE_RATE 32000
#define I2S_BUFFER_COUNT 4
#define I2S_BUFFER_SIZE 512
//DMA Buffer
#define DMA_BUFFER_SIZE 1024
uint8_t recBuffer[DMA_BUFFER_SIZE];
IPAddress ip(192, 168, 4, 2); // for fixed IP Address
IPAddress gateway(192,168, 4, 1); //
IPAddress subnet(255, 255, 255, 0); //
// Initiate AMP
void i2s_AMP_Init()
{
i2s_config_t i2s_config_AMP = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config_AMP = {
.bck_io_num = I2S_PIN_CLK_AMP,
.ws_io_num = I2S_PIN_WS_AMP,
.data_out_num = I2S_PIN_DOUT_AMP,
.data_in_num = I2S_PIN_DIN_AMP,
};
i2s_driver_install(I2S_NUM_AMP, &i2s_config_AMP, 0, NULL);
i2s_set_pin(I2S_NUM_AMP, &pin_config_AMP);
}
// Initiate MIC
void i2s_MIC_Init()
{
i2s_config_t i2s_config_MIC = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config_MIC = {
.bck_io_num = I2S_PIN_CLK_MIC,
.ws_io_num = I2S_PIN_WS_MIC,
.data_out_num = I2S_PIN_DOUT_MIC,
.data_in_num = I2S_PIN_DIN_MIC,
};
i2s_driver_install(I2S_NUM_MIC, &i2s_config_MIC, 0, NULL);
i2s_set_pin(I2S_NUM_MIC, &pin_config_MIC);
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);
// Try forever
while (WiFi.status() != WL_CONNECTED)
{
Serial.println("...Connecting to WiFi");
delay(1000);
}
Serial.println("Connected");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
wifiUdp.begin(LocalPort);
Serial.println("Client OK");
i2s_MIC_Init();
i2s_AMP_Init();
Serial.println("Send Server");
wifiUdp.beginPacket("192.168.4.1", RmoteUdpPort);
wifiUdp.write((uint8_t *)"OK",2);
wifiUdp.endPacket();
Serial.println("I2S OK");
}
void loop()
{
uint8_t rv_buf[DMA_BUFFER_SIZE];
int a,b;
size_t transBytes;
Serial.println("Write");
i2s_read(I2S_NUM_MIC, (char*)recBuffer, DMA_BUFFER_SIZE, &transBytes, portMAX_DELAY);
wifiUdp.beginPacket("192.168.4.1", RmoteUdpPort);
wifiUdp.write(recBuffer,DMA_BUFFER_SIZE);
wifiUdp.endPacket();
if (wifiUdp.parsePacket() > 0)
{
Serial.println("Recieve");
wifiUdp.read(rv_buf , DMA_BUFFER_SIZE);
i2s_write_bytes(I2S_NUM_AMP, rv_buf, sizeof(rv_buf), portMAX_DELAY);
wifiUdp.flush();
}
}
- 12から16行: I2S アンプ側のパラメータ
- 19から23行: I2S マイク側のパラメータ
- 25から27行: サンプリング周波数とDMAバッファーの設定
- 35から60行: アンプの初期設定関数
- 63から88行: マイクの初期設定関数
- 94行: APモードで接続。(IPアドレスは192.168.4.1になる)
- 103,103行: I2Sマイクとアンプ開始。
- 107から108行: クライアントの接続待ち
- この部分無しにLoop()に入ると、クライアントの接続が出来ませんでした。
- クライアントからの送信待ち
- 121から127行: クライアントから受信したデータをアンプへ出力
- 129から132行: マイクのデータをクライアントに送信
次は、クライアント側
#include "WiFi.h"
#include <WiFiUdp.h>
#include <driver/i2s.h>
const char * ssid = "ESP32UDP"; // SSID
const char * password = "12345678"; // password
WiFiUDP wifiUdp;
static const int RmoteUdpPort = 9000;
static const int LocalPort = 9000;
// AMP Port
#define I2S_NUM_AMP I2S_NUM_0
#define I2S_PIN_WS_AMP 4
#define I2S_PIN_CLK_AMP 16
#define I2S_PIN_DOUT_AMP 17
#define I2S_PIN_DIN_AMP I2S_PIN_NO_CHANGE
// MIC Port
#define I2S_NUM_MIC I2S_NUM_1
#define I2S_PIN_CLK_MIC 27
#define I2S_PIN_WS_MIC 25
#define I2S_PIN_DOUT_MIC I2S_PIN_NO_CHANGE
#define I2S_PIN_DIN_MIC 26
#define I2S_SAMPLE_RATE 32000
#define I2S_BUFFER_COUNT 4
#define I2S_BUFFER_SIZE 512
//DMA Buffer
#define DMA_BUFFER_SIZE 1024
uint8_t recBuffer[DMA_BUFFER_SIZE];
IPAddress ip(192, 168, 4, 2); // for fixed IP Address
IPAddress gateway(192,168, 4, 1); //
IPAddress subnet(255, 255, 255, 0); //
// Initiate AMP
void i2s_AMP_Init()
{
i2s_config_t i2s_config_AMP = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config_AMP = {
.bck_io_num = I2S_PIN_CLK_AMP,
.ws_io_num = I2S_PIN_WS_AMP,
.data_out_num = I2S_PIN_DOUT_AMP,
.data_in_num = I2S_PIN_DIN_AMP,
};
i2s_driver_install(I2S_NUM_AMP, &i2s_config_AMP, 0, NULL);
i2s_set_pin(I2S_NUM_AMP, &pin_config_AMP);
}
// Initiate MIC
void i2s_MIC_Init()
{
i2s_config_t i2s_config_MIC = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config_MIC = {
.bck_io_num = I2S_PIN_CLK_MIC,
.ws_io_num = I2S_PIN_WS_MIC,
.data_out_num = I2S_PIN_DOUT_MIC,
.data_in_num = I2S_PIN_DIN_MIC,
};
i2s_driver_install(I2S_NUM_MIC, &i2s_config_MIC, 0, NULL);
i2s_set_pin(I2S_NUM_MIC, &pin_config_MIC);
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);
// Try forever
while (WiFi.status() != WL_CONNECTED)
{
Serial.println("...Connecting to WiFi");
delay(1000);
}
Serial.println("Connected");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
wifiUdp.begin(LocalPort);
Serial.println("Client OK");
i2s_MIC_Init();
i2s_AMP_Init();
Serial.println("Send Server");
wifiUdp.beginPacket("192.168.4.1", RmoteUdpPort);
wifiUdp.write((uint8_t *)"OK",2);
wifiUdp.endPacket();
Serial.println("I2S OK");
}
void loop()
{
uint8_t rv_buf[DMA_BUFFER_SIZE];
int a,b;
size_t transBytes;
Serial.println("Write");
i2s_read(I2S_NUM_MIC, (char*)recBuffer, DMA_BUFFER_SIZE, &transBytes, portMAX_DELAY);
wifiUdp.beginPacket("192.168.4.1", RmoteUdpPort);
wifiUdp.write(recBuffer,DMA_BUFFER_SIZE);
wifiUdp.endPacket();
if (wifiUdp.parsePacket() > 0)
{
Serial.println("Recieve");
wifiUdp.read(rv_buf , DMA_BUFFER_SIZE);
i2s_write_bytes(I2S_NUM_AMP, rv_buf, sizeof(rv_buf), portMAX_DELAY);
wifiUdp.flush();
}
}
- 基本はサーバー側と同じ。
- 35から37行: 固定IPアドレスの指定
- 99行: クライアント側はSTAモードで接続。
- 100行: IPアドレスを固定。
- 121から123行: サーバーにダミーデータを送信
- サーバーにクライアントがレディになった事を知らせる
- 134から137行: マイクのデータをサーバーに送信
- 135行: beginPacket()の第一引数にサーバーのIPアドレスを直接指定
- 139から144行: サーバーからのデータをアンプに出力。
この2つのスケッチを実行すれば、サーバーからクライアント、クライアントからサーバーに音声データを送信出来ます。簡易インターフォンとなります。コンパイル実行して下さい。
AP接続について
今回は2つあるESP32の一方をサーバーとしましたが、もう一つESP32を用意しそれをサーバー専用にしその他の2つをIPアドレス固定でサーバーに接続した場合、お互いに通信出来るのか確認してみました。つまり以前ルータを介して接続した時のルータの変わりにAP接続のESP32を使用する接続です。
サーバ側のスケッチ
#include "WiFi.h"
const char * ssid = "ESP32UDP"; // SSID
const char * password = "12345678"; // password
void setup()
{
Serial.begin(115200);
WiFi.softAP(ssid, password);
delay(1000);
Serial.print("AP IP address: "); // 192.168.4.1
Serial.println(WiFi.softAPIP());
Serial.println("Server OK");
}
void loop()
{
}
- このESP32はただ単に、AP接続のサーバを立ち上げているだけです。
クライアント側
#include "WiFi.h"
#include <WiFiUdp.h>
#include <driver/i2s.h>
const char * ssid = "ESP32UDP"; // SSID
const char * password = "12345678"; // password
WiFiUDP wifiUdp;
static const int RmoteUdpPort = 9000;
static const int LocalPort = 9000;
// AMP Port
#define I2S_NUM_AMP I2S_NUM_0
#define I2S_PIN_WS_AMP 4
#define I2S_PIN_CLK_AMP 16
#define I2S_PIN_DOUT_AMP 17
#define I2S_PIN_DIN_AMP I2S_PIN_NO_CHANGE
// MIC Port
#define I2S_NUM_MIC I2S_NUM_1
#define I2S_PIN_CLK_MIC 27
#define I2S_PIN_WS_MIC 25
#define I2S_PIN_DOUT_MIC I2S_PIN_NO_CHANGE
#define I2S_PIN_DIN_MIC 26
#define I2S_SAMPLE_RATE 32000
#define I2S_BUFFER_COUNT 4
#define I2S_BUFFER_SIZE 512
//DMA Buffer
#define DMA_BUFFER_SIZE 1024
uint8_t recBuffer[DMA_BUFFER_SIZE];
IPAddress ip(192, 168, 4, 2); // for fixed IP Address
IPAddress gateway(192,168, 4, 1); //
IPAddress subnet(255, 255, 255, 0); //
// Initiate AMP
void i2s_AMP_Init()
{
i2s_config_t i2s_config_AMP = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config_AMP = {
.bck_io_num = I2S_PIN_CLK_AMP,
.ws_io_num = I2S_PIN_WS_AMP,
.data_out_num = I2S_PIN_DOUT_AMP,
.data_in_num = I2S_PIN_DIN_AMP,
};
i2s_driver_install(I2S_NUM_AMP, &i2s_config_AMP, 0, NULL);
i2s_set_pin(I2S_NUM_AMP, &pin_config_AMP);
}
// Initiate MIC
void i2s_MIC_Init()
{
i2s_config_t i2s_config_MIC = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config_MIC = {
.bck_io_num = I2S_PIN_CLK_MIC,
.ws_io_num = I2S_PIN_WS_MIC,
.data_out_num = I2S_PIN_DOUT_MIC,
.data_in_num = I2S_PIN_DIN_MIC,
};
i2s_driver_install(I2S_NUM_MIC, &i2s_config_MIC, 0, NULL);
i2s_set_pin(I2S_NUM_MIC, &pin_config_MIC);
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);
// Try forever
while (WiFi.status() != WL_CONNECTED)
{
Serial.println("...Connecting to WiFi");
delay(1000);
}
Serial.println("Connected");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
wifiUdp.begin(LocalPort);
Serial.println("Client OK");
i2s_MIC_Init();
i2s_AMP_Init();
Serial.println("I2S OK");
}
void loop()
{
uint8_t rv_buf[DMA_BUFFER_SIZE];
int a,b;
size_t transBytes;
Serial.println("Write");
i2s_read(I2S_NUM_MIC, (char*)recBuffer, DMA_BUFFER_SIZE, &transBytes, portMAX_DELAY);
wifiUdp.beginPacket("192.168.4.3", RmoteUdpPort);
wifiUdp.write(recBuffer,DMA_BUFFER_SIZE);
wifiUdp.endPacket();
if (wifiUdp.parsePacket() > 0)
{
Serial.println("Recieve");
wifiUdp.read(rv_buf , DMA_BUFFER_SIZE);
i2s_write_bytes(I2S_NUM_AMP, rv_buf, sizeof(rv_buf), portMAX_DELAY);
wifiUdp.flush();
}
}
- 先程のクライアント用のスケッチです。
- 131行: ここで、相手側にIPアドレスを、”192.168.4.3”と指定しています。
もう一つのクライアントは上記のスケッチ、
- 35行: IPアドレスの指定を、”192.168.4.3” に変更
- 131行: 相手先のIPアドレスを、”192.168.4.2”に変更
して下さい。これで、”192.168.4.2”と”192.168.4.3”の間でUDP通信する事になります。また、今回はサーバー用にESP32を1台使用しているので、クライアントの認識が問題無く出来る様なので、認識用のダミーデータの送信は削除しています。3つのスケッチをコンパイル実行して下さい。インターフォンとして動作しました。
これを応用すれば、
- 現在は1対1の通信で相手が固定だが、相手を変更する事が可能
- 複数接続しその中の1つまたは複数、または全員と繋ぐ事が可能
が考えられます。各部屋にこの機器を置いて、部屋同士または一斉に話す事が可能になるのでしょうか。