4662| 1
|
[项目] 使用Chirp进行声波通信 |
Chirp是一个很有趣的应用,他可以利用声波进行通信,Chirp使您的应用程序可以使用声音发送和接收信息。Chirp将字节数组编码为音频信号,可以由任何带扬声器的设备发送,并由具有麦克风和Chirp SDK的任何设备接收。它设计为在几米的距离内,以及在嘈杂的日常环境中坚固耐用。由于传输完全通过音频信号进行,因此不需要互联网连接或提前配对,并且听觉范围内的任何设备都可以接收数据。 打开Arduino IDE,添加ChirpSDK的库文件,Chirp的示例中自带了一个ESP32的接收程序,程序中使用的麦克风型号为SPH0645,而M5StickC内置的I2S麦克风为SPM1423 因此需要改造,将接收到的声音内容显示到屏幕上 [mw_shl_code=c,true]#include <M5StickC.h> #include <driver/i2s.h> #include "efontEnableAll.h" #include "efont.h" #include "efontM5StickC.h" #include "chirp_connect.h" #include "credentials.h" #define PIN_CLK 0 #define PIN_DATA 34 #define LED_PIN 10 // Pin number for on-board LED #define BUFFER_SIZE 512 // Audio buffer size #define SAMPLE_RATE 16000 // Audio sample rate #define MIC_CALIBRATION 13125 #define CONVERT_INPUT(sample) (((int32_t)(sample) >> 14) + MIC_CALIBRATION) // Global variables ------------------------------------------------------------ static chirp_connect_t *chirp = NULL; static chirp_connect_state_t currentState = CHIRP_CONNECT_STATE_NOT_CREATED; static bool startTasks = false; // Function definitions -------------------------------------------------------- void setupChirp(); void chirpErrorHandler(chirp_connect_error_code_t code); void setupAudioInput(int sample_rate); // Function declarations ------------------------------------------------------- void setup() { M5.begin(); M5.Lcd.setRotation(1); M5.Lcd.fillScreen(BLACK); delay(500); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); Serial.begin(115200); Serial.printf("Heap size: %u\n", ESP.getFreeHeap()); xTaskCreate(initTask, "initTask", 16384, NULL, 1, NULL); } void loop() { esp_err_t audioError; chirp_connect_error_code_t chirpError; if (startTasks) { xTaskCreate(processInputTask, "processInputTask", 16384, NULL, 5, NULL); startTasks = false; } } // RTOS Tasks ------------------------------------------------------------------ void initTask(void *parameter) { setupChirp(); chirp_connect_error_code_t chirpError = chirp_connect_set_input_sample_rate(chirp, SAMPLE_RATE); chirpErrorHandler(chirpError); setupAudioInput(SAMPLE_RATE); Serial.printf("Heap size: %u\n", ESP.getFreeHeap()); startTasks = true; vTaskDelete(NULL); } void processInputTask(void *parameter) { esp_err_t audioError; chirp_connect_error_code_t chirpError; size_t bytesLength = 0; float buffer[BUFFER_SIZE] = {0}; int32_t ibuffer[BUFFER_SIZE] = {0}; while (currentState >= CHIRP_CONNECT_STATE_RUNNING) { audioError = i2s_read(I2S_NUM_0, ibuffer, BUFFER_SIZE * 4, &bytesLength, portMAX_DELAY); if (bytesLength) { for (int i = 0; i < bytesLength / 4; i++) { buffer = (float) CONVERT_INPUT(ibuffer); } chirpError = chirp_connect_process_input(chirp, buffer, bytesLength / 4); chirpErrorHandler(chirpError); } } vTaskDelete(NULL); } // Chirp ----------------------------------------------------------------------- void onStateChangedCallback(void *chirp, chirp_connect_state_t previous, chirp_connect_state_t current) { currentState = current; Serial.printf("State changed from %d to %d\n", previous, current); } void onReceivingCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) { Serial.println("Receiving data..."); digitalWrite(LED_PIN, HIGH); } void onReceivedCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) { if (payload) { char *data = (char *)calloc(length + 1, sizeof(uint8_t)); memcpy(data, payload, length * sizeof(uint8_t)); Serial.print("Received data: "); Serial.println(data); // text print M5.Lcd.fillScreen(BLACK); M5.Lcd.setTextSize(2); printEfont(data, 5, 10); free(data); } else { Serial.println("Decode failed."); } } void setupChirp() { chirp = new_chirp_connect(CHIRP_APP_KEY, CHIRP_APP_SECRET); if (chirp == NULL) { Serial.println("Chirp initialisation failed."); return; } chirp_connect_error_code_t err = chirp_connect_set_config(chirp, CHIRP_APP_CONFIG); chirpErrorHandler(err); chirp_connect_callback_set_t callbacks = {0}; callbacks.on_state_changed = onStateChangedCallback; callbacks.on_receiving = onReceivingCallback; callbacks.on_received = onReceivedCallback; err = chirp_connect_set_callbacks(chirp, callbacks); chirpErrorHandler(err); err = chirp_connect_set_callback_ptr(chirp, chirp); chirpErrorHandler(err); err = chirp_connect_start(chirp); chirpErrorHandler(err); Serial.println("Chirp Connect initialised."); } void chirpErrorHandler(chirp_connect_error_code_t code) { if (code != CHIRP_CONNECT_OK) { const char *error_string = chirp_connect_error_code_to_string(code); Serial.println(error_string); exit(42); } } // I2S Audio ------------------------------------------------------------------- void setupAudioInput(int sample_rate) { i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM), .sample_rate = sample_rate, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // is fixed at 12bit, stereo, MSB .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, .communication_format = I2S_COMM_FORMAT_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 8, .dma_buf_len = 64, }; 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_sample_rates(I2S_NUM_0, sample_rate); i2s_set_clk(I2S_NUM_0, sample_rate, I2S_BITS_PER_SAMPLE_32BIT, I2S_CHANNEL_MONO); }[/mw_shl_code] 在credentials.h中,定义了APP_KEY, APP_SECRET和 APP_CONFIG,这些需要修改为自己的参数,另外#15行代码需要注释掉。 |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed