How to interface with an MCP4725 on a custom board based on the nRF52832 SoC

Hi,

We need to control an MCP4725 DAC from an nRF52832 SoC, and for one reason or the other, no example we've found works.

This next was the last attempt, based on the examples from "\nordic\v2.3.0\zephyr\samples\drivers\dac". I created the board files in a folder, separated from the project, and added that folder to BOARD_ROOT.

1) Added the i2c node in the dts as:

&i2c0 {
    compatible = "nordic,nrf-twi";
    status = "okay";

    pinctrl-0 = <&i2c0_default>;
    pinctrl-1 = <&i2c0_sleep>;
    pinctrl-names = "default", "sleep";
    dac0: mcp4725@60 {
        compatible = "microchip,mcp4725";
        reg = <0x60>;
        #io-channel-cells = <1>;
    };
};

2) In defined the pins in the dtsi:

 &pinctrl {
    i2c0_default: i2c0_default {
        group1 {
            psels = <NRF_PSEL(TWIM_SDA, 0, 7)>,
                <NRF_PSEL(TWIM_SCL, 0, 6)>;
                bias-pull-up;
        };
    };

    i2c0_sleep: i2c0_sleep {
        group1 {
            psels = <NRF_PSEL(TWIM_SDA, 0, 7)>,
                <NRF_PSEL(TWIM_SCL, 0, 6)>;
            low-power-enable;
        };
    };
};

3) Added this to the overlay file:

/ {
    zephyr,user {
        dac = <&dac0>;
        dac-channel-id = <0>;
        dac-resolution = <12>;
    };
};

4) Enabled required modules in prj.conf:

CONFIG_GPIO=y
CONFIG_NFCT_PINS_AS_GPIOS=y
CONFIG_I2C=y
CONFIG_PINCTRL=y
CONFIG_DAC=y
CONFIG_DAC_MCP4725=y

5) And used following code, extracted from the dac example:

#if (DT_NODE_HAS_PROP(ZEPHYR_USER_NODE, dac) && \
    DT_NODE_HAS_PROP(ZEPHYR_USER_NODE, dac_channel_id) && \
    DT_NODE_HAS_PROP(ZEPHYR_USER_NODE, dac_resolution))
#define DAC_NODE DT_PHANDLE(ZEPHYR_USER_NODE, dac)
#define DAC_CHANNEL_ID DT_PROP(ZEPHYR_USER_NODE, dac_channel_id)
#define DAC_RESOLUTION DT_PROP(ZEPHYR_USER_NODE, dac_resolution)
#else
#error "Unsupported board: see README and check /zephyr,user node"
#define DAC_NODE DT_INVALID_NODE
#define DAC_CHANNEL_ID 0
#define DAC_RESOLUTION 0
#endif

static const struct device *const dac_dev = DEVICE_DT_GET(DAC_NODE);

static const struct dac_channel_cfg dac_ch_cfg = {
    .channel_id  = DAC_CHANNEL_ID,
    .resolution  = DAC_RESOLUTION
};

static bool init_dac()
{
    if (!device_is_ready(dac_dev)) {
        printk("DAC device %s is not ready\n", dac_dev->name);
        return false;
    }

    int ret = dac_channel_setup(dac_dev, &dac_ch_cfg);

    if (ret != 0) {
        printk("Setting up of DAC channel failed with code %d\n", ret);
        return false;
    }

---- etc -----

The result is device_is_ready(...) always returns false.

Where can I find a working example of controlling an MCP4725 DAC from a nRF52832?

BR

Parents
  • Hi,

    Are you able to get a logic trace of the i2c pins? device_is_ready() checks whether the device was initialized correctly, and in the initialization of MCP4725 the driver tries to read RDY from the device. It would be good to see if the command fails to send or if the device fails to respond.

  • Hi,

    I was able to get a "no" logic trace on the i2c pins. The device was not initialising the pins and was not producing any output on them, back then when I tested this last week.

    Now I've deleted everything today and started from scratch, creating the custom board inside the project, adding the i2c0 element to the .dts, like below, and including the pinctrl in the .dtsi. Following this I made a pristine build, closed VSC, opened again, and flashed the device.

    After doing this the i2c signals do change. It is a 5-byte read operation which produces, hex: [C0, 80, 00, 08, 00].

    This is what I have in the dts. How do I instanciate dac0 in the program and how do I get access to its API?

    &i2c0 {
      compatible = "nordic,nrf-twi";

      status = "okay";
      clock-frequency = < I2C_BITRATE_STANDARD >;

      pinctrl-0 = <&i2c0_default>;
      pinctrl-1 = <&i2c0_sleep>;
      pinctrl-names = "default", "sleep";

      dac0: mcp4725@60 {
        compatible = "microchip,mcp4725";
        reg = <0x60>;
        #io-channel-cells = <1>;
      };
    };

    I've also removed all code I was using for testing. Now the only code accessing the device is zephyr's initialization code itself.

  • Sorry for the delay, so does device_is_ready() return true now, using the code from the dac sample? It should if I am reading that correctly.

Reply Children
  • Hi,

    I moved away from the code for the dac sample, it did not work for me and it also considered having an extra overlay that was unnecessary for my case.

    I created an alias in my dts (namely refdac), just for convenience, and I was able to get a pointer to the dac driver's instance using DEVICE_DT_GET(DT_ALIAS(refdac)).

    From that point on, I used that reference and the dac's driver API.

    I've been experiencing a lot of issues with VSC that, my best guess is, can be traced down to the nRF Connect and related extensions.

    So, for anyone coming next to same issues:

    1) Create the dts for your specific board,

    2) Add the DAC node into the i2c bus, just like in the dts excerpt in my previous post.

    3) In the aliases section of the dts, add a line with an alias for the dac, like: refdac = &dac0;

    4) In application code, a pointer to the dac's driver instance can be obtained using something similar to struct device const *dev = DEVICE_DT_GET(DT_ALIAS(refdac))refdac is the dac's alias, as per the aliases section of the dts.

    5) the rest is just as simple as using calls like: device_is_ready(dev), for checking the device status, and dac_write_value(dev, 0 /*channel*/ , 0 /*value*/) for writing to the dac.

    6) Go to the nRF Connect extension's configuration and make sure the BOARD_ROOT setting has absolute paths in Windows formats (including the drive letter). This is a requirement for my specific case as I have my projects and the Nordic's SDK and toolchain installations in a different drive from windows' main drive.

    7) Close VSCode, and restart, then make a pristine build.

    Steps 6) and 7) are required every time a new project that includes .overlay, .dts or board files/folders is added to the workspace.

    BR

Related