Hi, I have been trying to do a simple analogRead using the nrf5340 using the adc, the closest working example I found was Battery Voltage Measurement working with SDK 2.4 and Zephyr 3.2.
The example is working perfectly fine, but I am trying to modify it so I can read the voltage of an outside battery, a Classic AnalogRead on a pin.
I am sure it's a simple modification, but I couldn't figure it out , I would appreciate if you could help me figure out which configuration I need to modify to not read the power supply voltage but the one coming into the Pin from an outside source Thank you very much.
.overlay:
/ { zephyr,user { io-channels = <&adc 1>; }; };
main.c
/* */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <zephyr/init.h> #include <zephyr/drivers/gpio.h> #include <zephyr/drivers/adc.h> #include <zephyr/drivers/sensor.h> #include <zephyr/kernel.h> #define ZEPHYR_USER DT_PATH(zephyr_user) #define BATTERY_ADC_GAIN ADC_GAIN_1_6 struct io_channel_config { uint8_t channel; }; struct divider_config { struct io_channel_config io_channel; struct gpio_dt_spec power_gpios; /* output_ohm is used as a flag value: if it is nonzero then * the battery is measured through a voltage divider; * otherwise it is assumed to be directly connected to Vdd. */ uint32_t output_ohm; uint32_t full_ohm; }; static const struct divider_config divider_config = {.io_channel = { DT_IO_CHANNELS_INPUT(ZEPHYR_USER), }, }; struct divider_data { const struct device *adc; struct adc_channel_cfg adc_cfg; struct adc_sequence adc_seq; int16_t raw; }; static struct divider_data divider_data = { .adc = DEVICE_DT_GET(DT_IO_CHANNELS_CTLR(ZEPHYR_USER)), }; static bool battery_ok; static int divider_setup(void) { const struct divider_config *cfg = ÷r_config; const struct io_channel_config *iocp = &cfg->io_channel; const struct gpio_dt_spec *gcp = &cfg->power_gpios; struct divider_data *ddp = ÷r_data; struct adc_sequence *asp = &ddp->adc_seq; struct adc_channel_cfg *accp = &ddp->adc_cfg; int rc; if (!device_is_ready(ddp->adc)) { printk("ADC device is not ready %s", ddp->adc->name); return -ENOENT; } if (gcp->port) { if (!device_is_ready(gcp->port)) { printk("%s: device not ready", gcp->port->name); return -ENOENT; } rc = gpio_pin_configure_dt(gcp, GPIO_OUTPUT_INACTIVE); if (rc != 0) { printk("Failed to control feed %s.%u: %d", gcp->port->name, gcp->pin, rc); return rc; } } *asp = (struct adc_sequence){ .channels = BIT(0), .buffer = &ddp->raw, .buffer_size = sizeof(ddp->raw), .oversampling = 4, .calibrate = true, }; #ifdef CONFIG_ADC_NRFX_SAADC *accp = (struct adc_channel_cfg){ .gain = BATTERY_ADC_GAIN, .reference = ADC_REF_INTERNAL, .acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40), }; if (cfg->output_ohm != 0) { accp->input_positive = SAADC_CH_PSELP_PSELP_AnalogInput0 + iocp->channel; printk("OUTPUT != 0\n"); //this should not be activated in my situation } else { accp->input_positive = SAADC_CH_PSELP_PSELP_VDD; printk("OUTPUT == 0, else\n"); } asp->resolution = 14; #else /* CONFIG_ADC_var */ #error Unsupported ADC #endif /* CONFIG_ADC_var */ rc = adc_channel_setup(ddp->adc, accp); printk("Setup AIN%u got %d \n", iocp->channel, rc); return rc; } static int battery_setup(void) { int rc = divider_setup(); battery_ok = (rc == 0); printk("Battery setup: %d %d \n", rc, battery_ok); return rc; } SYS_INIT(battery_setup, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); //when system start this initialise int main(void) { const struct gpio_dt_spec *gcp = ÷r_config.power_gpios; if (gcp->port) { gpio_pin_set_dt(gcp, true); } while (true) { struct divider_data *ddp = ÷r_data; const struct divider_config *dcp = ÷r_config; struct adc_sequence *sp = &ddp->adc_seq; int batt_mV = adc_read(ddp->adc, sp); //printk("%d adc read;\n",batt_mV); sp->calibrate = false; if (batt_mV == 0) { int32_t val = ddp->raw; adc_raw_to_millivolts(adc_ref_internal(ddp->adc),ddp->adc_cfg.gain,sp->resolution,&val); batt_mV = val; } printk("%d mV;\n",batt_mV); k_busy_wait( ((1000U) * (1000U))); } return 0; }