diff --git a/software/.vscode/settings.json b/software/.vscode/settings.json index 8d96b49..0e40522 100644 --- a/software/.vscode/settings.json +++ b/software/.vscode/settings.json @@ -9,4 +9,7 @@ "app_version.h": "c" }, "C_Cpp.clang_format_style": "file", + "nrf-connect.applications": [ + "${workspaceFolder}/apps/slave_node" + ], } \ No newline at end of file diff --git a/software/apps/slave_node/boards/weact_stm32g431_core.overlay b/software/apps/slave_node/boards/weact_stm32g431_core.overlay index 2481bba..d3b125e 100644 --- a/software/apps/slave_node/boards/weact_stm32g431_core.overlay +++ b/software/apps/slave_node/boards/weact_stm32g431_core.overlay @@ -11,6 +11,40 @@ s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; // S0 (PB6) - Status/Select 0 output from VND7050AJ s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; // S1 (PB5) - Status/Select 1 output from VND7050AJ }; + + adc_sensors { + compatible = "adc-sensors"; + + supply_voltage: supply-voltage { + compatible = "custom,supply-voltage"; + io-channels = <&adc1 1>; /* ADC1 channel 1 (PA0) */ + io-channel-names = "voltage"; + reference-mv = <3300>; + voltage-divider-ratio = <4>; /* Adjust based on your voltage divider */ + + /* GPIO control pins using VND7050AJ pins */ + sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */ + s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */ + s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */ + + measurement-delay-ms = <5>; /* 5ms delay after GPIO setup */ + }; + + motor_current: motor-current { + compatible = "custom,motor-current"; + io-channels = <&adc1 1>; /* Same ADC channel, different mux setting */ + io-channel-names = "current"; + reference-mv = <3300>; + current-sense-resistor-mohm = <100>; /* 100mΩ sense resistor */ + + /* GPIO control pins using VND7050AJ pins */ + sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */ + s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */ + s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */ + + measurement-delay-ms = <10>; /* 10ms delay for current settling */ + }; + }; }; // Clock configuration: Uncomment the following section to use calibrated HSI instead of HSE diff --git a/software/apps/slave_node/dts/bindings/adc/custom,motor-current.yaml b/software/apps/slave_node/dts/bindings/adc/custom,motor-current.yaml new file mode 100644 index 0000000..db9b5c0 --- /dev/null +++ b/software/apps/slave_node/dts/bindings/adc/custom,motor-current.yaml @@ -0,0 +1,48 @@ +description: Custom motor current measurement with GPIO control + +compatible: "custom,motor-current" + +properties: + io-channels: + type: phandle-array + required: true + description: ADC channel for current measurement + + io-channel-names: + type: string-array + description: Names for the ADC channels + + current-sense-resistor-mohm: + type: int + required: true + description: Current sense resistor value in milliohms + + amplifier-gain: + type: int + default: 1 + description: Current sense amplifier gain + + reference-mv: + type: int + default: 3300 + description: ADC reference voltage in millivolts + + sen-gpios: + type: phandle-array + required: true + description: GPIO to enable/disable the current measurement sensor + + s0-gpios: + type: phandle-array + required: true + description: GPIO for multiplexer control bit 0 + + s1-gpios: + type: phandle-array + required: true + description: GPIO for multiplexer control bit 1 + + measurement-delay-ms: + type: int + default: 10 + description: Delay in milliseconds after setting GPIOs before ADC measurement diff --git a/software/apps/slave_node/dts/bindings/adc/custom,supply-voltage.yaml b/software/apps/slave_node/dts/bindings/adc/custom,supply-voltage.yaml new file mode 100644 index 0000000..3bc71ea --- /dev/null +++ b/software/apps/slave_node/dts/bindings/adc/custom,supply-voltage.yaml @@ -0,0 +1,63 @@ +description: Custom supply voltage measurement with GPIO control + +compatible: "custom,supply-voltage" + +properties: + io-channels: + type: phandle-array + required: true + description: ADC channel for voltage measurement + + io-channel-names: + type: string-array + description: Names for the ADC channels + + voltage-divider-ratio: + type: int + required: true + description: Voltage divider ratio for scaling + + reference-mv: + type: int + default: 3300 + description: ADC reference voltage in millivolts + + sen-gpios: + type: phandle-array + required: true + description: GPIO to enable/disable the voltage measurement sensor + + s0-gpios: + type: phandle-array + required: true + description: GPIO for multiplexer control bit 0 + + s1-gpios: + type: phandle-array + required: true + description: GPIO for multiplexer control bit 1 + + measurement-delay-ms: + type: int + default: 10 + description: Delay in milliseconds after setting GPIOs before ADC measurement + + sen-gpios: + type: phandle-array + required: true + description: GPIO for SEN (Sense Enable) pin + + s0-gpios: + type: phandle-array + required: true + description: GPIO for S0 (Select 0) pin + + s1-gpios: + type: phandle-array + required: true + description: GPIO for S1 (Select 1) pin + + measurement-delay-ms: + type: int + default: 10 + description: Delay in milliseconds after setting control pins before ADC reading \ No newline at end of file diff --git a/software/apps/slave_node/prj.conf b/software/apps/slave_node/prj.conf index 24aacee..9d47cf3 100644 --- a/software/apps/slave_node/prj.conf +++ b/software/apps/slave_node/prj.conf @@ -20,3 +20,6 @@ CONFIG_MODBUS=y CONFIG_MODBUS_ROLE_SERVER=y CONFIG_MODBUS_BUFFER_SIZE=256 +# ADC Sensor Configuration - Use real ADC readings +CONFIG_ADC_SENSOR_SIMULATED=n + diff --git a/software/lib/adc_sensor/Kconfig b/software/lib/adc_sensor/Kconfig index 13aca87..5767b19 100644 --- a/software/lib/adc_sensor/Kconfig +++ b/software/lib/adc_sensor/Kconfig @@ -8,7 +8,7 @@ if ADC_SENSOR config ADC_SENSOR_SIMULATED bool "Use simulated ADC readings" - default y + default n help Use simulated values instead of real ADC readings. Voltage: 12000mV, Current: 45mA diff --git a/software/lib/adc_sensor/adc_sensor.c b/software/lib/adc_sensor/adc_sensor.c index 6ec6104..b5be247 100644 --- a/software/lib/adc_sensor/adc_sensor.c +++ b/software/lib/adc_sensor/adc_sensor.c @@ -4,10 +4,13 @@ * * 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. + * placeholders for real hardware ADC implementation including GPIO control. */ #include +#include +#include +#include #include #include @@ -17,8 +20,150 @@ LOG_MODULE_REGISTER(adc_sensor, LOG_LEVEL_INF); #define SIMULATED_VOLTAGE_MV 12000 #define SIMULATED_CURRENT_MA 45 -static bool initialized = - false; // Flag to indicate if the ADC sensor is initialized +// 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) { @@ -30,8 +175,22 @@ int adc_sensor_init(void) { 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 - not yet implemented)"); + 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; @@ -47,9 +206,17 @@ uint16_t adc_sensor_get_voltage_mv(void) { #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 - return SIMULATED_VOLTAGE_MV; + uint16_t voltage = SIMULATED_VOLTAGE_MV; + + // Disable sensor after measurement to save power + set_voltage_sensor_gpios(false, false, false); + + return voltage; #endif } @@ -62,8 +229,16 @@ uint16_t adc_sensor_get_current_ma(void) { #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 - return SIMULATED_CURRENT_MA; + uint16_t current = SIMULATED_CURRENT_MA; + + // Disable sensor after measurement to save power + set_current_sensor_gpios(false, false, false); + + return current; #endif }