Передача аудиоданных с Arduino Nano 33 BLE Sense: Руководство по Chirp SDK
Компоненты и материалы
| Arduino Nano 33 BLE Sense | × | 1 |
О проекте
В Chirp мы с восторгом встретили новость о выпуске Arduino новой платы с множеством инновационных функций: широким набором датчиков, мощным процессором и, что самое важное, встроенным микрофоном. Команда Arduino предоставила нам предварительную версию Nano 33 BLE Sense, которая полностью совместима с Chirp, позволяя сообществу разработчиков передавать и принимать данные с помощью звука.
Chirp добавляет уникальный механизм передачи данных на платы Arduino. Возможности передачи данных через звук дают хакерам больше вариантов подключения. Основные преимущества:
- Независимость от устройств: данные можно отправлять из мобильных приложений, веб-страниц или даже аудиофайлов
- Один-ко-многим: любое устройство в радиусе слышимости получает данные за одну транзакцию
- Без настройки: не требует пары, паролей или начальной конфигурации
В этом руководстве мы покажем, как использовать Chirp SDK для отправки RGB-значения для изменения цвета встроенного светодиода. Chirp работает даже в шумных местах благодаря годам исследований, сделавшим декодер устойчивым к фоновым звукам.
Начало работы
Если вы еще не сделали этого, зарегистрируйтесь на developers.chirp.io. После регистрации вы получите ключ приложения, секрет и аудиоконфигурацию для вашего приложения.
Прием данных
Поскольку Nano 33 BLE Sense поставляется с встроенным микрофоном, для приема данных через Chirp нужен только Chirp SDK, доступный в менеджере библиотек.
- Откройте
Инструменты > Управление библиотеками - Найдите Chirp SDK и установите версию 3.3.0 или новее
- Откройте пример:
Файл > Примеры > ChirpSDK > Nano33SenseReceive - Скопируйте свои учетные данные для протокола 16khz-mono-embedded из developers.chirp.io в файл
credentials.h
Пример кода просто выводит принятые данные в Serial Monitor. Мы можем изменить поведение для управления встроенными светодиодами, отредактировав функцию onReceivedCallback.
Настройка GPIO для светодиодов
#define R_LED_PIN 22
#define G_LED_PIN 23
#define B_LED_PIN 24
void setup() {
pinMode(R_LED_PIN, OUTPUT);
pinMode(G_LED_PIN, OUTPUT);
pinMode(B_LED_PIN, OUTPUT);
}
Обработка принятых RGB-значений
void onReceivedCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) {
if (length > 0) {
// Высокие значения означают меньшую яркость, поэтому вычитаем из UINT8_MAX
analogWrite(R_LED_PIN, UINT8_MAX - payload[0]);
analogWrite(G_LED_PIN, UINT8_MAX - payload[1]);
analogWrite(B_LED_PIN, UINT8_MAX - payload[2]);
} else {
Serial.println("Decode failed");
}
}
Теперь можно протестировать код, воспроизводя аудиофайлы ниже — каждый должен менять цвет светодиода с красного на зеленый, затем на синий.
Что дальше?
Первая версия Chirp SDK для Arduino работает только с слышимым протоколом 16khz-mono-embedded. В ближайшие месяцы выйдет незримая версия на ультразвуковых частотах. Это позволит встраивать данные в существующий звук (музыку, видео) для триггеринга действий.
Мы также планируем больше руководств по использованию передачи данных через звук с Arduino. Делитесь своими проектами в Twitter @chirp или пишите на contact@chirp.io.
Полный код
/**--------------------------------------------------------------------
Пример приема данных с Arduino Nano 33 Sense.
@file Nano33SenseReceive.ino
@brief Создайте аккаунт разработчика на https://developers.chirp.io,
скопируйте ключ, секрет и конфигурацию для протокола "16khz-mono-embedded"
в определения chirp ниже.
Этот пример начинает слушать RGB-значения и менять цвет встроенного светодиода.
Схема: Arduino Nano 33 BLE
Copyright © 2011-2019, Asio Ltd. All rights reserved.
-------------------------------------------------------------------*/
#include <PDM.h>
#include "chirp_connect.h"
#define CHIRP_APP_KEY "YOUR_APP_KEY"
#define CHIRP_APP_SECRET "YOUR_APP_SECRET"
#define CHIRP_APP_CONFIG "YOUR_APP_CONFIG"
#define SAMPLE_RATE 16000
#define BUFFER_SIZE 256
#define R_LED_PIN 22
#define G_LED_PIN 23
#define B_LED_PIN 24
// Глобальные переменные
static chirp_connect_t *chirp = NULL;
short sampleBuffer[BUFFER_SIZE];
volatile int samplesRead;
// Прототипы функций
void setupChirp(void);
void chirpErrorHandler(chirp_connect_error_code_t code);
void onPDMdata(void);
void setup() {
Serial.begin(115200);
// while (!Serial);
pinMode(R_LED_PIN, OUTPUT);
pinMode(G_LED_PIN, OUTPUT);
pinMode(B_LED_PIN, OUTPUT);
setupChirp();
PDM.onReceive(onPDMdata);
PDM.setGain(30);
if (!PDM.begin(1, SAMPLE_RATE)) {
Serial.println("Failed to start PDM!");
while (1);
}
analogWrite(R_LED_PIN, UINT8_MAX);
analogWrite(G_LED_PIN, UINT8_MAX);
analogWrite(B_LED_PIN, UINT8_MAX);
}
void loop() {
if (samplesRead) {
chirp_connect_error_code_t err = chirp_connect_process_shorts_input(chirp, sampleBuffer, samplesRead);
chirpErrorHandler(err);
samplesRead = 0;
}
}
void onPDMdata() {
int bytesAvailable = PDM.available();
PDM.read(sampleBuffer, bytesAvailable);
samplesRead = bytesAvailable / sizeof(short);
}
// Chirp callbacks
void onReceivingCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) {
Serial.println("Receiving data...");
analogWrite(R_LED_PIN, UINT8_MAX);
analogWrite(G_LED_PIN, UINT8_MAX);
analogWrite(B_LED_PIN, UINT8_MAX);
}
void onReceivedCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) {
if (length) {
analogWrite(R_LED_PIN, UINT8_MAX - payload[0]);
analogWrite(G_LED_PIN, UINT8_MAX - payload[1]);
analogWrite(B_LED_PIN, UINT8_MAX - payload[2]);
} else {
analogWrite(R_LED_PIN, 0);
analogWrite(G_LED_PIN, UINT8_MAX);
analogWrite(B_LED_PIN, UINT8_MAX);
delay(500);
analogWrite(R_LED_PIN, UINT8_MAX);
delay(500);
analogWrite(R_LED_PIN, 0);
Serial.println("Decode failed");
}
}
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);
}
}
void setupChirp(void) {
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);
char *info = chirp_connect_get_info(chirp);
Serial.println(info);
chirp_connect_free(info);
chirp_connect_callback_set_t callback_set = {
.on_state_changed = NULL,
.on_sending = NULL,
.on_sent = NULL,
.on_receiving = onReceivingCallback,
.on_received = onReceivedCallback
};
err = chirp_connect_set_callbacks(chirp, callback_set);
chirpErrorHandler(err);
err = chirp_connect_set_input_sample_rate(chirp, SAMPLE_RATE);
chirpErrorHandler(err);
err = chirp_connect_set_frequency_correction(chirp, 1.0096);
chirpErrorHandler(err);
err = chirp_connect_start(chirp);
chirpErrorHandler(err);
Serial.println("Chirp SDK initialised.");
Serial.flush();
}
Производственный процесс
- Искусство и процесс производства виниловой пластинки LP
- Интеграция данных сенсоров в Raspberry Pi: практическое руководство
- Использование данных в Интернете надежности: стратегии эффективного управления
- IoT в эре Edge: рост, данные, безопасность и стратегия партнерств
- Подъем Индустрии 4.0: использование пограничной аналитики для более умного, быстрого производства
- Тип данных char в C++: объявление, ASCII и методы преобразования
- 8 распространённых типов утечек данных — реальные примеры и последствия
- Максимизация энергоэффективности завода с продвинутыми HMI
- Трансформация цифровых производственных команд с инсайтами реального времени
- Использование городских данных в реальном времени для инноваций в умных городах