This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf52 with Mynewt multi channel ADC configuration

Hi all,

We are using nrf52 DK (both pca10040 and 10056) to develop a multi-channel ADC sampling module running Mynewt.

The example ADC code with Mynewt is a single-channel one and it works. We need to add more channels to include more analog inputs.

We met difficulties in adding more channels and the Mynewt team did not provide helpful suggestions in this regard.

With the following modified code, we can have the first channel (no matter which PIN/AINx it is assigned) return a correct value, however, the second channel (again no matter which PIN/AINx it is assigned) always returns a value of 0. We are not sure if this is 1) a problem with the Channel Configuration or 2) the method that we retrieve the sampled value is not correct. 

Would you please help look into that? Your time and help are highly appreciated! Thanks,

Code:

#include "syscfg/syscfg.h"
#include "sysinit/sysinit.h"
#include <os/os.h>
#include <bsp/bsp.h>
#include <adc/adc.h>
#include <adc_nrf52/adc_nrf52.h>
#include <console/console.h>

#include <string.h>

#define ADC_NUMBER_SAMPLES (2)
#define ADC_NUMBER_CHANNELS (2)
#define ADC_CHANNEL_0 (0)
#define ADC_CHANNEL_1 (1)

/* /\* ADC Task settings *\/ */
#define ADC_TASK_PRIO           (0)
#define ADC_STACK_SIZE          (OS_STACK_ALIGN(128))
struct os_task adc_task;
os_stack_t adc_stack[ADC_STACK_SIZE];
struct adc_dev *adc;

//#define BLOCKING 1

#ifndef BLOCKING
static uint16_t * value;
uint8_t *sample_buffer1;
uint8_t *sample_buffer2;

uint16_t *
adc_read(void *buffer, int buffer_len)
{
    int i;
    int adc_result;
    uint16_t result_mv[2];
    int rc;

    for (j = 0; j < ADC_NUMBER_CHANNELS - 1; j++) {
        for (i = 0; i < ADC_NUMBER_SAMPLES - 1; i++) {
            rc = adc_buf_read(adc, buffer, buffer_len, i, &adc_result);
            if (rc != 0) {
                goto err;
            }
            console_printf("VAL:%d\n", adc_result);
            result_mv[j] = adc_result_mv(adc, 0, adc_result);
        }
        adc_buf_release(adc, buffer, buffer_len);
    }
    
    
    return result_mv;
err:
    return (-rc);
}

int
adc_read_event(struct adc_dev *dev,
               void *arg,
               uint8_t etype,
               void *buffer,
               int buffer_len)
{
    int rc = 0xFFFFFFFF;

    switch (etype) {
    case ADC_EVENT_CALIBRATED:
        console_printf("CALIBRATED\n");
        break;
    case ADC_EVENT_RESULT:
        value = adc_read(buffer, buffer_len);
        (void) value;
        break;
    default:
        goto err;
    }

    return (0);
err:
    return (rc);
}
#endif

