Implemented oneshot adc reading

This commit is contained in:
2026-01-21 00:59:30 -06:00
parent 6734c369b8
commit f656f466e7
4 changed files with 104 additions and 34 deletions

View File

@@ -35,4 +35,5 @@ idf_component_register(
${APP_SOURCES} ${APP_SOURCES}
INCLUDE_DIRS INCLUDE_DIRS
. .
REQUIRES esp_adc
) )

View File

@@ -273,6 +273,45 @@ static void state_machine_loop(void)
} }
} }
void emgPrinter() {
TickType_t previousWake = xTaskGetTickCount();
while (1) {
emg_sample_t sample;
emg_sensor_read(&sample);
for (uint8_t i = 0; i < EMG_NUM_CHANNELS; i++) {
printf("%d", sample.channels[i]);
if (i != EMG_NUM_CHANNELS - 1) printf(" | ");
}
printf("\n");
vTaskDelayUntil(&previousWake, pdMS_TO_TICKS(100));
}
}
void appConnector() {
/* Create command queue */
g_cmd_queue = xQueueCreate(10, sizeof(command_t));
if (g_cmd_queue == NULL) {
printf("[ERROR] Failed to create command queue!\n");
return;
}
/* Launch serial input task */
xTaskCreate(
serial_input_task,
"serial_input",
4096, /* Stack size */
NULL, /* Parameters */
5, /* Priority */
NULL /* Task handle */
);
printf("[PROTOCOL] Waiting for host to connect...\n");
printf("[PROTOCOL] Send: {\"cmd\": \"connect\"}\n\n");
/* Run main state machine */
state_machine_loop();
}
/******************************************************************************* /*******************************************************************************
* Application Entry Point * Application Entry Point
******************************************************************************/ ******************************************************************************/
@@ -300,26 +339,6 @@ void app_main(void)
printf("[INIT] Done!\n\n"); printf("[INIT] Done!\n\n");
/* Create command queue */ emgPrinter();
g_cmd_queue = xQueueCreate(10, sizeof(command_t)); // appConnector();
if (g_cmd_queue == NULL) {
printf("[ERROR] Failed to create command queue!\n");
return;
}
/* Launch serial input task */
xTaskCreate(
serial_input_task,
"serial_input",
4096, /* Stack size */
NULL, /* Parameters */
5, /* Priority */
NULL /* Task handle */
);
printf("[PROTOCOL] Waiting for host to connect...\n");
printf("[PROTOCOL] Send: {\"cmd\": \"connect\"}\n\n");
/* Run main state machine */
state_machine_loop();
} }

View File

@@ -25,7 +25,7 @@
* Set to 1 while waiting for EMG sensors to arrive. * Set to 1 while waiting for EMG sensors to arrive.
* Set to 0 when ready to use real sensors. * Set to 0 when ready to use real sensors.
*/ */
#define FEATURE_FAKE_EMG 1 #define FEATURE_FAKE_EMG 0
/******************************************************************************* /*******************************************************************************
* GPIO Pin Definitions - Servos * GPIO Pin Definitions - Servos
@@ -63,7 +63,7 @@
* EMG Configuration * EMG Configuration
******************************************************************************/ ******************************************************************************/
#define EMG_NUM_CHANNELS 4 /**< Number of EMG sensor channels */ #define EMG_NUM_CHANNELS 1 /**< Number of EMG sensor channels */
#define EMG_SAMPLE_RATE_HZ 1000 /**< Samples per second per channel */ #define EMG_SAMPLE_RATE_HZ 1000 /**< Samples per second per channel */
/******************************************************************************* /*******************************************************************************

View File

@@ -8,6 +8,18 @@
#include "emg_sensor.h" #include "emg_sensor.h"
#include "esp_timer.h" #include "esp_timer.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "esp_err.h"
adc_oneshot_unit_handle_t adc1_handle;
adc_cali_handle_t cali_handle = NULL;
const uint8_t emg_channels[EMG_NUM_CHANNELS] = {ADC_CHANNEL_1};
/******************************************************************************* /*******************************************************************************
* Public Functions * Public Functions
@@ -19,10 +31,44 @@ void emg_sensor_init(void)
/* Seed random number generator for fake data */ /* Seed random number generator for fake data */
srand((unsigned int)esp_timer_get_time()); srand((unsigned int)esp_timer_get_time());
#else #else
/* TODO: Configure ADC channels when sensors arrive */ // 1. --- ADC Unit Setup ---
/* adc1_config_width(EMG_ADC_WIDTH); */ adc_oneshot_unit_init_cfg_t init_config1 = {
/* adc1_config_channel_atten(ADC_EMG_CH0, EMG_ADC_ATTEN); */ .unit_id = ADC_UNIT_1,
/* ... */ .ulp_mode = ADC_ULP_MODE_DISABLE,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
// 2. --- ADC Channel Setup (GPIO 1?) ---
// Ensure the channel matches your GPIO in pinmap. For ADC1, GPIO1 is usually not CH0.
// Check your datasheet! (e.g., on S3, GPIO 1 is ADC1_CH0)
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT, // 12-bit for S3
.atten = ADC_ATTEN_DB_12, // Allows up to ~3.1V
};
for (uint8_t i = 0; i < EMG_NUM_CHANNELS; i++)
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, emg_channels[i], &config));
// 3. --- Calibration Setup (CORRECTED for S3) ---
// ESP32-S3 uses Curve Fitting, not Line Fitting
adc_cali_curve_fitting_config_t cali_config = {
.unit_id = ADC_UNIT_1,
.atten = ADC_ATTEN_DB_12,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &cali_handle));
// while (1) {
// int raw_val, voltage_mv;
// // Read Raw
// ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_1, &raw_val));
// // Convert to mV using calibration
// ESP_ERROR_CHECK(adc_cali_raw_to_voltage(cali_handle, raw_val, &voltage_mv));
// printf("Raw: %d | Voltage: %d mV\n", raw_val, voltage_mv);
// vTaskDelay(pdMS_TO_TICKS(500));
// }
#endif #endif
} }
@@ -33,19 +79,23 @@ void emg_sensor_read(emg_sample_t *sample)
#if FEATURE_FAKE_EMG #if FEATURE_FAKE_EMG
/* /*
* Generate fake EMG data: * Generate fake EMG data:
* - Base value around 512 (middle of 10-bit range, matching Python sim) * - Base value around 1650 (middle of 3.3V millivolt range)
* - Random noise of +/- 50 * - Random noise of +/- 50
* - Mimics real EMG baseline noise * - Mimics real EMG baseline noise
*/ */
for (int i = 0; i < EMG_NUM_CHANNELS; i++) { for (int i = 0; i < EMG_NUM_CHANNELS; i++) {
int noise = (rand() % 101) - 50; /* -50 to +50 */ int noise = (rand() % 101) - 50; /* -50 to +50 */
sample->channels[i] = (uint16_t)(512 + noise); sample->channels[i] = (uint16_t)(1650 + noise);
} }
#else #else
/* TODO: Real ADC reads when sensors arrive */ int raw_val, voltage_mv;
/* sample->channels[0] = adc1_get_raw(ADC_EMG_CH0); */ for (uint8_t i = 0; i < EMG_NUM_CHANNELS; i++) {
/* sample->channels[1] = adc1_get_raw(ADC_EMG_CH1); */ ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, emg_channels[i], &raw_val));
/* ... */ ESP_ERROR_CHECK(adc_cali_raw_to_voltage(cali_handle, raw_val, &voltage_mv));
sample->channels[i] = (uint16_t) voltage_mv;
}
printf("\n");
#endif #endif
} }