ADC using DPPI along with eeprom

Hi, am using the nrf52dk with nrf52832, nrf coonect sdk 2.5.1/ toolchain 2.5.2 and am building a prototype to aquire the signal from the ckp and cmp sensor in the car when its cranking to start and in order to do that am using the adc sample in the DPPI mode in order to aquire the 8000 samples for 1 channel then stop and save the data in the eeprom using the i2c.

the problem its that i cant figure it out how to save it in the eeprom using the i2c because its sends me an error and it cant write to the eeprom. 

Any suggestions how can i do that? 

I am posting my code 

case NRFX_SAADC_EVT_DONE:

            /* STEP 5.3 - Buffer has been filled. Do something with the data and proceed */
            int64_t average = 0;
            int16_t max = INT16_MIN;
            int16_t min = INT16_MAX;
            int16_t counter = 0x0000;//doy de alta el contador
            int16_t current_value; 
            int8_t high_byte = 0x00; //doy de alta los contadores que van a ir en la direeccion de la eeprom
            int8_t low_byte = 0x00;
            int ret;
            int8_t highbyte_current_value;
            int8_t lowbyte_current_value;
            for(int i=0; i < p_event->data.done.size; i++){
            
            high_byte=((counter>>8)&0xff);  //divido las direcciones de 8000 posiciones en el array en 2
            low_byte=(counter&0xff);
                current_value = ((int16_t *)(p_event->data.done.p_buffer))[i];
                highbyte_current_value=((current_value>>8)&0xff);
                lowbyte_current_value= (current_value&0xff);
               //LOG_INF("SAADC buffer %d filled with sample %d ",current_value,i);
                
    /* STEP 7 - Retrieve the API-specific device structure and make sure that the device is ready to use  */





                average += current_value;
                if(current_value > max){
                    max = current_value;
                }
                if(current_value < min){
                    min = current_value;
                }
            }
            average = average/p_event->data.done.size;
            LOG_INF("SAADC buffer at 0x%x filled with %d samples", (uint32_t)p_event->data.done.p_buffer, p_event->data.done.size);
            LOG_INF("AVG=%d, MIN=%d, MAX=%d", (int16_t)average, min, max);
            counter=counter+0x0001;
            //you only need the write address and the eeprom address you want to read from 
     
        uint8_t sensor_regs[3] ={Eeprom_addr_write,0x00,0x00};
        //uint8_t temp_reading[2]= {0xFF,0x00};
        uint8_t temp_reading[4];
        ret = i2c_write_read_dt(&dev_i2c,&sensor_regs,3,&temp_reading,4);
        k_busy_wait(SLEEP_TIME_MS);
          for(int z=0; z < 5; z++){
        printk("waiting... %x\n\r");
       
          }

		if(ret != 0){
			printk("Failed to write/Read I2C device address %x at Reg. %x \n\r", dev_i2c.addr,sensor_regs[0]);
		}
		else{
		printk("memory content write&read %x\n\r",temp_reading[0]);
		printk("memory content write&read %x\n\r",temp_reading[1]);
		printk("memory content write&read %x\n\r",temp_reading[2]);
		printk("memory content write&read %x\n\r",temp_reading[3]);
		}

        
         nrfx_timer_disable(&timer_instance);
            break;

