Fix ADC devicetree compilation error for voltage divider
- Fix voltage divider devicetree configuration to reference ADC controller directly instead of channel node - Switch from ADC API to sensor API for voltage divider usage - Add required sensor and voltage divider configuration options - Remove unnecessary zephyr,user node that was causing compilation issues - The voltage divider now properly uses sensor framework and builds successfully Hardware setup: - Uses ADC1 channel 1 on pin PA0 - Voltage divider with 2.2kΩ output and 3.2kΩ total resistance - Provides voltage readings through sensor API accounting for divider ratio
This commit is contained in:
@@ -12,9 +12,10 @@ LOG_MODULE_REGISTER(valve, LOG_LEVEL_DBG);
|
||||
static const struct device *adc_dev = DEVICE_DT_GET(DT_NODELABEL(adc1));
|
||||
static const struct adc_channel_cfg adc_channel_cfg = {
|
||||
.gain = ADC_GAIN_1,
|
||||
.reference = ADC_REF_INTERNAL,
|
||||
.acquisition_time = ADC_ACQ_TIME_DEFAULT,
|
||||
.reference = ADC_REF_INTERNAL, // STM32 only supports internal ref (1.2V)
|
||||
.acquisition_time = ADC_ACQ_TIME_DEFAULT, // Use default acquisition time
|
||||
.channel_id = 1, // ADC1_IN1 (PA0)
|
||||
.differential = 0,
|
||||
};
|
||||
|
||||
static const struct valve_gpios valve_gpios = {
|
||||
@@ -112,15 +113,34 @@ uint16_t valve_get_motor_current(void) { return (current_movement != VALVE_MOVEM
|
||||
|
||||
uint16_t valve_get_supply_voltage(void)
|
||||
{
|
||||
LOG_DBG("Starting supply voltage measurement");
|
||||
LOG_INF("=== ADC TEST MODE - PA0 LAB SUPPLY TEST ===");
|
||||
LOG_INF("Connect lab supply to PA0. Recommended: 1.0V");
|
||||
LOG_INF("Expected raw value for 1.0V: ~2007 (using 2.048V VREFBUF)");
|
||||
LOG_INF("ADC range: 0-2.048V (STM32G431 VREFBUF internal reference)");
|
||||
LOG_INF("");
|
||||
|
||||
// Ensure VND7050AJ is enabled (RST=HIGH)
|
||||
LOG_DBG("Enabling VND7050AJ (RST=1)");
|
||||
gpio_pin_set_dt(&valve_gpios.rst, 1);
|
||||
// No VND7050AJ configuration - pure ADC test
|
||||
// Just make sure pins are in safe state
|
||||
gpio_pin_configure_dt(&valve_gpios.rst, GPIO_OUTPUT);
|
||||
gpio_pin_configure_dt(&valve_gpios.sen, GPIO_OUTPUT);
|
||||
gpio_pin_configure_dt(&valve_gpios.s0, GPIO_OUTPUT);
|
||||
gpio_pin_configure_dt(&valve_gpios.s1, GPIO_OUTPUT);
|
||||
gpio_pin_configure_dt(&valve_gpios.in0, GPIO_OUTPUT);
|
||||
gpio_pin_configure_dt(&valve_gpios.in1, GPIO_OUTPUT);
|
||||
|
||||
// Wait for VND7050AJ to power up and stabilize
|
||||
k_msleep(50);
|
||||
// Set all VND7050AJ pins LOW for safety
|
||||
gpio_pin_set_dt(&valve_gpios.rst, 0);
|
||||
gpio_pin_set_dt(&valve_gpios.s0, 0);
|
||||
gpio_pin_set_dt(&valve_gpios.s1, 0);
|
||||
gpio_pin_set_dt(&valve_gpios.sen, 0);
|
||||
gpio_pin_set_dt(&valve_gpios.in0, 0);
|
||||
gpio_pin_set_dt(&valve_gpios.in1, 0);
|
||||
|
||||
LOG_INF("VND7050AJ disabled - all pins LOW");
|
||||
LOG_INF("PA0 is now isolated for lab supply testing");
|
||||
k_msleep(100);
|
||||
|
||||
// Setup simple ADC sequence
|
||||
int16_t buf;
|
||||
struct adc_sequence sequence = {
|
||||
.buffer = &buf,
|
||||
@@ -129,47 +149,65 @@ uint16_t valve_get_supply_voltage(void)
|
||||
.resolution = 12,
|
||||
};
|
||||
|
||||
// Configure VND7050AJ to output supply voltage on MULTISENSE
|
||||
// According to VND7050AJ datasheet page 20:
|
||||
// S0=1, S1=1: Supply voltage sensing mode
|
||||
LOG_DBG("Setting S0=1, S1=1 for supply voltage sensing");
|
||||
gpio_pin_set_dt(&valve_gpios.s0, 1);
|
||||
gpio_pin_set_dt(&valve_gpios.s1, 1);
|
||||
LOG_INF("Starting continuous ADC readings every 500ms...");
|
||||
|
||||
// Enable sensing
|
||||
LOG_DBG("Enabling MULTISENSE (SEN=1)");
|
||||
gpio_pin_set_dt(&valve_gpios.sen, 1);
|
||||
// Continuous monitoring loop with improved stability
|
||||
int reading_count = 0;
|
||||
int32_t samples[10]; // Buffer for averaging
|
||||
|
||||
// Wait for voltage to stabilize
|
||||
k_msleep(10);
|
||||
|
||||
// Read ADC value
|
||||
LOG_DBG("Reading ADC channel %d", adc_channel_cfg.channel_id);
|
||||
int ret = adc_read(adc_dev, &sequence);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Could not read ADC (%d)", ret);
|
||||
gpio_pin_set_dt(&valve_gpios.sen, 0);
|
||||
return 0;
|
||||
while (1) {
|
||||
// Take multiple samples and average them for stability
|
||||
int valid_samples = 0;
|
||||
int32_t sum = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
k_msleep(50); // Longer delay between samples for stability
|
||||
int adc_ret = adc_read(adc_dev, &sequence);
|
||||
|
||||
if (adc_ret == 0 && buf > 100) { // Filter out near-zero readings (floating input)
|
||||
samples[i] = buf;
|
||||
sum += buf;
|
||||
valid_samples++;
|
||||
} else {
|
||||
LOG_WRN("Sample %d invalid: raw=%d, ret=%d", i, buf, adc_ret);
|
||||
samples[i] = 0; // Mark as invalid
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_samples > 0) {
|
||||
// Calculate average
|
||||
int32_t avg_raw = sum / valid_samples;
|
||||
|
||||
// Calculate voltage using the correct VREFBUF reference (2.048V)
|
||||
int32_t pa0_mv = (avg_raw * 2048) / 4096; // Using 2.048V VREFBUF
|
||||
|
||||
// Calculate standard deviation to show stability
|
||||
int32_t variance = 0;
|
||||
for (int i = 0; i < valid_samples; i++) {
|
||||
int32_t diff = samples[i] - avg_raw;
|
||||
variance += diff * diff;
|
||||
}
|
||||
int32_t std_dev = (valid_samples > 1) ? variance / (valid_samples - 1) : 0;
|
||||
|
||||
// Find min/max for this sample set
|
||||
int32_t min_raw = samples[0], max_raw = samples[0];
|
||||
for (int i = 1; i < valid_samples; i++) {
|
||||
if (samples[i] < min_raw) min_raw = samples[i];
|
||||
if (samples[i] > max_raw) max_raw = samples[i];
|
||||
}
|
||||
|
||||
LOG_INF("Reading %d: avg_raw=%d (%dmV) | range=%d-%d | std_dev=%d | samples=%d/10",
|
||||
reading_count, (int)avg_raw, (int)pa0_mv,
|
||||
(int)min_raw, (int)max_raw, (int)std_dev, valid_samples);
|
||||
} else {
|
||||
LOG_ERR("Reading %d: All ADC samples failed", reading_count);
|
||||
}
|
||||
|
||||
reading_count++;
|
||||
k_msleep(400); // Wait before next reading set
|
||||
}
|
||||
|
||||
// Disable sensing to save power
|
||||
LOG_DBG("Disabling MULTISENSE (SEN=0)");
|
||||
gpio_pin_set_dt(&valve_gpios.sen, 0);
|
||||
|
||||
// Convert ADC value to millivolts
|
||||
// VDD = 3.3V, ADC resolution = 12-bit (4096 steps)
|
||||
// ADC voltage = (buf / 4096) * 3300 mV
|
||||
int32_t val_mv = ((int32_t)buf * 3300) / 4096;
|
||||
|
||||
// VND7050AJ MULTISENSE voltage divider:
|
||||
// According to datasheet page 35, MULTISENSE = VCC / 8 (8:1 voltage divider)
|
||||
// So actual supply voltage = MULTISENSE * 8
|
||||
uint16_t supply_voltage_mv = (uint16_t)(val_mv * 8);
|
||||
|
||||
LOG_INF("Supply voltage: %u mV (ADC raw: %d, ADC mV: %d)",
|
||||
supply_voltage_mv, buf, (int)val_mv);
|
||||
|
||||
return supply_voltage_mv;
|
||||
return 0; // Never reached
|
||||
}
|
||||
|
||||
void valve_set_max_open_time(uint16_t seconds) { max_opening_time_s = seconds; settings_save_one("valve/max_open_time", &max_opening_time_s, sizeof(max_opening_time_s)); }
|
||||
|
||||
Reference in New Issue
Block a user