Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Recent changes to the [Chirp Arduino SDK](https://developers.chirp.io/docs).

## v3.3.0 (09/08/2019)

- Added support for cortex-m4 (Nano 33 Sense)
- Added send-only support for cortex-m0plus (MKRZero, MKR Vidor 4000)
- Build v3.3.0-rc1
Expand Down
30 changes: 18 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,26 @@
Chirp is a library enabling Arduino-based devices to send and receive data using sound. You'll need:

* A compatible Arduino board
* A digital I2S MEMS microphone
* A digital I2S MEMS microphone (if your board does not contain a microphone)
* A digital I2S amplifier and compatible speaker

For sound input you will need a digital MEMS microphone such as the SPH0645 or ICS-43434. (Not necessary for the Nano 33 Sense as it comes with an on board microphone)
For sound output it is recommended to use a digital I2S output such as the UDA1334A or MAX98357A connected to a compatible speaker.
For receiving data, you will need a digital MEMS microphone. Some boards (for example, the Nano 33 Sense and Microsoft MXChip) already include a MEMS mic so you are good to go. For others, you will need an external mic such as the [SPH0645](https://www.adafruit.com/product/3421) or [ICS-43434](https://www.mouser.co.uk/ProductDetail/TDK-InvenSense/ICS-43434?qs=u4fy%2FsgLU9PAgmWRI7%252BqXA%3D%3D).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About the second microphone, do we really want to suggest people a microphone no even mounted on a small board ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only tested with SPH0645, but other people have suggested ICS as an alternative

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against but the link suggest a microphone which is not mounted on anything :/


You can quickly test the sound input by playing random chirps from the [Developer Hub](https://developers.chirp.io).
The easiest way to test the sound output would be to use Chirp on the [command line](https://developers.chirp.io/docs/tutorials/command-line) to receive data from the Arduino.
For sending data, we recommend using a digital I2S audio output such as the [UDA1334A](https://www.adafruit.com/product/3678) or [MAX98357A](https://www.adafruit.com/product/3006), connected to a compatible speaker.

You can quickly test that your device is receiving chirps by playing some random test signals from the [Developer Hub](https://developers.chirp.io).

To test whether your device is sending chirps OK, we recommend setting up the [Python command-line tools](https://developers.chirp.io/docs/tutorials/command-line) to receive data from the Arduino.

## Supported hardware

Send and receive capabilities
The following Arduino-compatible boards are able to both send and receive chirps:

* Arduino Nano 33 Sense
* Microsoft MXChip
* ESP32

Send only
The following Arduino-compatible boards are only able to send chirps, as they are not able to do on-chip DSP:

* Arduino MKRZero
* Arduino Vidor 4000
Expand All @@ -36,17 +38,21 @@ Send only

Chirp is written for the Arduino IDE versions 1.8.6 and above.

Install ChirpSDK as a library. For instructions, see
Install ChirpSDK as a library using "Manage Libraries". For instructions, see

[http://arduino.cc/en/Guide/Libraries](http://arduino.cc/en/Guide/Libraries)

Once installed, you can access the example programs from the menu :
Once installed, you can access the example programs from the menu:

```File > Examples > ChirpSDK > Example ```
```
File > Examples > ChirpSDK > Example
```

and you can include the headers to use Chirp in your own code by adding :
and you can include the headers to use Chirp in your own code by adding:

```#include "chirp_connect.h"```
```
#include "chirp_connect.h"
```

## Usage

Expand Down
90 changes: 48 additions & 42 deletions examples/ESP32Receive/ESP32Receive.ino
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**-----------------------------------------------------------------------------

Example code to receive data using ESP32 and SPH0645 microphone
Example code using the Chirp SDK to receive data using ESP32 and
SPH0645 microphone

@file ESP32Receive.ino

Expand All @@ -27,19 +28,20 @@
#define I2SI_BCK 14 // I2S BCLK on GPIO14
#define I2SI_LRCL 15 // I2S SELECT on GPIO15

#define LED_PIN 2 // LED
#define SWITCH_PIN 0 // Switch
#define LED_PIN 2 // Pin number for on-board LED
#define SWITCH_PIN 0 // Pin number for on-board switch

#define BUFFER_SIZE 512
#define MIC_CALIBRATION 13125
#define SAMPLE_RATE 16000
#define BUFFER_SIZE 512 // Audio buffer size
#define SAMPLE_RATE 16000 // Audio sample rate

/**
Convert I2S input data.
Data is 18 bit signed, MSBit first, two's complement.
The calibration value is determined using the Serial
Plotter to centre the audio about zero.
The MIC_CALIBRATION value is determined using the Serial
Plotter to centre the audio about zero. The below value
should be correct for most ESP32 boards.
*/
#define MIC_CALIBRATION 13125
#define CONVERT_INPUT(sample) (((int32_t)(sample) >> 14) + MIC_CALIBRATION)

// Global variables ------------------------------------------------------------
Expand All @@ -56,8 +58,7 @@ void setupAudioInput(int sample_rate);

// Function declarations -------------------------------------------------------

void
setup()
void setup()
{
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Expand All @@ -68,35 +69,34 @@ setup()
xTaskCreate(initTask, "initTask", 16384, NULL, 1, NULL);
}

void
loop()
void loop()
{
esp_err_t audioError;
chirp_connect_error_code_t chirpError;

if (startTasks) {
if (startTasks)
{
xTaskCreate(processInputTask, "processInputTask", 16384, NULL, 5, NULL);
startTasks = false;
}
}

// RTOS Tasks ------------------------------------------------------------------

void
initTask(void *parameter)
void initTask(void *parameter)
{
setupChirp();

uint32_t input_sample_rate = chirp_connect_set_input_sample_rate(chirp, SAMPLE_RATE);
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)
void processInputTask(void *parameter)
{
esp_err_t audioError;
chirp_connect_error_code_t chirpError;
Expand All @@ -105,11 +105,14 @@ processInputTask(void *parameter)
float buffer[BUFFER_SIZE] = {0};
int32_t ibuffer[BUFFER_SIZE] = {0};

while (currentState >= CHIRP_CONNECT_STATE_RUNNING) {
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[i] = (float)CONVERT_INPUT(ibuffer[i]);
if (bytesLength)
{
for (int i = 0; i < bytesLength / 4; i++)
{
buffer[i] = (float) CONVERT_INPUT(ibuffer[i]);
}

chirpError = chirp_connect_process_input(chirp, buffer, bytesLength / 4);
Expand All @@ -121,39 +124,39 @@ processInputTask(void *parameter)

// Chirp -----------------------------------------------------------------------

void
onStateChangedCallback(void *chirp, chirp_connect_state_t previous, chirp_connect_state_t current)
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)
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)
void onReceivedCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel)
{
if (payload) {
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);
free(data);
} else {
}
else
{
Serial.println("Decode failed.");
}
}

void
setupChirp()
void setupChirp()
{
chirp = new_chirp_connect(CHIRP_APP_KEY, CHIRP_APP_SECRET);
if (chirp == NULL) {
if (chirp == NULL)
{
Serial.println("Chirp initialisation failed.");
return;
}
Expand All @@ -178,8 +181,7 @@ setupChirp()
Serial.println("Chirp Connect initialised.");
}

void
chirpErrorHandler(chirp_connect_error_code_t code)
void chirpErrorHandler(chirp_connect_error_code_t code)
{
if (code != CHIRP_CONNECT_OK)
{
Expand All @@ -191,16 +193,16 @@ chirpErrorHandler(chirp_connect_error_code_t code)

// I2S Audio -------------------------------------------------------------------

void
setupAudioInput(int sample_rate)
void setupAudioInput(int sample_rate)
{
/*
Set up I2S audio for SPH0645 microphone
*/
esp_err_t err;
Serial.println("Initialising audio input driver..");

const i2s_config_t i2s_config = {
const i2s_config_t i2s_config =
{
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = sample_rate,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
Expand All @@ -212,27 +214,31 @@ setupAudioInput(int sample_rate)
.use_apll = true
};

const i2s_pin_config_t pin_config = {
const i2s_pin_config_t pin_config =
{
.bck_io_num = I2SI_BCK,
.ws_io_num = I2SI_LRCL,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2SI_DATA
};

err = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
if (err != ESP_OK) {
if (err != ESP_OK)
{
Serial.printf("Failed installing driver: %d\n", err);
while (true);
}

err = i2s_set_pin(I2S_NUM_0, &pin_config);
if (err != ESP_OK) {
if (err != ESP_OK)
{
Serial.printf("Failed setting pin: %d\n", err);
while (true);
}

err = i2s_set_sample_rates(I2S_NUM_0, sample_rate);
if (err != ESP_OK) {
if (err != ESP_OK)
{
Serial.printf("Failed to set sample rates: %d\n", err);
while (true);
}
Expand Down
Loading