diff --git a/FactoryTest/FactoryTest.ino b/FactoryTest/FactoryTest.ino index a09b181..b5399db 100644 --- a/FactoryTest/FactoryTest.ino +++ b/FactoryTest/FactoryTest.ino @@ -7,7 +7,7 @@ // #include // #include -// #define ENABLE_I2S 0 +#define ENABLE_I2S 1 // #define ENABLE_BLE 1 #ifdef ENABLE_BLE @@ -126,16 +126,19 @@ void powerOffOrDeepSleep() { - if (M5.Power.isCharging()){ + if (M5.Power.isCharging()) + { Disbuff.fillRect(0, 0, 240, 135, TFT_RED); Disbuff.setCursor(12, 20); Disbuff.setTextColor(TFT_WHITE); Disbuff.printf("Enter Deep Sleep"); Disbuff.pushSprite(0, 0); M5.delay(3000); - esp_sleep_enable_timer_wakeup(7 * 86400 * 1000000ULL); // 24時間後に復帰 + esp_sleep_enable_timer_wakeup(7 * 86400 * 1000000ULL); // 24時間後に復帰 esp_deep_sleep_start(); - } else { + } + else + { Disbuff.fillRect(0, 0, 240, 135, TFT_GREEN); Disbuff.setCursor(12, 20); Disbuff.setTextColor(TFT_BLACK); @@ -412,57 +415,57 @@ void MicRecordfft(void *arg) // フーリエ変換 { #ifdef ENABLE_I2S - int16_t *buffptr; - size_t bytesread; - uint16_t count_n = 0; - float adc_data; - double data = 0; - uint16_t ydata; - uint16_t count_offset = 1; + // int16_t *buffptr; + // size_t bytesread; + // uint16_t count_n = 0; + // float adc_data; + // double data = 0; + // uint16_t ydata; + // uint16_t count_offset = 1; - while (1) - { - xSemaphoreTake(start_fft, portMAX_DELAY); - xSemaphoreGive(start_fft); - fft_config_t *real_fft_plan = fft_init(1024, FFT_REAL, FFT_FORWARD, NULL, NULL); - i2s_read(I2S_NUM_0, (char *)i2s_readraw_buff, 2048, &bytesread, (100 / portTICK_RATE_MS)); // portTICK_RATE_MS は 1 - buffptr = (int16_t *)i2s_readraw_buff; + // while (1) + // { + // xSemaphoreTake(start_fft, portMAX_DELAY); + // xSemaphoreGive(start_fft); + // fft_config_t *real_fft_plan = fft_init(1024, FFT_REAL, FFT_FORWARD, NULL, NULL); + // i2s_read(I2S_NUM_0, (char *)i2s_readraw_buff, 2048, &bytesread, (100 / portTICK_RATE_MS)); // portTICK_RATE_MS は 1 + // buffptr = (int16_t *)i2s_readraw_buff; - // fftmax, fftmaxidx = real_fft_plan->size; + // // fftmax, fftmaxidx = real_fft_plan->size; - for (count_n = 0; count_n < real_fft_plan->size; count_n++) // eal_fft_plan->sizeは1024 - { - adc_data = (float)map(buffptr[count_n], INT16_MIN, INT16_MAX, -2000, 2000); // long map(long x, long in_min, long in_max, long out_min, long out_max) - real_fft_plan->input[count_n] = adc_data; - } - fft_execute(real_fft_plan); + // for (count_n = 0; count_n < real_fft_plan->size; count_n++) // eal_fft_plan->sizeは1024 + // { + // adc_data = (float)map(buffptr[count_n], INT16_MIN, INT16_MAX, -2000, 2000); // long map(long x, long in_min, long in_max, long out_min, long out_max) + // real_fft_plan->input[count_n] = adc_data; + // } + // fft_execute(real_fft_plan); - xSemaphoreTake(xSemaphore, 100 / portTICK_RATE_MS); - for (count_n = 1; count_n < real_fft_plan->size / 4; count_n++) // 1024/4=>256 - { - data = sqrt(real_fft_plan->output[2 * count_n] * real_fft_plan->output[2 * count_n] + real_fft_plan->output[2 * count_n + 1] * real_fft_plan->output[2 * count_n + 1]); - if ((count_n - 1) < 254) - { - data = (data > 3000) ? 3000 : data; - ydata = map(data, 0, 3000, 0, 255); - if (128 - count_n > 0) - fft_dis_buff[posData][128 - count_n] = ydata; - if (ydata > 40 && fftmax < ydata) - { - fftmax = ydata; - fftmaxidx = count_n; - } - } - } + // xSemaphoreTake(xSemaphore, 100 / portTICK_RATE_MS); + // for (count_n = 1; count_n < real_fft_plan->size / 4; count_n++) // 1024/4=>256 + // { + // data = sqrt(real_fft_plan->output[2 * count_n] * real_fft_plan->output[2 * count_n] + real_fft_plan->output[2 * count_n + 1] * real_fft_plan->output[2 * count_n + 1]); + // if ((count_n - 1) < 254) + // { + // data = (data > 3000) ? 3000 : data; + // ydata = map(data, 0, 3000, 0, 255); + // if (128 - count_n > 0) + // fft_dis_buff[posData][128 - count_n] = ydata; + // if (ydata > 40 && fftmax < ydata) + // { + // fftmax = ydata; + // fftmaxidx = count_n; + // } + // } + // } - posData++; - if (posData >= 241) - { - posData = 0; - } - xSemaphoreGive(xSemaphore); - fft_destroy(real_fft_plan); - } + // posData++; + // if (posData >= 241) + // { + // posData = 0; + // } + // xSemaphoreGive(xSemaphore); + // fft_destroy(real_fft_plan); + // } #endif } @@ -517,29 +520,152 @@ TaskHandle_t xhandle_display = NULL; TaskHandle_t xhandle_fft = NULL; +static constexpr const size_t record_number = 256; +static constexpr const size_t record_length = 200; +static constexpr const size_t record_size = record_number * record_length; +static constexpr const size_t record_samplerate = 16000; +static int16_t prev_y[record_length]; +static int16_t prev_h[record_length]; +static size_t rec_record_idx = 2; +static size_t draw_record_idx = 0; +static int16_t *rec_data; + void DisplayMicro() { Disbuff.fillRect(0, 0, 160, 80, Disbuff.color565(0, 0, 0)); // 黒(R=0,G=0,B=0)で塗りつぶす Disbuff.pushSprite(0, 0); +#ifdef ENABLE_I2S + prepareMic(); +#endif - xSemaphoreGive(start_dis); // 画面表示タスク スタート - xSemaphoreGive(start_fft); // フーリエ変換タスク スタート - while ((!M5.BtnA.isPressed()) && (!M5.BtnB.isPressed())) // ABボタン押していない間、くりかえす + // xSemaphoreGive(start_dis); // 画面表示タスク スタート + // xSemaphoreGive(start_fft); // フーリエ変換タスク スタート + M5.Display.setFont(&fonts::lgfxJapanGothic_16); + M5.Display.startWrite(); + M5.Display.clear(); + M5.Display.setTextColor( WHITE, TFT_BLACK ); + rec_data = (typeof(rec_data))heap_caps_malloc(record_size * sizeof(int16_t), MALLOC_CAP_8BIT); + memset(rec_data, 0, record_size * sizeof(int16_t)); + M5.Speaker.setVolume(132); // 0-255だが、あまり大きいと音が割れる + + while ((!M5.BtnA.isPressed())) // ABボタン押していない間、くりかえす { - xSemaphoreGive(start_dis); - xSemaphoreGive(start_fft); M5.update(); - xSemaphoreTake(start_dis, portMAX_DELAY); //  画面表示タスク 一時停止 - xSemaphoreTake(start_fft, portMAX_DELAY); // フーリエ変換タスク 一時停止 + if (M5.Mic.isEnabled()) + { + static constexpr int shift = 6; + auto data = &rec_data[rec_record_idx * record_length]; + if (M5.Mic.record(data, record_length, record_samplerate)) + { + data = &rec_data[draw_record_idx * record_length]; + + int32_t w = M5.Display.width(); + if (w > record_length - 1) + { + w = record_length - 1; + } + for (int32_t x = 0; x < w; ++x) + { + M5.Display.writeFastVLine(x, prev_y[x], prev_h[x], TFT_BLACK); // 以前の線を消す + int32_t y1 = (data[x] >> shift); + int32_t y2 = (data[x + 1] >> shift); + if (y1 > y2) + { + int32_t tmp = y1; + y1 = y2; + y2 = tmp; + } + int32_t y = (M5.Display.height() >> 1) + y1; + int32_t h = (M5.Display.height() >> 1) + y2 + 1 - y; + prev_y[x] = y; + prev_h[x] = h; + M5.Display.writeFastVLine(x, y, h, TFT_WHITE); + } + M5.Display.setCursor(0, 0); + M5.Display.print("●マイク録音モード:\nBボタンで最新の3秒間を再生"); + + M5.Display.display(); + + if (++draw_record_idx >= record_number) + { + draw_record_idx = 0; + } + if (++rec_record_idx >= record_number) + { + rec_record_idx = 0; + } + } + } + + // if (M5.BtnA.wasHold() || M5.BtnB.wasClicked()) + // { + // auto cfg = M5.Mic.config(); + // cfg.noise_filter_level = (cfg.noise_filter_level + 8) & 255; + // M5.Mic.config(cfg); + // M5.Display.setCursor(32,0); + // M5.Display.printf("nf:%03d", cfg.noise_filter_level); + // } + // else { + if (M5.BtnB.wasPressed()) + { + if (M5.Speaker.isEnabled()) + { + M5.Display.clear(); + while (M5.Mic.isRecording()) + { + M5.delay(1); + } + + /// Since the microphone and speaker cannot be used at the same time, turn off the microphone here. + M5.Mic.end(); + M5.delay(20); + M5.Speaker.begin(); + + // M5.Display.setCursor(0,0); + // M5.Display.print("再生中"); + int start_pos = rec_record_idx * record_length; + if (start_pos < record_size) + { + M5.Speaker.playRaw(&rec_data[start_pos], record_size - start_pos, record_samplerate, false, 1, 0); + } + if (start_pos > 0) + { + M5.Speaker.playRaw(rec_data, start_pos, record_samplerate, false, 1, 0); + } + Serial.println("Playing..."); + for (int sec = 3; sec > 0; sec--) + { + M5.Display.setCursor(0, 0); + M5.Display.printf("再生モード:\n 再生中 %d", sec); + M5.delay(1000); + } // ここを実行しているあいだに、playRawの内容が再生されている。 + + do + { + M5.delay(10); + M5.update(); + // Serial.println("waiting end of play"); + } while (M5.Speaker.isPlaying()); // まだ再生中だったら待つ + + // Reset I2S and reinitialize microphone + prepareMic(); + + M5.Display.clear(); + // M5.Display.setCursor(0,0); + // M5.Display.print("録音モード"); + + // } + } + } checkAXPPress(); } - // xSemaphoreTake( start_dis , portMAX_DELAY ); - // xSemaphoreTake( start_fft , portMAX_DELAY ); while ((M5.BtnA.isPressed()) || (M5.BtnB.isPressed())) // ABボタン押している間、くりかえす { M5.update(); checkAXPPress(); + M5.Display.endWrite(); + M5.Speaker.setVolume(45); mytone_switch(1000, 200); } } @@ -548,39 +674,16 @@ #define PIN_DATA 34 #ifdef ENABLE_I2S -bool InitI2SMicroPhone() // マイクの初期化 +void prepareMic() { - esp_err_t err = ESP_OK; - i2s_config_t i2s_config = { - .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM), - .sample_rate = 44100, - .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB - .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 = 128, - }; - - 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; - - err += i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); - err += i2s_set_pin(I2S_NUM_0, &pin_config); - err += i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); - // i2s_set_clk(0) - - if (err != ESP_OK) - { - return false; - } - else - { - return true; - } + // This function will reset the I2S peripheral to clear any existing issues with channel allocation. + M5.Speaker.end(); + delay(10); // Add a small delay to allow hardware reset + M5.Mic.begin(); // Reinitialize the microphone + auto cfg = M5.Mic.config(); + cfg.noise_filter_level = 128; + M5.Mic.config(cfg); + // Serial.println("resetI2S_end"); } #endif @@ -833,50 +936,6 @@ return crc; } -// ENV. II SENSORをつないだときに、温度と湿度がとれる -// int getTempAndHum(float *temp, float *hum) -// { -// static float _tempSave, _HUmSave; -// uint8_t databuff[6]; -// Wire.beginTransmission(0x44); -// Wire.write(0x2c); -// Wire.write(0x06); -// Wire.endTransmission(); -// Wire.requestFrom(0x44, 6); - -// for (int i = 0; i < 6; i++) -// { -// databuff[i] = Wire.read(); -// Serial.printf("%02X ", databuff[i]); -// } -// Serial.println("--"); - -// if (crc8(0x31, &databuff[0], 2) == databuff[2]) -// { -// uint16_t tempraw = databuff[0] << 8 | databuff[1]; -// *temp = -45 + 175 * (float(tempraw) / 65535.0); -// _tempSave = *temp; -// Serial.printf("Temp:%.2f ", *temp); -// } -// else -// { -// *temp = _tempSave; -// } - -// if (crc8(0x31, &databuff[3], 2) == databuff[5]) -// { -// uint16_t Humraw = databuff[3] << 8 | databuff[4]; -// *hum = 100 * (float(Humraw) / 65535.0); -// _HUmSave = *hum; -// Serial.printf("Hum:%.2f \n", *hum); -// } -// else -// { -// *hum = _HUmSave; -// } -// return 0; -// } - #ifdef ENABLE_IRSEND void DisIRSend() // 赤外線通信 画面表示 { @@ -1017,62 +1076,21 @@ } #endif -// void DisplayGroveSHT30() // SHT30=ENV. II SENSOR 温度と湿度 -// { -// float tempdata, humdata; -// uint8_t count = 0; - -// Wire.begin(32, 33); - -// while ((!M5.BtnA.isPressed()) && (!M5.BtnB.isPressed())) -// { -// Disbuff.fillRect(0, 0, 240, 135, TFT_BLACK); -// Disbuff.setSwapBytes(true); -// Disbuff.pushImage(180, 16, 48, 48, (uint16_t *)icon_ir); -// Disbuff.setTextColor(Disbuff.color565(180, 180, 180)); -// Disbuff.setTextSize(3); -// Disbuff.setCursor(12, 20); -// Disbuff.printf("IR Send "); - -// if (count >= 10) -// { -// count = 0; -// getTempAndHum(&tempdata, &humdata); // ENV. II SENSORをつないだときに、温度と湿度がとれる - -// Disbuff.setCursor(12, 50); -// Disbuff.printf("%.2f", tempdata); -// Disbuff.setCursor(12, 80); -// Disbuff.printf("%.2f", humdata); -// Disbuff.pushSprite(0, 0); -// } -// checkAXPPress(); -// M5.update(); -// M5.delay(100); -// count++; -// } -// while ((M5.BtnA.isPressed()) || (M5.BtnB.isPressed())) -// { -// M5.update(); -// checkAXPPress(); -// } -// M5.delay(50); -// Disbuff.setTextColor(TFT_WHITE); -// } void DisplayTestMode() // テストモード:ピンの電圧とバッテリー電圧 { float tempdata, humdata; uint8_t count_u = 0, count_t = 0; -#ifdef ENABLE_I2S - i2s_pin_config_t pin_config; - pin_config.bck_io_num = I2S_PIN_NO_CHANGE; - pin_config.ws_io_num = 33; - pin_config.data_out_num = I2S_PIN_NO_CHANGE; - pin_config.data_in_num = PIN_DATA; - i2s_set_pin(I2S_NUM_0, &pin_config); + // #ifdef ENABLE_I2S + // i2s_pin_config_t pin_config; + // pin_config.bck_io_num = I2S_PIN_NO_CHANGE; + // pin_config.ws_io_num = 33; + // pin_config.data_out_num = I2S_PIN_NO_CHANGE; + // pin_config.data_in_num = PIN_DATA; + // i2s_set_pin(I2S_NUM_0, &pin_config); - i2s_driver_uninstall(I2S_NUM_0); -#endif + // i2s_driver_uninstall(I2S_NUM_0); + // #endif gpio_reset_pin(GPIO_NUM_0); gpio_reset_pin(GPIO_NUM_26); @@ -1218,10 +1236,6 @@ mytone_switch(1000, 200); } Disbuff.setTextColor(TFT_WHITE); - -#ifdef ENABLE_I2S - InitI2SMicroPhone(); -#endif } esp_now_peer_info_t peerInfo; @@ -1653,14 +1667,14 @@ { // それぞれのテスト中は、関数のなかのループがまわる // A(orB)ボタンを押したら、現在実行中の関数のループを抜け、次の関数を実行する - MPU6886Test(); // 加速度・ジャイロ - DisplayRTC(); // リアルタイムクロック - // DisplayMicro(); // マイク + MPU6886Test(); // 加速度・ジャイロ + DisplayRTC(); // リアルタイムクロック + DisplayMicro(); // マイク #ifdef ENABLE_IRSEND DisIRSend(); // 赤外線通信 #endif -// DisplayTestMode(); // バッテリー電圧 + // DisplayTestMode(); // バッテリー電圧 #ifdef ENABLE_BLE DisPlayBLESend(); diff --git a/FactoryTest/wifi.ino b/FactoryTest/wifi.ino index b8d87a7..a66a9c9 100644 --- a/FactoryTest/wifi.ino +++ b/FactoryTest/wifi.ino @@ -13,9 +13,11 @@ WiFi.begin(ssid, password); // 接続開始 int count = 50; + M5.Speaker.tone(2000, 200); + M5.delay(500); while (WiFi.status() != WL_CONNECTED) { // 接続中... - M5.Speaker.tone(1000, 100); + M5.Speaker.tone(2000, 200); M5.delay(500); M5.Display.print("."); count--; @@ -25,7 +27,7 @@ if (count > 0) { // 接続完了!! - M5.Speaker.tone(2000, 1500); + M5.Speaker.tone(4000, 1500); M5.Display.fillScreen(GREEN); M5.Display.setCursor(0, 8, 4); M5.Display.setTextColor(BLACK, GREEN); @@ -56,7 +58,12 @@ { configTime(9 * 3600, 0, ntpserver); // NTPサーバからLocalTimeへの時刻同期 - M5.delay(5000); + M5.delay(2500); + for(int i = 0; i < 3; i++) + { + M5.Speaker.tone(1000, 200); + M5.delay(500); + } struct tm localTime; getLocalTime(&localTime); while (localTime.tm_hour == 0) @@ -64,10 +71,10 @@ getLocalTime(&localTime); // Serial.printf("%2d %2d %2d\n", localTime.tm_hour, localTime.tm_min, localTime.tm_sec); M5.Speaker.tone(1000, 200); - M5.delay(1000); + M5.delay(500); M5.Display.print("."); } - M5.Speaker.tone(2000, 500); + M5.Speaker.tone(2000, 1500); setRTCfromLT(localTime); // LocalTimeからRTCへの時刻同期 }