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:
@@ -1,28 +1,38 @@
|
||||
/ {
|
||||
zephyr,user {
|
||||
io-channels = <&adc1 1>;
|
||||
io-channel-names = "multi_sense";
|
||||
};
|
||||
vdd_sense: voltage-divider {
|
||||
compatible = "voltage-divider";
|
||||
/*
|
||||
* This reference must provide one argument (the channel number)
|
||||
* because of the "#io-channel-cells = <1>" in the &adc1 node.
|
||||
*/
|
||||
io-channels = <&adc1 1>;
|
||||
output-ohms = <2200>;
|
||||
full-ohms = <3200>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc1 {
|
||||
status = "okay";
|
||||
status = "okay";
|
||||
|
||||
pinctrl-0 = <&adc1_in1_pa0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&adc1_in1_pa0>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
st,adc-clock-source = "SYNC";
|
||||
st,adc-prescaler = <4>;
|
||||
st,adc-clock-source = "SYNC";
|
||||
st,adc-prescaler = <4>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
/*
|
||||
* This line is required by the st,stm32-adc driver binding.
|
||||
* It declares that references to its channels need one extra argument.
|
||||
*/
|
||||
#io-channel-cells = <1>;
|
||||
|
||||
/* This defines channel 1 on adc1. The "1" in io-channels refers to this reg value. */
|
||||
adc_channel_1: channel@1 {
|
||||
reg = <1>;
|
||||
zephyr,gain = "ADC_GAIN_1";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
adc_channel_1: channel@1 {
|
||||
reg = <1>;
|
||||
zephyr,gain = "ADC_GAIN_1";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
||||
@@ -1,2 +1,4 @@
|
||||
CONFIG_ADC=y
|
||||
CONFIG_SENSOR=y
|
||||
CONFIG_VOLTAGE_DIVIDER=y
|
||||
CONFIG_LOG=y
|
||||
@@ -1,57 +1,43 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/adc.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(adc_dt_example, LOG_LEVEL_DBG);
|
||||
|
||||
/* Get the ADC channel specification from the devicetree */
|
||||
#define SENSE_NODE DT_PATH(zephyr_user)
|
||||
static const struct adc_dt_spec sense_channel = ADC_DT_SPEC_GET_BY_NAME(SENSE_NODE, multi_sense);
|
||||
/* Get the voltage divider device */
|
||||
#define VOLTAGE_DIVIDER_NODE DT_NODELABEL(vdd_sense)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const struct device *vdd_dev = DEVICE_DT_GET(VOLTAGE_DIVIDER_NODE);
|
||||
struct sensor_value val;
|
||||
int err;
|
||||
uint16_t buf;
|
||||
struct adc_sequence sequence = {
|
||||
.buffer = &buf,
|
||||
.buffer_size = sizeof(buf),
|
||||
};
|
||||
|
||||
if (!device_is_ready(sense_channel.dev)) {
|
||||
LOG_ERR("ADC controller device not ready");
|
||||
if (!device_is_ready(vdd_dev)) {
|
||||
LOG_ERR("Voltage divider device not ready");
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = adc_channel_setup_dt(&sense_channel);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Could not setup channel #%u (%d)", sense_channel.channel_id, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_INF("ADC channel setup successful!");
|
||||
LOG_INF("Voltage divider device ready!");
|
||||
|
||||
while (1) {
|
||||
// 1. Explicitly initialize the sequence structure from the devicetree spec.
|
||||
// This sets sequence.channels correctly.
|
||||
(void)adc_sequence_init_dt(&sense_channel, &sequence);
|
||||
|
||||
// 2. Perform the read on the ADC device with the now-configured sequence.
|
||||
err = adc_read(sense_channel.dev, &sequence);
|
||||
err = sensor_sample_fetch(vdd_dev);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Could not read (%d)", err);
|
||||
LOG_ERR("Could not fetch sample (%d)", err);
|
||||
k_sleep(K_MSEC(1000));
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t val_mv = buf;
|
||||
err = adc_raw_to_millivolts_dt(&sense_channel, &val_mv);
|
||||
err = sensor_channel_get(vdd_dev, SENSOR_CHAN_VOLTAGE, &val);
|
||||
if (err < 0) {
|
||||
LOG_WRN("Could not convert to millivolts (%d)", err);
|
||||
LOG_ERR("Could not get channel (%d)", err);
|
||||
k_sleep(K_MSEC(1000));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_INF("ADC reading raw: %d -> %d mV", buf, val_mv);
|
||||
LOG_INF("Voltage reading: %d.%06d V", val.val1, val.val2);
|
||||
|
||||
k_sleep(K_MSEC(1000));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user