diff --git a/software/apps/slave_node/prj.conf b/software/apps/slave_node/prj.conf index 9d47cf3..ab89f97 100644 --- a/software/apps/slave_node/prj.conf +++ b/software/apps/slave_node/prj.conf @@ -22,4 +22,5 @@ CONFIG_MODBUS_BUFFER_SIZE=256 # ADC Sensor Configuration - Use real ADC readings CONFIG_ADC_SENSOR_SIMULATED=n +CONFIG_ADC=y diff --git a/software/lib/adc_sensor/adc_sensor.c b/software/lib/adc_sensor/adc_sensor.c index b5be247..2cc6e1a 100644 --- a/software/lib/adc_sensor/adc_sensor.c +++ b/software/lib/adc_sensor/adc_sensor.c @@ -24,6 +24,34 @@ LOG_MODULE_REGISTER(adc_sensor, LOG_LEVEL_INF); #define VOLTAGE_SENSOR_NODE DT_NODELABEL(supply_voltage) #define CURRENT_SENSOR_NODE DT_NODELABEL(motor_current) +#ifndef CONFIG_ADC_SENSOR_SIMULATED +// ADC device reference +#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) +#define ADC_NODE DT_PHANDLE(VOLTAGE_SENSOR_NODE, io_channels) +#define ADC_CHANNEL DT_PHA(VOLTAGE_SENSOR_NODE, io_channels, input) +#define ADC_RESOLUTION 12 +#define ADC_REFERENCE_MV DT_PROP(VOLTAGE_SENSOR_NODE, reference_mv) +#define VOLTAGE_DIVIDER_RATIO \ + DT_PROP(VOLTAGE_SENSOR_NODE, voltage_divider_ratio) + +static const struct device *adc_dev; +static struct adc_channel_cfg adc_channel_cfg = { + .gain = ADC_GAIN_1, + .reference = ADC_REF_INTERNAL, + .acquisition_time = ADC_ACQ_TIME_DEFAULT, + .channel_id = ADC_CHANNEL, + .differential = 0}; + +static struct adc_sequence adc_sequence = { + .channels = BIT(ADC_CHANNEL), + .buffer_size = sizeof(uint16_t), + .resolution = ADC_RESOLUTION, +}; + +static uint16_t adc_buffer; +#endif +#endif + static bool initialized = false; #ifndef CONFIG_ADC_SENSOR_SIMULATED @@ -165,6 +193,65 @@ static int set_current_sensor_gpios(bool enable, bool s0_state, bool s1_state) { } #endif /* !CONFIG_ADC_SENSOR_SIMULATED */ +#ifndef CONFIG_ADC_SENSOR_SIMULATED +/** + * @brief Read ADC value and convert to millivolts + * @return ADC reading in millivolts, or 0 on error + */ +static uint16_t read_adc_voltage_mv(void) { +#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) + int ret = adc_read(adc_dev, &adc_sequence); + if (ret < 0) { + LOG_ERR("ADC read failed: %d", ret); + return 0; + } + + // Convert ADC reading to millivolts + // ADC reading is 12-bit (0-4095) representing 0 to ADC_REFERENCE_MV + uint32_t adc_value = adc_buffer; + uint32_t voltage_mv = (adc_value * ADC_REFERENCE_MV) / 4095; + + // Apply voltage divider scaling + voltage_mv *= VOLTAGE_DIVIDER_RATIO; + + LOG_DBG("ADC raw: %u, voltage: %u mV", adc_value, (uint16_t)voltage_mv); + + return (uint16_t)voltage_mv; +#else + return 0; +#endif +} + +/** + * @brief Read ADC value and convert to milliamps (for current sensor) + * @return ADC reading in milliamps, or 0 on error + */ +static uint16_t read_adc_current_ma(void) { +#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE) + int ret = adc_read(adc_dev, &adc_sequence); + if (ret < 0) { + LOG_ERR("ADC read failed: %d", ret); + return 0; + } + + // Convert ADC reading to millivolts first + uint32_t adc_value = adc_buffer; + uint32_t voltage_mv = (adc_value * ADC_REFERENCE_MV) / 4095; + + // Convert voltage to current based on current sensor characteristics + // Assuming a linear current sensor with specific mV/mA ratio + // This will need to be calibrated for your specific current sensor + uint32_t current_ma = voltage_mv / 10; // Example: 10mV per mA + + LOG_DBG("ADC raw: %u, current: %u mA", adc_value, (uint16_t)current_ma); + + return (uint16_t)current_ma; +#else + return 0; +#endif +} +#endif + int adc_sensor_init(void) { if (initialized) { return 0; @@ -182,7 +269,25 @@ int adc_sensor_init(void) { return ret; } - // TODO: Initialize real ADC hardware + // Initialize ADC hardware +#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) + adc_dev = DEVICE_DT_GET(ADC_NODE); + if (!device_is_ready(adc_dev)) { + LOG_ERR("ADC device not ready"); + return -ENODEV; + } + + adc_sequence.buffer = &adc_buffer; + + ret = adc_channel_setup(adc_dev, &adc_channel_cfg); + if (ret < 0) { + LOG_ERR("Failed to setup ADC channel: %d", ret); + return ret; + } + + LOG_INF("ADC device ready: %s", adc_dev->name); +#endif + LOG_INF("ADC sensor initialized (real ADC mode with GPIO control)"); #if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) @@ -209,9 +314,8 @@ uint16_t adc_sensor_get_voltage_mv(void) { // Set GPIOs for voltage measurement (example: s0=0, s1=0 for channel 0) set_voltage_sensor_gpios(true, false, false); - // TODO: Read real ADC value for voltage - // For now return simulated value - uint16_t voltage = SIMULATED_VOLTAGE_MV; + // Read real ADC value for voltage + uint16_t voltage = read_adc_voltage_mv(); // Disable sensor after measurement to save power set_voltage_sensor_gpios(false, false, false); @@ -232,9 +336,8 @@ uint16_t adc_sensor_get_current_ma(void) { // Set GPIOs for current measurement (example: s0=1, s1=0 for channel 1) set_current_sensor_gpios(true, true, false); - // TODO: Read real ADC value for current - // For now return simulated value - uint16_t current = SIMULATED_CURRENT_MA; + // Read real ADC value for current + uint16_t current = read_adc_current_ma(); // Disable sensor after measurement to save power set_current_sensor_gpios(false, false, false);