質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
M5Stack

M5Stackは、小型のマイコンモジュールです。拡張モジュールが豊富に用意されており、センサと組み合わせることで測定機能を自由に追加することができます。

IDE

IDE、統合開発環境((Integrated Development Environment)とは、テキストエディタ以上の機能を提供して、ソフトウェア開発を効率をあげるコンピュータプログラムを指す。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

0回答

1641閲覧

M5Stick同士で音声通信がしたい

Letemon

総合スコア4

M5Stack

M5Stackは、小型のマイコンモジュールです。拡張モジュールが豊富に用意されており、センサと組み合わせることで測定機能を自由に追加することができます。

IDE

IDE、統合開発環境((Integrated Development Environment)とは、テキストエディタ以上の機能を提供して、ソフトウェア開発を効率をあげるコンピュータプログラムを指す。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2020/11/10 08:17

編集2020/11/10 13:34

やりたいこと:M5StickC同士での音声通信

使用しているパーツ:M5StickC本体、SPKHAT

UDP通信で音声データを送るコードを書いているのですが、送信はおそらくできているのですが、受信ができていないみたいです。

具体的には、送信側のコードのwifi_send()関数内の
wifiUdp.beginPacket(pc_addr, pc_port);
wifiUdp.write(send_num);
wifiUdp.write(recPos_a);
wifiUdp.write(recPos_b);
wifiUdp.endPacket();
は、受信側で受け取れているのですが、2回目以降のwifiUdp.beginPacket(pc_addr, pc_port);で送る
wifiUdp.write(send_num);
wifiUdp.write(soundStorage[recPos_bef]);
が受け取ることができていません。

受信側では、wifi_receive() 関数内のint num_packet = wifiUdp.parsePacket();で受け取ったnum_packetが
Serial.printで0と表示されます。

送信側コード #include <M5StickC.h> #include <driver/i2s.h> #include <WiFi.h> #include <WiFiUDP.h> #define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ ((x)<< 8 & 0x00FF0000UL) | \ ((x)>> 8 & 0x0000FF00UL) | \ ((x)>>24 & 0x000000FFUL) ) #define PIN_CLK (0) // I2S Clock PIN #define PIN_DATA (34) // I2S Data PIN #define SAMPLING_RATE (16384) // サンプリングレート(44100, 22050, 16384, more...) #define BUFFER_LEN (1024) // バッファサイズ //#define STORAGE_LEN (102400) // 本体保存容量(MAX 100K前後) #define STORAGE_LEN (52400) #define WAVE_EXPORT (0) // WAVEファイルに出力するか const char* ssid = "????????"; const char* password = "?????????"; WiFiUDP wifiUdp; const char *pc_addr = "??????????????"; //"???????";//相手のipアドレス(com4:??????) const int pc_port = 50008; //送信先のポート const int my_port = 50007; //自身のポート uint8_t soundBuffer[BUFFER_LEN]; // DMA転送バッファ uint8_t soundStorage[STORAGE_LEN]; // サウンドデータ保存領域 bool recFlag = false; // 録音状態 int recPos = 0; // 録音の長さ int recPos_bef = 0; // 録音をする void i2sRecord() { // 録音用設定 i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM), .sample_rate = SAMPLING_RATE, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ALL_RIGHT, .communication_format = I2S_COMM_FORMAT_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 2, .dma_buf_len = BUFFER_LEN, .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = 0, }; // PIN設定 i2s_pin_config_t pin_config; pin_config.bck_io_num = I2S_PIN_NO_CHANGE; pin_config.ws_io_num = PIN_CLK; pin_config.data_out_num = I2S_PIN_NO_CHANGE; pin_config.data_in_num = PIN_DATA; // 録音設定実施 i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM_0, &pin_config); i2s_set_clk(I2S_NUM_0, SAMPLING_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); // 録音開始 recFlag = true; xTaskCreatePinnedToCore(i2sRecordTask, "i2sRecordTask", 2048, NULL, 1, NULL, 1); } // 録音用タスク void i2sRecordTask(void* arg) { // 初期化 recPos = 0; memset(soundStorage, 0, sizeof(soundStorage)); // 録音処理 while (recFlag) { size_t transBytes; // I2Sからデータ取得 i2s_read(I2S_NUM_0, (char*)soundBuffer, BUFFER_LEN, &transBytes, (100 / portTICK_RATE_MS)); // int16_t(12bit精度)をuint8_tに変換 recPos_bef = recPos;//どこから送信するか for (int i = 0 ; i < transBytes ; i += 2 ) { if ( recPos < STORAGE_LEN ) { int16_t* val = (int16_t*)&soundBuffer[i]; soundStorage[recPos] = ( *val + 32768 ) / 256; recPos++; } } wifi_send(); Serial.printf("transBytes = %d, STORAGE_LEN=%d, recPos=%d\n", transBytes, STORAGE_LEN, recPos); vTaskDelay(1 / portTICK_RATE_MS); } i2s_driver_uninstall(I2S_NUM_0); // タスク削除 vTaskDelete(NULL); } void wifi_send() { Serial.println("------------------Send Start------------------"); // データ送信 int send_num = 0;//何回目のsendか int recPos_a = recPos_bef/256; int recPos_b = recPos_bef%256; wifiUdp.beginPacket(pc_addr, pc_port); send_num++; wifiUdp.write(send_num); wifiUdp.write(recPos_a); wifiUdp.write(recPos_b); for(int i=0;recPos_bef<recPos;i++){ if(i%180 == 0){//180回ごとに送る wifiUdp.endPacket();//1460byte(/8=182bit)以上になると捨てられるので注意 Serial.println("Send middle"); delay(10); wifiUdp.flush(); int begPac = wifiUdp.beginPacket(pc_addr, pc_port); if(begPac == 0){ Serial.println("beginPacket miss"); }else{ Serial.println("beginPacket OK"); } send_num++; wifiUdp.write(send_num); Serial.print("send_num : "); Serial.println(send_num); } wifiUdp.write(soundStorage[recPos_bef]);//send_num=1から始まる recPos_bef++; } wifiUdp.endPacket();//1460byte(/8=182bit)以上になると捨てられるので注意 Serial.println("------------------Send End------------------"); } void setup() { M5.begin(); M5.Lcd.setRotation(3); M5.Lcd.fillScreen(WHITE); M5.Lcd.setTextColor(BLACK, WHITE); M5.Lcd.println("Sound Recorder"); M5.Lcd.println("BtnA Record"); WiFi.begin(ssid, password); while( WiFi.status() != WL_CONNECTED) { M5.Lcd.print("."); delay(500); } M5.Lcd.print("\r\nWiFi connected\r\nIP address: "); M5.Lcd.println(WiFi.localIP()); wifiUdp.begin(my_port); delay(500);//wifiUdp.begin()の処理を待つ時間 M5.Lcd.println("Setup OK"); } void loop() { M5.update(); if ( M5.BtnA.wasPressed() ) { // 録音スタート //M5.Lcd.setCursor(0, 24); M5.Lcd.println("REC..."); Serial.println("Record Start"); i2sRecord(); } else if ( M5.BtnA.wasReleased() ) { // 録音ストップ M5.Lcd.setCursor(0, 24); M5.Lcd.println(" "); recFlag = false; delay(100); // 録音終了まで待つ Serial.println("Record Stop"); } delay(10); }
受信側 #include <M5StickC.h> #include <driver/i2s.h> #include <WiFi.h> #include <WiFiUDP.h> #define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ ((x)<< 8 & 0x00FF0000UL) | \ ((x)>> 8 & 0x0000FF00UL) | \ ((x)>>24 & 0x000000FFUL) ) #define PIN_CLK (0) // I2S Clock PIN #define PIN_DATA (34) // I2S Data PIN #define SAMPLING_RATE (16384) // サンプリングレート(44100, 22050, 16384, more...) #define BUFFER_LEN (1024) // バッファサイズ //#define STORAGE_LEN (102400) // 本体保存容量(MAX 100K前後) #define STORAGE_LEN (52400) const char* ssid = "???????????"; const char* password = "?????????"; WiFiUDP wifiUdp; const char *pc_addr = "??????????"; //"????????";//相手のipアドレス const int pc_port = 50007; //送信先のポート const int my_port = 50008; //自身のポート uint8_t receive_soundBuffer[BUFFER_LEN]; // DMA転送バッファ uint8_t receive_soundStorage[STORAGE_LEN]; // サウンドデータ保存領域 uint8_t receive_soundStorage_tmp[185]; // サウンドデータ保存領域 bool recFlag = false; // 録音状態 int recPos = 0; // 録音の長さ // 再生をする void i2sPlay(){ //省略 } void wifi_receive() { int num_packet = wifiUdp.parsePacket(); if (num_packet){ Serial.print("num_packet : "); Serial.println(num_packet); int recPos_tmp,recPos_a,recPos_b; int j = 0; int send_num;//何回目のsendか int send_num_tmp = 2;//次に受け取りたいsend_numの番号 send_num = wifiUdp.read(); recPos_a = wifiUdp.read(); recPos_b = wifiUdp.read(); recPos_tmp = recPos_a*256 + recPos_b;//1回で送られた録音の長さ recPos += recPos_tmp;//最終的な録音の長さ Serial.print("recPos_tmp : "); Serial.println(recPos_tmp); delay(5); while(1){ num_packet = wifiUdp.parsePacket(); if (num_packet){ send_num = wifiUdp.read(); Serial.print("send_num : "); Serial.println(send_num); if(send_num == send_num_tmp){ Serial.println("Receive middle"); int len = wifiUdp.read(receive_soundStorage_tmp,num_packet-1); for(int i=0;i<len;i++){ receive_soundStorage[i] = receive_soundStorage_tmp[i]; } send_num_tmp++; if(j<recPos_tmp){ j += len; }else{break;} } }else{ Serial.println("num_packet = 0"); delay(5); } } Serial.println("Receive End"); } } void setup() { M5.begin(); M5.Lcd.setRotation(3); M5.Lcd.fillScreen(WHITE); M5.Lcd.setTextColor(BLACK, WHITE); M5.Lcd.println("Sound Recorder"); M5.Lcd.println("BtnA Record"); M5.Lcd.println("BtnB Play"); WiFi.begin(ssid, password); while( WiFi.status() != WL_CONNECTED) { M5.Lcd.print("."); delay(500); } M5.Lcd.print("\r\nWiFi connected\r\nIP address: "); M5.Lcd.println(WiFi.localIP()); wifiUdp.begin(my_port); delay(500);//wifiUdp.begin()の処理を待つ時間 M5.update(); } void loop() { wifi_receive(); if ( M5.BtnB.wasReleased() ) { Serial.println("sizeof : "); Serial.println(sizeof(receive_soundStorage)); // 再生スタート M5.Lcd.setCursor(0, 24); M5.Lcd.println("Play..."); Serial.println("Play Start"); i2sPlay(); M5.Lcd.println("Play Stop"); Serial.println("Play Stop"); recPos = 0; M5.update(); } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2020/11/10 23:39

まだそんなに精査していませんが、 WiFiUDP::parsePacket()はブロックしないで未受信時には0を返す仕様だったと思います。 受信したとき以外は0を返すので、大量に"num_packet = 0"が表示されるのが当然と思いますが、そういうことではなくて、パケットが送信されたはずの時にも一切受信されない、ということなのですか?
Letemon

2020/11/11 02:45

回答頂きありがとうございます。 はい、”パケットが送信されたはずの時にも一切受信されない”状態です。 具体的には、送信側のコードのwifi_send()関数内の最初のパケット(send_num,recPos_a,recPos_bの3つ)は受信できています。 しかし、その後のfor文内でパケット(send_num,soundStorage[recPos_bef])を送信したはずなのに一切受信されていないです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問