static void
adc_init()
{
    struct adc_dev_cfg cfg = {
        .resolution = ADC_RESOLUTION_12BIT,
        .oversample = ADC_OVERSAMPLE_DISABLED,
        .calibrate = false
    };

    struct adc_chan_cfg channel_0_config = {
        .reference = ADC_REFERENCE_INTERNAL,
        .gain = ADC_GAIN1_2,
        .pin = 3,
        .differential = false,
        .pin_negative = 0
    };

    struct adc_chan_cfg channel_1_config = {
        .reference = ADC_REFERENCE_INTERNAL,
        .gain = ADC_GAIN1_2,
        .pin = 5,
        .differential = false,
        .pin_negative = 0
    };
    adc = (struct adc_dev *) os_dev_open("adc0",
                                         OS_TIMEOUT_NEVER,
                                         &cfg);
    assert(adc != NULL);
    adc_chan_config(adc, ADC_CHANNEL_0, &channel_0_config);
    adc_chan_config(adc, ADC_CHANNEL_1, &channel_1_config);

#ifndef BLOCKING
    int rc;
    sample_buffer1 = malloc(adc_buf_size(adc,
                                         ADC_NUMBER_CHANNELS,
                                         ADC_NUMBER_SAMPLES));
    sample_buffer2 = malloc(adc_buf_size(adc,
                                         ADC_NUMBER_CHANNELS,
                                         ADC_NUMBER_SAMPLES));

    memset(sample_buffer1, 0, adc_buf_size(adc,
                                           ADC_NUMBER_CHANNELS,
                                           ADC_NUMBER_SAMPLES));
    memset(sample_buffer2, 0, adc_buf_size(adc,
                                           ADC_NUMBER_CHANNELS,
                                           ADC_NUMBER_SAMPLES));
    rc = adc_buf_set(adc,
                sample_buffer1,
                sample_buffer2,
                adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
    assert(rc == 0);
#endif
}

/**
 * Event loop for the sensor task.
 */
static void
adc_task_handler(void *unused)
{
    int rc;
#ifdef BLOCKING
    int result;
#endif

    adc_init();

#ifndef BLOCKING
    rc = adc_event_handler_set(adc, adc_read_event, (void *) NULL);
    assert(rc == 0);
#endif

    while (1) {
#ifndef BLOCKING
        rc = adc_sample(adc);
        assert(rc == 0);
        if (value >= 0) {
            console_printf("Ch0 Got %dmv\n", value);
            console_printf("Ch1 Got %dmv\n", *(&value + 1));
        } else {
            console_printf("Error while reading: %d\n", value);
        }

#else
        rc = adc_read_channel(adc, 0, &result);
        assert(rc == 0);
        console_printf("VAL:%d\n", result);
#endif
        /* Wait 2 second */
        os_time_delay(OS_TICKS_PER_SEC * 2);
    }
}

int
main(int argc, char **argv)
{
    sysinit();
    console_printf("Started \n");
    os_task_init(&adc_task,
                 "sensor",
                 adc_task_handler,
                 NULL,
                 ADC_TASK_PRIO,
                 OS_WAIT_FOREVER,
                 adc_stack,
                 ADC_STACK_SIZE);

    while (1) {
        os_eventq_run(os_eventq_dflt_get());
    }
    assert(0);
    return(0);
}

Parents
  • I solved the problem. It was caused by code error in the value readout function:

    below is the correct one which works now.

    uint16_t *
    adc_read(void *buffer, int buffer_len)
    {
        int i;
        int j;
        int adc_result;
    
        for (j = 0; j < ADC_NUMBER_CHANNELS; j++) {
            for (i = 0; i < ADC_NUMBER_SAMPLES - 1; i++) {
                adc_buf_read(adc, buffer, buffer_len, j, &adc_result);
                adc_buf_release(adc, buffer, buffer_len);
            }
            result_mv[j] = adc_result_mv(adc, j, adc_result); // RESULT = (V(P) – V(N)) * (GAIN/REFERENCE) * 2^RESOLUTION
        }
    
        return result_mv;
    }
Reply
  • I solved the problem. It was caused by code error in the value readout function:

    below is the correct one which works now.

    uint16_t *
    adc_read(void *buffer, int buffer_len)
    {
        int i;
        int j;
        int adc_result;
    
        for (j = 0; j < ADC_NUMBER_CHANNELS; j++) {
            for (i = 0; i < ADC_NUMBER_SAMPLES - 1; i++) {
                adc_buf_read(adc, buffer, buffer_len, j, &adc_result);
                adc_buf_release(adc, buffer, buffer_len);
            }
            result_mv[j] = adc_result_mv(adc, j, adc_result); // RESULT = (V(P) – V(N)) * (GAIN/REFERENCE) * 2^RESOLUTION
        }
    
        return result_mv;
    }
Children
No Data
Related