Skip to content
Open
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
29 changes: 17 additions & 12 deletions main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
* ==========================================
*/

// Approximate full-scale voltages for ESP32C6/ESP32 ADC attenuations
// 0dB: ~950mV, 2.5dB: ~1250mV, 6dB: ~1750mV, 11dB: ~3100mV+ (use 3.3V)
// ADC now sends calibrated millivolts directly from firmware
// Max voltage range depends on attenuation setting
/** @type {number[]} */
const ATTEN_TO_MAX_V = [0.95, 1.25, 1.75, 3.3];
const ATTEN_TO_MAX_MV = [1000, 1300, 1900, 3300];

// Data buffer size
/** @type {number} */
Expand Down Expand Up @@ -49,7 +49,7 @@ let activeConfig = {

/** @type {LowRateState} */
let lowRateState = {
accMin: 4096,
accMin: 3300,
accMax: 0,
accSum: 0,
accCount: 0,
Expand Down Expand Up @@ -155,11 +155,12 @@ function getTotalTimeMs() {
}

/**
* Helper to get max voltage
* @returns {number} Max voltage stored in ATTEN_TO_MAX_V or 3.3
* Helper to get max voltage in volts
* @returns {number} Max voltage in volts
*/
function getMaxVoltage() {
return ATTEN_TO_MAX_V[activeConfig.atten] || 3.3;
// Firmware sends millivolts, convert to volts
return (ATTEN_TO_MAX_MV[activeConfig.atten] || 3100) / 1000;
}

/**
Expand Down Expand Up @@ -306,7 +307,7 @@ function processData(newData) {
});

// Reset Min/Max/Sum for next window
lowRateState.accMin = 4096;
lowRateState.accMin = 3300;
lowRateState.accMax = 0;
lowRateState.accSum = 0;
lowRateState.accCount = 0;
Expand Down Expand Up @@ -472,14 +473,18 @@ function draw() {
const h = canvas.height;
ctx.clearRect(0, 0, w, h);

const maxAdcVal = 4096; // 12-bit fixed scale
// Use the actual max millivolts for current attenuation (not 3300)
const maxAdcVal = ATTEN_TO_MAX_MV[activeConfig.atten] || 3100;

// Trigger values
let drawIdx = dataBuffer.length - w;
if (drawIdx < 0)
drawIdx = 0;
else {
const triggerVal = (4096 - (parseInt(triggerLevel.value) || 2048));
// Convert trigger level from slider (0-4095) to millivolts (0-maxAdcVal)
// Slider is inverted: 0 = top (max mV), 4095 = bottom (0mV)
const sliderVal = parseInt(triggerLevel.value) || 2048;
const triggerVal = Math.round((1 - sliderVal / 4095) * maxAdcVal);

// Helper to extract value for trigger (handles numbers and avg objects)
const getVal = (i) => {
Expand All @@ -505,7 +510,7 @@ function draw() {
}
}

const triggerVolts = ((maxAdcVal - activeConfig.trigger) * getMaxVoltage() / maxAdcVal).toFixed(2) + "V";
const triggerVolts = (triggerVal / 1000).toFixed(2) + "V";
const triggerDir = triggerLevel.invert ? '&#x1F809;' : '&#x1F80B;';
if (drawIdx < 0) {
drawIdx = dataBuffer.length - w;
Expand Down Expand Up @@ -781,7 +786,7 @@ function setParams() {
body: JSON.stringify(payload)
}).then(res => {
if (res.ok) {
lowRateState.accMin = 4096;
lowRateState.accMin = 3300;
lowRateState.accMax = 0;
lowRateState.accSum = 0;
lowRateState.accCount = 0;
Expand Down
66 changes: 62 additions & 4 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "esp_event.h"
#include "esp_http_server.h"
#include "esp_log.h"
Expand Down Expand Up @@ -35,9 +37,7 @@ static void start_webserver(void);

// ADC Configuration
#define ADC_UNIT ADC_UNIT_1
#define ADC_UNIT ADC_UNIT_1
#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1
#define ADC_ATTEN ADC_ATTEN_DB_11
#define ADC_BIT_WIDTH ADC_BITWIDTH_12

#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
Expand All @@ -51,6 +51,7 @@ static bool is_ap = false;
#define ADC_READ_LEN 4096

static adc_continuous_handle_t adc_handle = NULL;
static adc_cali_handle_t cali_handle = NULL;

// Single client support for simplicity, or use a list for multiple
static int s_ws_client_fd = -1;
Expand Down Expand Up @@ -80,6 +81,43 @@ static uint32_t get_optimal_buffer_size(uint32_t sample_rate) {
return (target_size + 3) & ~3;
}

/*
* Initialize ADC calibration using chip-specific eFuse data
*/
static void init_adc_calibration(void) {
if (cali_handle != NULL) {
ESP_LOGW(TAG, "ADC calibration already initialized");
return;
}

adc_cali_curve_fitting_config_t cali_config = {
.unit_id = ADC_UNIT,
.atten = s_atten,
.bitwidth = s_bit_width,
};

esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_config, &cali_handle);
if (ret == ESP_OK) {
ESP_LOGI(TAG, "ADC calibration initialized successfully (atten=%d, bitwidth=%d)",
s_atten, s_bit_width);
} else {
ESP_LOGW(TAG, "ADC calibration failed: %s - using raw values with fallback conversion",
esp_err_to_name(ret));
cali_handle = NULL;
}
}

/*
* Deinitialize ADC calibration
*/
static void deinit_adc_calibration(void) {
if (cali_handle != NULL) {
adc_cali_delete_scheme_curve_fitting(cali_handle);
cali_handle = NULL;
ESP_LOGI(TAG, "ADC calibration deinitialized");
}
}

/*
* Task to read from ADC Continuous driver
*/
Expand All @@ -97,9 +135,16 @@ static void adc_read_task(void* arg) {
&adc_handle);
ESP_ERROR_CHECK(adc_continuous_start(adc_handle));

// Initialize ADC calibration
init_adc_calibration();

while (1) {
if (s_reconfig_needed) {
ESP_LOGI(TAG, "Reconfiguring ADC...");

// Deinitialize ADC calibration before reconfiguring
deinit_adc_calibration();

if (adc_handle) {
ESP_LOGI(TAG, "Stopping ADC...");
ret = adc_continuous_stop(adc_handle);
Expand All @@ -126,6 +171,10 @@ static void adc_read_task(void* arg) {

ESP_LOGI(TAG, "Starting ADC...");
ESP_ERROR_CHECK(adc_continuous_start(adc_handle));

// Reinitialize ADC calibration with new settings
init_adc_calibration();

ESP_LOGI(TAG, "ADC Reconfigured and Restarted");
s_reconfig_needed = false;
}
Expand All @@ -150,8 +199,17 @@ static void adc_read_task(void* arg) {

for (int i = 0; i < ret_num; i += sizeof(adc_digi_output_data_t)) {
adc_digi_output_data_t* p = (adc_digi_output_data_t*)&result[i];
uint32_t val = ADC_GET_DATA(p);
out_buf[out_idx++] = (uint16_t)val;
uint32_t raw_val = ADC_GET_DATA(p);

// Convert raw ADC value to calibrated millivolts
int voltage_mv;
if (cali_handle) {
adc_cali_raw_to_voltage(cali_handle, (int)raw_val, &voltage_mv);
} else {
// Fallback to approximate conversion (3.3V reference / 4096 steps)
voltage_mv = (int)((raw_val * 3300) / 4096);
}
out_buf[out_idx++] = (uint16_t)voltage_mv;
}

if (out_idx > 0) {
Expand Down