2641浏览
查看: 2641|回复: 1

[项目] 使用Chirp进行声波通信

[复制链接]
使用Chirp进行声波通信图1

Chirp是一个很有趣的应用,他可以利用声波进行通信,Chirp使您的应用程序可以使用声音发送和接收信息。Chirp将字节数组编码为音频信号,可以由任何带扬声器的设备发送,并由具有麦克风和Chirp SDK的任何设备接收。它设计为在几米的距离内,以及在嘈杂的日常环境中坚固耐用。由于传输完全通过音频信号进行,因此不需要互联网连接或提前配对,并且听觉范围内的任何设备都可以接收数据。
使用Chirp进行声波通信图2

打开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]


使用Chirp进行声波通信图3

credentials.h中,定义了APP_KEY, APP_SECRET和 APP_CONFIG,这些需要修改为自己的参数,另外#15行代码需要注释掉。


gada888  版主

发表于 2019-9-13 09:11:38

有空试一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail