i intend to upload the code to a ESP32-C3 board. the objective of this code is to command the arduino to give input to a servo motor, stepper motor, ultrasonic sensor, to build an AI audio classifier smart dust bin.
#include <Arduino.h>
#include <driver/i2s.h>
#include <AccelStepper.h>
#include <ESP32Servo.h> // Library for Servo motor on ESP32
#include <Edge_AI_Recycle_Bin_inferencing.h>
/** Audio buffers, pointers and selectors */
typedef struct {
int16_t *buffer;
uint8_t buf_ready;
uint32_t buf_count;
uint32_t n_samples;
} inference_t;
static inference_t inference;
static int16_t sampleBuffer[2048];
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
AccelStepper stepper1(1, 2, 3); // Adjust pins as needed for your stepper motor
Servo trapdoor; // Servo motor object for ESP32
const int HALL = 5; // Hall sensor pin
int compartment[] = {925, 2775, 0, 4625, 6475}; // Compartment positions based on model (Bottle, Can, Noise, Paper, Ping-pong)
float threshold = 0.8;
int selected = 2; // Default as Noise
void setupI2SMicrophone() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 1024,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = 25, // Adjust pins as needed
.ws_io_num = 32, // Adjust pins as needed
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = 33 // Adjust pins as needed
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
pinMode(HALL, INPUT);
trapdoor.attach(A5); // Attach servo to pin A5
// Stepper motor calibration
stepper1.setMaxSpeed(2000); // Set maximum speed value for the stepper
stepper1.setAcceleration(1000); // Set acceleration value for the stepper
while(digitalRead(HALL)){
stepper1.setSpeed(-400); // Set the current position to 0 steps
stepper1.runSpeed();
Serial.println("Homing...");
}
delay(100);
stepper1.setCurrentPosition(0);
// End of stepper motor calibration
// Servo motor calibration
for (int pos = 11; pos <= 90; pos += 1) { // Goes from 0 degrees to 180 degrees in steps of 1 degree
trapdoor.write(pos); // Tell servo to go to position in variable 'pos'
delay(20); // Waits 20 ms for the servo to reach the position
}
for (int pos = 90; pos >= 11; pos -= 1) { // Goes from 180 degrees to 0 degrees in steps of -1 degree
trapdoor.write(pos); // Tell servo to go to position in variable 'pos'
delay(20); // Waits 20 ms for the servo to reach the position
}
delay(500); // Delay so the sound of servo is not captured
Serial.println("Edge Impulse Inferencing Demo");
// Summary of inferencing settings
ei_printf("Inferencing settings:\n");
ei_printf("\tInterval: %.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS);
ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
ei_printf("\tSample length: %d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16);
ei_printf("\tNo. of classes: %d\n", sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0]));
if (!microphone_inference_start(EI_CLASSIFIER_RAW_SAMPLE_COUNT)) {
ei_printf("ERR: Could not allocate audio buffer (size %d), this could be due to the window length of your model\r\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT);
return;
}
}
void captureAudio() {
size_t bytesRead;
i2s_read(I2S_NUM_0, &sampleBuffer, sizeof(sampleBuffer), &bytesRead, portMAX_DELAY);
// Process the audio samples and run inference
}
static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr) {
for (size_t i = 0; i < length; i++) {
out_ptr[i] = (float)sampleBuffer[offset + i] / 32768.0f;
}
return 0;
}
void loop() {
captureAudio();
signal_t signal;
signal.total_length = sizeof(sampleBuffer) / sizeof(sampleBuffer[0]);
signal.get_data = µphone_audio_signal_get_data;
ei_impulse_result_t result = { 0 };
EI_IMPULSE_ERROR r = run_classifier(&signal, &result, debug_nn);
if (r != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", r);
return;
}
// Print the predictions
ei_printf("Predictions ");
ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
ei_printf(": \n");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
if (result.classification[ix].value > threshold){
ei_printf("\nYOUR TRASH IS: %s\n", result.classification[ix].label);
selected = ix;
}
}
// Control stepper motor and servo based on classification
if (selected >= 0 && selected < sizeof(compartment) / sizeof(compartment[0])) {
stepper1.moveTo(compartment[selected]);
stepper1.runToPosition();
for (int pos = 11; pos <= 90; pos += 1) { // Goes from 0 degrees to 180 degrees in steps of 1 degree
trapdoor.write(pos); // Tell servo to go to position in variable 'pos'
delay(20); // Waits 20 ms for the servo to reach the position
}
for (int pos = 90; pos >= 11; pos -= 1) { // Goes from 180 degrees to 0 degrees in steps of -1 degree
trapdoor.write(pos); // Tell servo to go to position in variable 'pos'
delay(20); // Waits 20 ms for the servo to reach the position
}
delay(500); // Delay after action
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(" anomaly score: %.3f\n", result.anomaly);
#endif
}
static bool microphone_inference_start(uint32_t n_samples) {
inference.buffer = (int16_t *)malloc(n_samples * sizeof(int16_t));
if (inference.buffer == NULL) {
return false;
}
inference.buf_count = 0;
inference.n_samples = n_samples;
inference.buf_ready = 0;
// Configure the data receive callback
PDM.onReceive(&pdm_data_ready_inference_callback);
PDM.setBufferSize(4096);
// Initialize PDM with:
// - one channel (mono mode)
// - a 16 kHz sample rate
if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) {
ei_printf("Failed to start PDM!");
microphone_inference_end();
return false;
}
// Set the gain, defaults to 20
PDM.setGain(80);
return true;
}
static void pdm_data_ready_inference_callback(void) {
int bytesAvailable = PDM.available();
int bytesRead = PDM.read((char *)&sampleBuffer[0], bytesAvailable);
if (inference.buf_ready == 0) {
for (int i = 0; i < bytesRead >> 1; i++) {
inference.buffer[inference.buf_count++] = sampleBuffer[i];
if (inference.buf_count >= inference.n_samples) {
inference.buf_count = 0;
inference.buf_ready = 1;
break;
}
}
}
}
static bool microphone_inference_record(void) {
inference.buf_ready = 0;
inference.buf_count = 0;
return true;
}
static void microphone_inference_end(void) {
free(inference.buffer);
inference.buffer = NULL;
}
i have got this new code for ESP32-C3 (i didn't get to use the nano 33 BLE sense, tried every thing until i gave up-The code was compiling though) and i am having errors while trying to compile it. i need help to correcting the code. this is my first time dealing with this