I am implementing the code for nrf54l15 nordic MCU to:
Use vbat_mon pin p1.10 in NRF54L15 as ADC and trying to read the voltages, but physically i am not able to read/get the correct voltages across
VBAT_MEAS_SW and VBAT_MON which is having volatge divider circuit in the schematics. instead i am able to read as 0 V at both pins.
I am using the dts board file code as below
zephyr,user
I am using the dts board file code as below
zephyr,user
{ io-channels = <&adc 0>;
};
aliases {
aliases {
vbatmon = &vbat_mon;
vbatadcnode = &vbatadc_node;
};
&adc {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
vbatadc_node: channel@0 {
reg = <0>; /* Use ADC channel 0 */
zephyr,gain = "ADC_GAIN_1_6"; /* Gain 1/6 to measure up to VDD range */
zephyr,reference = "ADC_REF_INTERNAL"; /* Internal 0.6V reference */
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN3>; /* P1.10 maps to AIN3 */
zephyr,resolution = <12>; /* 12-bit resolution */
};
};
using the kconfig options as below
CONFIG_ADC=y
using the kconfig options as below
CONFIG_ADC=y
CONFIG_NRFX_SAADC=y
I implemented the below code:
please provide inputs if any of the above implementation is incorrect ?
I must ensure that exact volatges are read across those pins on board physically
I implemented the below code:
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>
#include <stdio.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/gpio.h>
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
#include <zephyr/devicetree/gpio.h>
#include <zephyr/toolchain/common.h>
#include <zephyr/sys/__assert.h>
#include "tca9535_config.h"
#include "tca9535.h"
#include "VoltMon.h"
LOG_MODULE_REGISTER(vbat_mon, LOG_LEVEL_INF);
/*
* Use DT_PATH(zephyr_user) to get the node,
* and 0 to specify the first channel in its 'io-channels' list.
*/
static const struct adc_dt_spec vbat_adc_channel = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
static int16_t sample_buffer;
void measure_vbat_voltage(void)
{
int err;
struct adc_sequence sequence = {
.channels = BIT(vbat_adc_channel.channel_id), // Use the specific channel ID retrieved by the macro
.buffer = &sample_buffer,
/* buffer size in bytes, not number of samples */
.buffer_size = sizeof(sample_buffer),
.calibrate = true, // Calibration is recommended
.oversampling = 0, // Set oversampling rate if needed (0 for default/off)
.resolution = vbat_adc_channel.resolution, // Use resolution from DT spec
};
// Follow the steps in the linked guide to initialize and read ADC data
if (!adc_is_ready_dt(&vbat_adc_channel)) {
printk("ADC controller device %s not ready", vbat_adc_channel.dev->name);
return;
}
err = adc_channel_setup_dt(&vbat_adc_channel);
if (err < 0) {
printk("Could not setup ADC channel (%d)", err);
return;
}
//Enable the VBAT_MEAS_SW PIN before reading the voltage
TCA9535_Set_PORT0_PORT1(VBAT_MEAS_SW_PORT0_EN); // Enable measurement path
k_sleep(K_MSEC(10)); // Allow stabilization
while (1)
{
err = adc_read(vbat_adc_channel.dev, &sequence);
if (err)
{
LOG_ERR("ADC read failed (%d)", err);
}
else
{
/* Convert raw ADC value to voltage */
float vbat = ((float)sample_buffer / (1 << vbat_adc_channel.resolution)) * 0.6f * 6; // internal ref * gain factor
LOG_INF("VBAT raw: %d, voltage: %.2f V", sample_buffer, vbat);
}
k_sleep(K_SECONDS(1));
}
//Disable the VBAT_MEAS_SW PIN after reading the voltage
TCA9535_Set_PORT0_PORT1(VBAT_MEAS_SW_PORT0_DISABLE);
}
please provide inputs if any of the above implementation is incorrect ?
I must ensure that exact volatges are read across those pins on board physically