Parents
  • Hi there,

    Exactly which function is returning the error and what error is returned?

    Have you been able to successfully write to the external memory before? 

    regards

    Jared 

  • Yes, i manage to succesfully write and read to the external eeprom program that only does that, but now i want to write the buffer from the ADC example using the DPPI to the eeprom but am having errors and its not working

    first let me show u the little program i made to make it work to write and read from the eeprom:

    uint8_t config[7] = {Eeprom_addr_write,0x00,0x00,0x00,0x01,0x02,0x03};
    
    	ret = i2c_write_dt(&dev_i2c, config, sizeof(config));
    		k_msleep(SLEEP_TIME_MS);
    	if(ret != 0){
    		printk("Failed to Write to I2C device address %x at Reg. %x \n", dev_i2c.addr,config[0]);
    		return -1;
    	}
    
    
    uint8_t data;
    ret = i2c_read_dt(&dev_i2c, &data, sizeof(data));
    k_msleep(SLEEP_TIME_MS);
    		if(ret != 0){
    			printk("Failed to read from I2C device address %x at Reg. %x \n\r", dev_i2c.addr,config[0]);
    		}
    		else{
    		printk("memory content first read %x\n\r",data);
    		}
    //you only need the write address and the eeprom address you want to read from 
    uint8_t sensor_regs[3] ={Eeprom_addr_write,0x00,0x00};
    //uint8_t temp_reading[2]= {0xFF,0x00};
    uint8_t temp_reading[4];
    ret = i2c_write_read_dt(&dev_i2c,&sensor_regs,3,&temp_reading,4);
    k_msleep(SLEEP_TIME_MS);
    		if(ret != 0){
    			printk("Failed to write/Read I2C device address %x at Reg. %x \n\r", dev_i2c.addr,sensor_regs[0]);
    		}
    		else{
    		printk("memory content write&read %x\n\r",temp_reading[0]);
    		printk("memory content write&read %x\n\r",temp_reading[1]);
    		printk("memory content write&read %x\n\r",temp_reading[2]);
    		printk("memory content write&read %x\n\r",temp_reading[3]);
    		}
    	while (1) {
    /* STEP 10 - Read the temperature from the sensor */
    
    /*conversion to MV may nto be supported*/
    
    /* STEP 11 - Convert the two bytes to a 12-bits */
    
    		//k_msleep(SLEEP_TIME_MS);
    	
    }
    }
    

    and i get succesfully the readings on the terminal as follow:

  • yep i already did that excercise regarding the lesson6 in the intermidate course, the problem am having it says that zephyr doesnt actually work with nfrx thats its my question. looks this its my code if u can take a look to point out any mistake am doing:

    /*
     * Copyright (c) 2023 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>
    #include <nrfx_saadc.h>
    #include <nrfx_timer.h>
    #include <helpers/nrfx_gppi.h>
    #if defined (DPPI_PRESENT)
    #include <nrfx_dppi.h>
    #else
    #include <nrfx_ppi.h>
    #endif
    /* STEP 3 - Include the header file of the I2C API */
    #include <zephyr/drivers/i2c.h>
    /* STEP 4.1 - Include the header file of printk() */
    #include<zephyr/sys/printk.h>
    
    
    LOG_MODULE_REGISTER(Lesson6_Exercise3, LOG_LEVEL_DBG);
    
    /* STEP 2 - Include header for nrfx drivers */
    
    
    /* STEP 3.1 - Define the SAADC sample interval in microseconds */
    #define SAADC_SAMPLE_INTERVAL_US 50
    
    /* STEP 4.1 - Define the buffer size for the SAADC */
    //#define SAADC_BUFFER_SIZE   4000
    #define SAADC_BUFFER_SIZE   8000
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   50
    
    
    /* STEP 8 - Define the I2C slave device address and the addresses of relevant registers */
    #define I2C0_NODE DT_NODELABEL(mysensor)
    #define Eeprom_addr 0b1010000
    #define Eeprom_addr_write 0b10100000
    #define Eeprom_addr_read 0b10100001
    
    
    
    /* STEP 3.2 - Declaring an instance of nrfx_timer for TIMER2. */
    const nrfx_timer_t timer_instance = NRFX_TIMER_INSTANCE(2);
    
    /* STEP 4.2 - Declare the buffers for the SAADC */
    static int16_t saadc_sample_buffer[2][SAADC_BUFFER_SIZE];
    //static int16_t saadc_sample_buffer_2[2][SAADC_BUFFER_SIZE];
    
    /* STEP 4.3 - Declare variable used to keep track of which buffer was last assigned to the SAADC driver */
    static uint32_t saadc_current_buffer = 0;
    //static uint32_t saadc_current_buffer_2 = 0;
    
    
    
    /* STEP 6 - Get the node identifier of the sensor */
    static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C0_NODE);
    
    
    
    static void configure_timer(void)
    {
        nrfx_err_t err;
    
        /* STEP 3.3 - Declaring timer config and intialize nrfx_timer instance. */
        nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(1000000);
        err = nrfx_timer_init(&timer_instance, &timer_config, NULL);
        if (err != NRFX_SUCCESS) {
    	LOG_ERR("nrfx_timer_init error: %08x", err);
    	return;
    }
    
        /* STEP 3.4 - Set compare channel 0 to generate event every SAADC_SAMPLE_INTERVAL_US. */
        uint32_t timer_ticks = nrfx_timer_us_to_ticks(&timer_instance,
         SAADC_SAMPLE_INTERVAL_US);
        nrfx_timer_extended_compare(&timer_instance,
         NRF_TIMER_CC_CHANNEL0,
          timer_ticks, 
          NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 
          false);
    
    }
    
    static void saadc_event_handler(nrfx_saadc_evt_t const * p_event)
    {
        nrfx_err_t err;
        switch (p_event->type)
        {
            case NRFX_SAADC_EVT_READY:
            
               /* STEP 5.1 - Buffer is ready, timer (and sampling) can be started. */
                nrfx_timer_enable(&timer_instance);
    
                break;                        
                
            case NRFX_SAADC_EVT_BUF_REQ:
            
                /* STEP 5.2 - Set up the next available buffer. Alternate between buffer 0 and 1 */
                err = nrfx_saadc_buffer_set(saadc_sample_buffer[(saadc_current_buffer++)%2], SAADC_BUFFER_SIZE);
                if (err != NRFX_SUCCESS) {
                LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
                 return;
                }
    
              /* err = nrfx_saadc_buffer_set(saadc_sample_buffer_2[(saadc_current_buffer_2++)%2], SAADC_BUFFER_SIZE);
                if (err != NRFX_SUCCESS) {
                LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
                 return;
                }
    */ 
                break;
    
            case NRFX_SAADC_EVT_DONE:
    
                /* STEP 5.3 - Buffer has been filled. Do something with the data and proceed */
                int64_t average = 0;
                int16_t max = INT16_MIN;
                int16_t min = INT16_MAX;
                int16_t counter = 0x0000;//doy de alta el contador
                int16_t current_value; 
                int8_t high_byte = 0x00; //doy de alta los contadores que van a ir en la direeccion de la eeprom
                int8_t low_byte = 0x00;
                int ret;
                int8_t highbyte_current_value;
                int8_t lowbyte_current_value;
                for(int i=0; i < p_event->data.done.size; i++){
                
                high_byte=((counter>>8)&0xff);  //divido las direcciones de 8000 posiciones en el array en 2
                low_byte=(counter&0xff);
                    current_value = ((int16_t *)(p_event->data.done.p_buffer))[i];
                    highbyte_current_value=((current_value>>8)&0xff);
                    lowbyte_current_value= (current_value&0xff);
                   //LOG_INF("SAADC buffer %d filled with sample %d ",current_value,i);
                    
        /* STEP 7 - Retrieve the API-specific device structure and make sure that the device is ready to use  */
    
    
    
    
    
                    average += current_value;
                    if(current_value > max){
                        max = current_value;
                    }
                    if(current_value < min){
                        min = current_value;
                    }
                }
                average = average/p_event->data.done.size;
                LOG_INF("SAADC buffer at 0x%x filled with %d samples", (uint32_t)p_event->data.done.p_buffer, p_event->data.done.size);
                LOG_INF("AVG=%d, MIN=%d, MAX=%d", (int16_t)average, min, max);
               // counter=counter+0x0001;
                //you only need the write address and the eeprom address you want to read from 
          
    
    
    uint8_t config[7] = {Eeprom_addr_write,0x00,0x00,0x00,0x01,0x02,0x03};
    uint8_t data;
    ret = i2c_read_dt(&dev_i2c, &data, sizeof(data));
    k_msleep(SLEEP_TIME_MS);
    		if(ret != 0){
    			printk("Failed to read from I2C device address %x at Reg. %x \n\r", dev_i2c.addr,config[0]);
    		}
    		else{
    		printk("memory content first read %d\n\r",data);
    		}
    
    /*
            uint8_t sensor_regs[3] ={Eeprom_addr_write,0x00,0x00};
            //uint8_t temp_reading[2]= {0xFF,0x00};
            uint8_t temp_reading[4];
            ret = i2c_write_read_dt(&dev_i2c,&sensor_regs,3,&temp_reading,4);
            k_busy_wait(SLEEP_TIME_MS);
              for(int z=0; z < 5; z++){
            printk("waiting... %x\n\r");
           
              }
    
    		if(ret != 0){
    			printk("Failed to write/Read I2C device address %x at Reg. %x \n\r", dev_i2c.addr,sensor_regs[0]);
    		}
    		else{
    		printk("memory content write&read %x\n\r",temp_reading[0]);
    		printk("memory content write&read %x\n\r",temp_reading[1]);
    		printk("memory content write&read %x\n\r",temp_reading[2]);
    		printk("memory content write&read %x\n\r",temp_reading[3]);
    		}
    
           */ 
             nrfx_timer_disable(&timer_instance);
                break;
    
            default:
                LOG_INF("Unhandled SAADC evt %d", p_event->type);
    
                break;
              
        }
    }
    
    static void configure_saadc(void)
    {
        nrfx_err_t err;
    
        /* STEP 4.4 - Connect ADC interrupt to nrfx interrupt handler */
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(adc)),
                DT_IRQ(DT_NODELABEL(adc), priority),
                nrfx_isr, nrfx_saadc_irq_handler, 0);
    
        
        /* STEP 4.5 - Initialize the nrfx_SAADC driver */
        err = nrfx_saadc_init(DT_IRQ(DT_NODELABEL(adc), priority));
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_init error: %08x", err);
        return;
    }
    
        
        /* STEP 4.6 - Declare the struct to hold the configuration for the SAADC channel used to sample the battery voltage */
       nrfx_saadc_channel_t channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0);
       // nrfx_saadc_channel_t channel_2 = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN1, 1);
        //nrfx_saadc_channel_t channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(SAADC_CH_PSELP_PSELP_VDD, 0);
    
        /* STEP 4.7 - Change gain config in default config and apply channel configuration */
        channel.channel_config.gain = NRF_SAADC_GAIN1_6;
        err = nrfx_saadc_channels_config(&channel, 1);
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_channels_config error: %08x", err);
        return;
    }
    
        /* STEP 4.8 - Configure channel 0 in advanced mode with event handler (non-blocking mode) */
        nrfx_saadc_adv_config_t saadc_adv_config = NRFX_SAADC_DEFAULT_ADV_CONFIG;
        err = nrfx_saadc_advanced_mode_set(BIT(0),
        NRF_SAADC_RESOLUTION_12BIT,
        &saadc_adv_config,
        saadc_event_handler);
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_advanced_mode_set error: %08x", err);
        return;
    }
                                                
        /* STEP 4.9 - Configure two buffers to make use of double-buffering feature of SAADC */
       err = nrfx_saadc_buffer_set(saadc_sample_buffer[0], SAADC_BUFFER_SIZE);
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
        return;
    }
    err = nrfx_saadc_buffer_set(saadc_sample_buffer[1], SAADC_BUFFER_SIZE);
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
        return;
    }
        /* STEP 4.10 - Trigger the SAADC. This will not start sampling, but will prepare buffer for sampling triggered through PPI */
    err = nrfx_saadc_mode_trigger();
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_mode_trigger error: %08x", err);
        return;
    }
    
    }
    
    static void configure_ppi(void)
    {
        nrfx_err_t err;
        /* STEP 6.1 - Declare variables used to hold the (D)PPI channel number */
        uint8_t m_saadc_sample_ppi_channel;
        uint8_t m_saadc_start_ppi_channel;
       // uint8_t m_saadc_stop_ppi_channel;
    
        /* STEP 6.2 - Trigger task sample from timer */
        err = nrfx_gppi_channel_alloc(&m_saadc_sample_ppi_channel);
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
        return;
        }
    
    err = nrfx_gppi_channel_alloc(&m_saadc_start_ppi_channel);
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
        return;
        }
    
     //   err = nrfx_gppi_channel_alloc(&m_saadc_stop_ppi_channel);
     //   if (err != NRFX_SUCCESS) {
     //   LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
     //   return;
     //   }
    
    
        /* STEP 6.3 - Trigger task sample from timer */
        nrfx_gppi_channel_endpoints_setup(m_saadc_sample_ppi_channel, 
        nrfx_timer_compare_event_address_get(&timer_instance, NRF_TIMER_CC_CHANNEL0),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE));
    
        /* STEP 6.4 - Trigger task start from end event */
        nrfx_gppi_channel_endpoints_setup(m_saadc_start_ppi_channel, 
        nrf_saadc_event_address_get(NRF_SAADC, NRF_SAADC_EVENT_END),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_START));
    
        /* STEP 6.6 - End task sample from timer */
       /* nrfx_gppi_channel_endpoints_setup(m_saadc_stop_ppi_channel, 
        nrfx_timer_compare_event_address_get(&timer_instance, NRF_TIMER_CC_CHANNEL0),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_STOP));
    */
        /* STEP 6.5 - Enable both (D)PPI channels */ 
        nrfx_gppi_channels_enable(BIT(m_saadc_sample_ppi_channel));
        nrfx_gppi_channels_enable(BIT(m_saadc_start_ppi_channel));
        // nrfx_gppi_channels_enable(BIT(m_saadc_stop_ppi_channel));
    
        
        
    }
    
    
    int main(void)
    {
       
     
    /* STEP 7 - Retrieve the API-specific device structure and make sure that the device is ready to use  */
    
    if (!device_is_ready(dev_i2c.bus)) {
    	printk("I2C bus %s is not ready!\n\r",dev_i2c.bus->name);
    	return;
    }
        configure_timer();
        configure_saadc();  
        configure_ppi();
       
       
       k_sleep(K_FOREVER);
       
    }
    

  • Ah, I think I understand now.

    So you use Zephyr for i2c, and nrfx for the ADC.

    Correct?

  • It should be possible to do this.

    I suggest that you start by using only the zephyr i2c driver to write some dummy data to the eeprom. (With no other code in the same project)
    Have you tried that?

  • its like if i flash the program to read and write to the eeporm alone using the zephyr i2c driver it works, then if i flash the program for the ADC alone it works. the issue its when i put together these two i get the error.

