查看: 1489|回复: 0

使用Chirp进行声波通信

[复制链接]

该用户从未签到

发表于 2019-9-12 11:17 | 显示全部楼层 |阅读模式
uploads2ftmp2f83ce6e91-c52b-4083-a35d-3e9e64a902042fe59bb31_rkH1TSwDdJ.jpeg
Chirp是一个很有趣的应用,他可以利用声波进行通信,Chirp使您的应用程序可以使用声音发送和接收信息。Chirp将字节数组编码为音频信号,可以由任何带扬声器的设备发送,并由具有麦克风和Chirp SDK的任何设备接收。它设计为在几米的距离内,以及在嘈杂的日常环境中坚固耐用。由于传输完全通过音频信号进行,因此不需要互联网连接或提前配对,并且听觉范围内的任何设备都可以接收数据。
截屏2019-09-1210.23.06.png
打开Arduino IDE,添加ChirpSDK的库文件,Chirp的示例中自带了一个ESP32的接收程序,程序中使用的麦克风型号为SPH0645,而M5StickC内置的I2S麦克风为SPM1423 因此需要改造,将接收到的声音内容显示到屏幕上


[mw_shl_code=arduino,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]

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

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

本版积分规则

热门推荐

【干货分享】mega2560原理图PCB图纸altium designer18
【干货分享】mega2560原理
分享一下mega2560的板子 AD版本 **** 本内容被作者隐藏 **** ergo
小度app不能连接<已解决>
小度app不能连接<已解决>
用的是点灯2.7.1,已经没有阿里broker了。所以就加了Arduino设备。 点灯app没有问题可
MAX6675模块+K型热电偶因为导线长短出现的测温不准问题
MAX6675模块+K型热电偶因
MAX6675模块+K型热电偶因为导线长短出现的测温不准问题.搞了好多天了,找不到原因。MA
智能家居之震动闹钟
智能家居之震动闹钟
[md]## 简介 blinker设备端SDK已经集成了定时控制功能,用户只需要添加定时组件到设备
家居之氛围灯
家居之氛围灯
[md]## 简介 Wifiduino接入云服务器后,我们可以通过已经联网的智能音箱发送指令来控
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表