Please refer to the previous article Nordic nRF54L15-DK Zephyr Linux Installation Steps to install the nRF54L15-DK Nordic Zephyr Dev installation needed to complete this. The goal of this article is to describe how to interface to the Nordic nRF54L15-DK SAADC. In order to do this please create the following files in a project foder, create the prj.conf
#
# Copyright (c) 2024 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_LOG=y
# STEP 1 - Enable the ADC API and driver
CONFIG_ADC=y
The main.c is the following,
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>
/* STEP 3.1 - Include the header file of the Zephyr ADC API */
#include <zephyr/drivers/adc.h>
/* STEP 3.2 - Define a variable of type adc_dt_spec for each channel */
static const struct adc_dt_spec adc_channel = ADC_DT_SPEC_GET(DT_PATH(zephyr_user));
LOG_MODULE_REGISTER(Output, LOG_LEVEL_DBG);
int main(void)
{
int err;
uint32_t count = 0;
/* STEP 4.1 - Define a variable of type adc_sequence and a buffer of type uint16_t */
int16_t buf;
struct adc_sequence sequence = {
.buffer = &buf,
/* buffer size in bytes, not number of samples */
.buffer_size = sizeof(buf),
// Optional
//.calibrate = true,
};
/* STEP 3.3 - validate that the ADC peripheral (SAADC) is ready */
if (!adc_is_ready_dt(&adc_channel)) {
LOG_ERR("ADC controller devivce %s not ready", adc_channel.dev->name);
return 0;
}
/* STEP 3.4 - Setup the ADC channel */
err = adc_channel_setup_dt(&adc_channel);
if (err < 0) {
LOG_ERR("Could not setup channel #%d (%d)", 0, err);
return 0;
}
/* STEP 4.2 - Initialize the ADC sequence */
err = adc_sequence_init_dt(&adc_channel, &sequence);
if (err < 0) {
LOG_ERR("Could not initalize sequnce");
return 0;
}
while (1) {
int val_mv;
/* STEP 5 - Read a sample from the ADC */
err = adc_read(adc_channel.dev, &sequence);
if (err < 0) {
LOG_ERR("Could not read (%d)", err);
continue;
}
val_mv = (int)buf;
LOG_INF("ADC reading[%u]: %s, channel %d: Raw: %d", count++, adc_channel.dev->name,
adc_channel.channel_id, val_mv);
/* STEP 6 - Convert raw value to mV*/
err = adc_raw_to_millivolts_dt(&adc_channel, &val_mv);
/* conversion to mV may not be supported, skip if not */
if (err < 0) {
LOG_WRN(" (value in mV not available)\n");
} else {
LOG_INF(" = %d mV", val_mv);
}
k_sleep(K_MSEC(1000));
}
return 0;
}
Finally create the nrf54l15dk_nrf54l15.overlay overlay file is as follows,
/ {
zephyr,user {
io-channels = <&adc 0>;
};
};
&adc {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
channel@0 {
reg = <0>;
zephyr,gain = "ADC_GAIN_1_4";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN4>; /* P1.11 for the nRF54L15 DK */
zephyr,resolution = <14>;
};
};
The resulting directory structure in your project folder is shown below,
├── CMakeLists.txt
├── nrf54l15dk_nrf54l15.overlay
├── prj.conf
└── src
└── main.c
Now proceed to build this Zephyr RTOS project as follows in the python virtual environment,
digikey_coffee_cup (venv) $ west build -p always -b nrf54l15dk/nrf54l15/cpuapp -- -DEXTRA_DTC_OVERLAY_FILE=nrf54l15dk_nrf54l15.overlay
Finally connect the Nordic Development kit nRF54L15-DK via the USB interface to flash it,
digikey_coffee_cup (venv) $ west flash
-- west flash: rebuilding
ninja: no work to do.
-- west flash: using runner nrfutil
-- runners.nrfutil: reset after flashing requested
Using board 001057777221
-- runners.nrfutil: Flashing file: /home/engineer/Digikey/Projects/Workspace/zephyr/zephyrproject/zephyr/adc/build/zephyr/zephyr.hex
-- runners.nrfutil: Connecting to probe
-- runners.nrfutil: Programming image
-- runners.nrfutil: Verifying image
-- runners.nrfutil: Reset
-- runners.nrfutil: Board(s) with serial number(s) 1057777221 flashed successfully.
To see the results of this project open a minicom terminal as follows,
digikey_coffee_cup $ minicom -D /dev/ttyACM1
Welcome to minicom 2.9
OPTIONS: I18n
Port /dev/ttyACM1, 19:28:23
Press CTRL-A Z for help on special keys
[00:04:54.044,706] <inf> Output: ADC reading[294]: adc@d5000, channel 0: Raw: 1056
[00:04:54.044,714] <inf> Output: = 232 mV
[00:04:55.044,857] <inf> Output: ADC reading[295]: adc@d5000, channel 0: Raw: 1056
[00:04:55.044,869] <inf> Output: = 232 mV
[00:04:56.044,994] <inf> Output: ADC reading[296]: adc@d5000, channel 0: Raw: 640
[00:04:56.045,002] <inf> Output: = 140 mV
[00:04:57.045,145] <inf> Output: ADC reading[297]: adc@d5000, channel 0: Raw: 3840
[00:04:57.045,157] <inf> Output: = 843 mV
[00:04:58.045,282] <inf> Output: ADC reading[298]: adc@d5000, channel 0: Raw: 4928
[00:04:58.045,290] <inf> Output: = 1082 mV
[00:04:59.045,433] <inf> Output: ADC reading[299]: adc@d5000, channel 0: Raw: 8256
[00:04:59.045,445] <inf> Output: = 1814 mV
[00:05:00.045,570] <inf> Output: ADC reading[300]: adc@d5000, channel 0: Raw: 8240
[00:05:00.045,578] <inf>Output: = 1810 mV
The previous sequence shows that when the nRF54L15-DK SAADC was hooked up to VDIO is 1.8V, an open wire and the “ground” terminal, this shows is working for these conditions. The nRF54L15-DK available at DigiKey
is an excellent development platform for many demanding IoT applications.
Have a great day!
This article is also available in spanish here.
Este artículo esta disponible en español aquí.