Reply Children
  • Next up, in the example with both:

    Do not call the i2c from the saadc handler, but write some dummy data to the eeprom memory from a loop in main(). Use k_sleep() between each of the loop.

    Does this work?

  • Alhamdulillah Sigurd,

    Already worked and managed to read from the eeporm that way

    /*
     * Copyright (c) 2023 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>
    #include <nrfx_saadc.h>
    #include <nrfx_timer.h>
    #include <helpers/nrfx_gppi.h>
    #if defined (DPPI_PRESENT)
    #include <nrfx_dppi.h>
    #else
    #include <nrfx_ppi.h>
    #endif
    /* STEP 3 - Include the header file of the I2C API */
    #include <zephyr/drivers/i2c.h>
    /* STEP 4.1 - Include the header file of printk() */
    #include<zephyr/sys/printk.h>
    
    
    LOG_MODULE_REGISTER(Lesson6_Exercise3, LOG_LEVEL_DBG);
    
    /* STEP 2 - Include header for nrfx drivers */
    
    
    /* STEP 3.1 - Define the SAADC sample interval in microseconds */
    #define SAADC_SAMPLE_INTERVAL_US 50
    
    /* STEP 4.1 - Define the buffer size for the SAADC */
    //#define SAADC_BUFFER_SIZE   4000
    #define SAADC_BUFFER_SIZE   8000
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   50
    
    
    /* STEP 8 - Define the I2C slave device address and the addresses of relevant registers */
    #define I2C0_NODE DT_NODELABEL(mysensor)
    #define Eeprom_addr 0b1010000
    #define Eeprom_addr_write 0b10100000
    #define Eeprom_addr_read 0b10100001
    
    
    
    /* STEP 3.2 - Declaring an instance of nrfx_timer for TIMER2. */
    const nrfx_timer_t timer_instance = NRFX_TIMER_INSTANCE(2);
    
    /* STEP 4.2 - Declare the buffers for the SAADC */
    static int16_t saadc_sample_buffer[2][SAADC_BUFFER_SIZE];
    //static int16_t saadc_sample_buffer_2[2][SAADC_BUFFER_SIZE];
    
    /* STEP 4.3 - Declare variable used to keep track of which buffer was last assigned to the SAADC driver */
    static uint32_t saadc_current_buffer = 0;
    //static uint32_t saadc_current_buffer_2 = 0;
    
    
    
    /* STEP 6 - Get the node identifier of the sensor */
    static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C0_NODE);
    
    
    
    static void configure_timer(void)
    {
        nrfx_err_t err;
    
        /* STEP 3.3 - Declaring timer config and intialize nrfx_timer instance. */
        nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(1000000);
        err = nrfx_timer_init(&timer_instance, &timer_config, NULL);
        if (err != NRFX_SUCCESS) {
    	LOG_ERR("nrfx_timer_init error: %08x", err);
    	return;
    }
    
        /* STEP 3.4 - Set compare channel 0 to generate event every SAADC_SAMPLE_INTERVAL_US. */
        uint32_t timer_ticks = nrfx_timer_us_to_ticks(&timer_instance,
         SAADC_SAMPLE_INTERVAL_US);
        nrfx_timer_extended_compare(&timer_instance,
         NRF_TIMER_CC_CHANNEL0,
          timer_ticks, 
          NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 
          false);
    
    }
    
    static void saadc_event_handler(nrfx_saadc_evt_t const * p_event)
    {
        nrfx_err_t err;
        switch (p_event->type)
        {
            case NRFX_SAADC_EVT_READY:
            
               /* STEP 5.1 - Buffer is ready, timer (and sampling) can be started. */
                nrfx_timer_enable(&timer_instance);
    
                break;                        
                
            case NRFX_SAADC_EVT_BUF_REQ:
            
                /* STEP 5.2 - Set up the next available buffer. Alternate between buffer 0 and 1 */
                err = nrfx_saadc_buffer_set(saadc_sample_buffer[(saadc_current_buffer++)%2], SAADC_BUFFER_SIZE);
                if (err != NRFX_SUCCESS) {
                LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
                 return;
                }
    
              /* err = nrfx_saadc_buffer_set(saadc_sample_buffer_2[(saadc_current_buffer_2++)%2], SAADC_BUFFER_SIZE);
                if (err != NRFX_SUCCESS) {
                LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
                 return;
                }
    */ 
                break;
    
            case NRFX_SAADC_EVT_DONE:
    
                /* STEP 5.3 - Buffer has been filled. Do something with the data and proceed */
                int64_t average = 0;
                int16_t max = INT16_MIN;
                int16_t min = INT16_MAX;
                int16_t counter = 0x0000;//doy de alta el contador
                int16_t current_value; 
                int8_t high_byte = 0x00; //doy de alta los contadores que van a ir en la direeccion de la eeprom
                int8_t low_byte = 0x00;
                //int ret;
                int8_t highbyte_current_value;
                int8_t lowbyte_current_value;
                for(int i=0; i < p_event->data.done.size; i++){
                
                high_byte=((counter>>8)&0xff);  //divido las direcciones de 8000 posiciones en el array en 2
                low_byte=(counter&0xff);
                    current_value = ((int16_t *)(p_event->data.done.p_buffer))[i];
                    highbyte_current_value=((current_value>>8)&0xff);
                    lowbyte_current_value= (current_value&0xff);
                   //LOG_INF("SAADC buffer %d filled with sample %d ",current_value,i);
                    
        /* STEP 7 - Retrieve the API-specific device structure and make sure that the device is ready to use  */
    
    
    
    
    
                    average += current_value;
                    if(current_value > max){
                        max = current_value;
                    }
                    if(current_value < min){
                        min = current_value;
                    }
                }
                average = average/p_event->data.done.size;
                LOG_INF("SAADC buffer at 0x%x filled with %d samples", (uint32_t)p_event->data.done.p_buffer, p_event->data.done.size);
                LOG_INF("AVG=%d, MIN=%d, MAX=%d", (int16_t)average, min, max);
               // counter=counter+0x0001;
                //you only need the write address and the eeprom address you want to read from 
          
    
    
    
    nrfx_timer_disable(&timer_instance);
    /*
            uint8_t sensor_regs[3] ={Eeprom_addr_write,0x00,0x00};
            //uint8_t temp_reading[2]= {0xFF,0x00};
            uint8_t temp_reading[4];
            ret = i2c_write_read_dt(&dev_i2c,&sensor_regs,3,&temp_reading,4);
            k_busy_wait(SLEEP_TIME_MS);
              for(int z=0; z < 5; z++){
            printk("waiting... %x\n\r");
           
              }
    
    		if(ret != 0){
    			printk("Failed to write/Read I2C device address %x at Reg. %x \n\r", dev_i2c.addr,sensor_regs[0]);
    		}
    		else{
    		printk("memory content write&read %x\n\r",temp_reading[0]);
    		printk("memory content write&read %x\n\r",temp_reading[1]);
    		printk("memory content write&read %x\n\r",temp_reading[2]);
    		printk("memory content write&read %x\n\r",temp_reading[3]);
    		}
    
           */
             
                break;
    
            default:
                LOG_INF("Unhandled SAADC evt %d", p_event->type);
    
                break;
              
        }
    }
    
    static void configure_saadc(void)
    {
        nrfx_err_t err;
    
        /* STEP 4.4 - Connect ADC interrupt to nrfx interrupt handler */
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(adc)),
                DT_IRQ(DT_NODELABEL(adc), priority),
                nrfx_isr, nrfx_saadc_irq_handler, 0);
    
        
        /* STEP 4.5 - Initialize the nrfx_SAADC driver */
        err = nrfx_saadc_init(DT_IRQ(DT_NODELABEL(adc), priority));
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_init error: %08x", err);
        return;
    }
    
        
        /* STEP 4.6 - Declare the struct to hold the configuration for the SAADC channel used to sample the battery voltage */
       nrfx_saadc_channel_t channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0);
       // nrfx_saadc_channel_t channel_2 = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN1, 1);
        //nrfx_saadc_channel_t channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(SAADC_CH_PSELP_PSELP_VDD, 0);
    
        /* STEP 4.7 - Change gain config in default config and apply channel configuration */
        channel.channel_config.gain = NRF_SAADC_GAIN1_6;
        err = nrfx_saadc_channels_config(&channel, 1);
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_channels_config error: %08x", err);
        return;
    }
    
        /* STEP 4.8 - Configure channel 0 in advanced mode with event handler (non-blocking mode) */
        nrfx_saadc_adv_config_t saadc_adv_config = NRFX_SAADC_DEFAULT_ADV_CONFIG;
        err = nrfx_saadc_advanced_mode_set(BIT(0),
        NRF_SAADC_RESOLUTION_12BIT,
        &saadc_adv_config,
        saadc_event_handler);
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_advanced_mode_set error: %08x", err);
        return;
    }
                                                
        /* STEP 4.9 - Configure two buffers to make use of double-buffering feature of SAADC */
       err = nrfx_saadc_buffer_set(saadc_sample_buffer[0], SAADC_BUFFER_SIZE);
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
        return;
    }
    err = nrfx_saadc_buffer_set(saadc_sample_buffer[1], SAADC_BUFFER_SIZE);
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
        return;
    }
        /* STEP 4.10 - Trigger the SAADC. This will not start sampling, but will prepare buffer for sampling triggered through PPI */
    err = nrfx_saadc_mode_trigger();
    if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_saadc_mode_trigger error: %08x", err);
        return;
    }
    
    }
    
    static void configure_ppi(void)
    {
        nrfx_err_t err;
        /* STEP 6.1 - Declare variables used to hold the (D)PPI channel number */
        uint8_t m_saadc_sample_ppi_channel;
        uint8_t m_saadc_start_ppi_channel;
       // uint8_t m_saadc_stop_ppi_channel;
    
        /* STEP 6.2 - Trigger task sample from timer */
        err = nrfx_gppi_channel_alloc(&m_saadc_sample_ppi_channel);
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
        return;
        }
    
    err = nrfx_gppi_channel_alloc(&m_saadc_start_ppi_channel);
        if (err != NRFX_SUCCESS) {
        LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
        return;
        }
    
     //   err = nrfx_gppi_channel_alloc(&m_saadc_stop_ppi_channel);
     //   if (err != NRFX_SUCCESS) {
     //   LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
     //   return;
     //   }
    
    
        /* STEP 6.3 - Trigger task sample from timer */
        nrfx_gppi_channel_endpoints_setup(m_saadc_sample_ppi_channel, 
        nrfx_timer_compare_event_address_get(&timer_instance, NRF_TIMER_CC_CHANNEL0),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE));
    
        /* STEP 6.4 - Trigger task start from end event */
        nrfx_gppi_channel_endpoints_setup(m_saadc_start_ppi_channel, 
        nrf_saadc_event_address_get(NRF_SAADC, NRF_SAADC_EVENT_END),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_START));
    
        /* STEP 6.6 - End task sample from timer */
       /* nrfx_gppi_channel_endpoints_setup(m_saadc_stop_ppi_channel, 
        nrfx_timer_compare_event_address_get(&timer_instance, NRF_TIMER_CC_CHANNEL0),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_STOP));
    */
        /* STEP 6.5 - Enable both (D)PPI channels */ 
        nrfx_gppi_channels_enable(BIT(m_saadc_sample_ppi_channel));
        nrfx_gppi_channels_enable(BIT(m_saadc_start_ppi_channel));
        // nrfx_gppi_channels_enable(BIT(m_saadc_stop_ppi_channel));
    
        
        
    }
    
    
    int main(void)
    {
       if (!device_is_ready(dev_i2c.bus)) {
    	printk("I2C bus %s is not ready!\n\r",dev_i2c.bus->name);
    	return;
    }
     
    /* STEP 7 - Retrieve the API-specific device structure and make sure that the device is ready to use  */
    
    
        configure_timer();
        configure_saadc();  
        configure_ppi();
    
        uint8_t config[7] = {Eeprom_addr_write,0x00,0x00,0x00,0x01,0x02,0x03};
        uint8_t data;
        int ret;
        ret = i2c_read_dt(&dev_i2c, &data, sizeof(data));
        k_sleep(K_MSEC(50));
    		if(ret != 0){
    			printk("Failed to read from I2C device address %x at Reg. %x \n\r", dev_i2c.addr,config[0]);
    		}
    		else{ printk("memory content first read %x\n\r",data);
    		}
       
       
       k_sleep(K_FOREVER);
    
       
    }
    

  • That is good!

    In that case, I suspect that it is because you try to use the I2C from the ADC callback.

    Try to use a Zephyr Workqueue, and then make a Work Thread to read from the I2C. Then add this Work Thread from the ADC callback.

  • Sigurd,

    is there no other way to extract the samples from the done event and save them in the eeprom on the main program?

  • Just to be clear:
    I do not know 100% that the case is that you use the I2C from the ADC callback.

    It would be good to try to do that from another thread first just to test.

    If we find that this fixes the issue, we can look closer at alternative solutions at that point

Related