/** * @file adc_sensor.c * @brief Implementation of the ADC sensor library. * * This file contains the implementation for initializing and reading from ADC * sensors. It currently provides simulated values for voltage and current, with * placeholders for real hardware ADC implementation including GPIO control. */ #include #include #include #include #include #include LOG_MODULE_REGISTER(adc_sensor, LOG_LEVEL_INF); // Simulated values #define SIMULATED_VOLTAGE_MV 12000 #define SIMULATED_CURRENT_MA 45 // Devicetree node checks #define VOLTAGE_SENSOR_NODE DT_NODELABEL(supply_voltage) #define CURRENT_SENSOR_NODE DT_NODELABEL(motor_current) static bool initialized = false; #ifndef CONFIG_ADC_SENSOR_SIMULATED // GPIO specs for voltage sensor (if devicetree nodes exist) #if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) static const struct gpio_dt_spec voltage_sen_gpio = GPIO_DT_SPEC_GET(VOLTAGE_SENSOR_NODE, sen_gpios); static const struct gpio_dt_spec voltage_s0_gpio = GPIO_DT_SPEC_GET(VOLTAGE_SENSOR_NODE, s0_gpios); static const struct gpio_dt_spec voltage_s1_gpio = GPIO_DT_SPEC_GET(VOLTAGE_SENSOR_NODE, s1_gpios); #endif // GPIO specs for current sensor (if devicetree nodes exist) #if DT_NODE_EXISTS(CURRENT_SENSOR_NODE) static const struct gpio_dt_spec current_sen_gpio = GPIO_DT_SPEC_GET(CURRENT_SENSOR_NODE, sen_gpios); static const struct gpio_dt_spec current_s0_gpio = GPIO_DT_SPEC_GET(CURRENT_SENSOR_NODE, s0_gpios); static const struct gpio_dt_spec current_s1_gpio = GPIO_DT_SPEC_GET(CURRENT_SENSOR_NODE, s1_gpios); #endif /** * @brief Configure GPIO pins for ADC sensor control */ static int configure_sensor_gpios(void) { int ret = 0; #if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) // Configure voltage sensor GPIOs if (gpio_is_ready_dt(&voltage_sen_gpio)) { ret = gpio_pin_configure_dt(&voltage_sen_gpio, GPIO_OUTPUT_INACTIVE); if (ret < 0) { LOG_ERR("Failed to configure voltage sen GPIO: %d", ret); return ret; } } if (gpio_is_ready_dt(&voltage_s0_gpio)) { ret = gpio_pin_configure_dt(&voltage_s0_gpio, GPIO_OUTPUT_INACTIVE); if (ret < 0) { LOG_ERR("Failed to configure voltage s0 GPIO: %d", ret); return ret; } } if (gpio_is_ready_dt(&voltage_s1_gpio)) { ret = gpio_pin_configure_dt(&voltage_s1_gpio, GPIO_OUTPUT_INACTIVE); if (ret < 0) { LOG_ERR("Failed to configure voltage s1 GPIO: %d", ret); return ret; } } #endif #if DT_NODE_EXISTS(CURRENT_SENSOR_NODE) // Configure current sensor GPIOs if (gpio_is_ready_dt(¤t_sen_gpio)) { ret = gpio_pin_configure_dt(¤t_sen_gpio, GPIO_OUTPUT_INACTIVE); if (ret < 0) { LOG_ERR("Failed to configure current sen GPIO: %d", ret); return ret; } } if (gpio_is_ready_dt(¤t_s0_gpio)) { ret = gpio_pin_configure_dt(¤t_s0_gpio, GPIO_OUTPUT_INACTIVE); if (ret < 0) { LOG_ERR("Failed to configure current s0 GPIO: %d", ret); return ret; } } if (gpio_is_ready_dt(¤t_s1_gpio)) { ret = gpio_pin_configure_dt(¤t_s1_gpio, GPIO_OUTPUT_INACTIVE); if (ret < 0) { LOG_ERR("Failed to configure current s1 GPIO: %d", ret); return ret; } } #endif return 0; } /** * @brief Set GPIO pins for voltage measurement * @param s0_state State for S0 pin (multiplexer bit 0) * @param s1_state State for S1 pin (multiplexer bit 1) */ static int set_voltage_sensor_gpios(bool enable, bool s0_state, bool s1_state) { #if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) if (gpio_is_ready_dt(&voltage_sen_gpio)) { gpio_pin_set_dt(&voltage_sen_gpio, enable ? 1 : 0); } if (gpio_is_ready_dt(&voltage_s0_gpio)) { gpio_pin_set_dt(&voltage_s0_gpio, s0_state ? 1 : 0); } if (gpio_is_ready_dt(&voltage_s1_gpio)) { gpio_pin_set_dt(&voltage_s1_gpio, s1_state ? 1 : 0); } // Delay for GPIO settling (from devicetree or default) #if DT_NODE_HAS_PROP(VOLTAGE_SENSOR_NODE, measurement_delay_ms) k_msleep(DT_PROP(VOLTAGE_SENSOR_NODE, measurement_delay_ms)); #else k_msleep(5); // Default 5ms delay #endif #endif return 0; } /** * @brief Set GPIO pins for current measurement * @param s0_state State for S0 pin (multiplexer bit 0) * @param s1_state State for S1 pin (multiplexer bit 1) */ static int set_current_sensor_gpios(bool enable, bool s0_state, bool s1_state) { #if DT_NODE_EXISTS(CURRENT_SENSOR_NODE) if (gpio_is_ready_dt(¤t_sen_gpio)) { gpio_pin_set_dt(¤t_sen_gpio, enable ? 1 : 0); } if (gpio_is_ready_dt(¤t_s0_gpio)) { gpio_pin_set_dt(¤t_s0_gpio, s0_state ? 1 : 0); } if (gpio_is_ready_dt(¤t_s1_gpio)) { gpio_pin_set_dt(¤t_s1_gpio, s1_state ? 1 : 0); } // Delay for GPIO settling (from devicetree or default) #if DT_NODE_HAS_PROP(CURRENT_SENSOR_NODE, measurement_delay_ms) k_msleep(DT_PROP(CURRENT_SENSOR_NODE, measurement_delay_ms)); #else k_msleep(10); // Default 10ms delay #endif #endif return 0; } #endif /* !CONFIG_ADC_SENSOR_SIMULATED */ int adc_sensor_init(void) { if (initialized) { return 0; } #ifdef CONFIG_ADC_SENSOR_SIMULATED LOG_INF("ADC sensor initialized (simulated mode)"); LOG_INF("Simulated values: %dmV, %dmA", SIMULATED_VOLTAGE_MV, SIMULATED_CURRENT_MA); #else // Initialize GPIO pins for sensor control int ret = configure_sensor_gpios(); if (ret < 0) { LOG_ERR("Failed to configure sensor GPIOs: %d", ret); return ret; } // TODO: Initialize real ADC hardware LOG_INF("ADC sensor initialized (real ADC mode with GPIO control)"); #if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE) LOG_INF("Voltage sensor found in devicetree"); #endif #if DT_NODE_EXISTS(CURRENT_SENSOR_NODE) LOG_INF("Current sensor found in devicetree"); #endif #endif initialized = true; return 0; } uint16_t adc_sensor_get_voltage_mv(void) { if (!initialized) { LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()"); adc_sensor_init(); } #ifdef CONFIG_ADC_SENSOR_SIMULATED return SIMULATED_VOLTAGE_MV; #else // 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; // Disable sensor after measurement to save power set_voltage_sensor_gpios(false, false, false); return voltage; #endif } uint16_t adc_sensor_get_current_ma(void) { if (!initialized) { LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()"); adc_sensor_init(); } #ifdef CONFIG_ADC_SENSOR_SIMULATED return SIMULATED_CURRENT_MA; #else // 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; // Disable sensor after measurement to save power set_current_sensor_gpios(false, false, false); return current; #endif }