This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[Contiki][CC2650] how to use the ADC

Other Parts Discussed in Thread: CC2650

Hey everyone.

 I wonder how we can use the CC2650 senssortag ADC with the contiki software.


I created this code, getting inspired with this topic https://e2e.ti.com/support/wireless_connectivity/f/538/p/404426/1433112#1433112

#define SAMPLETYPE uint16_t


static SAMPLETYPE get_adc(void)
{
        SAMPLETYPE singleSample;

	//intialisation of ADC
	// Enable clock for ADC digital and analog interface (not currently enabled in driver)
	AUXWUCClockEnable(AUX_WUC_ADI_CLOCK|AUX_WUC_SOC_CLOCK);   // was : AUX_WUC_MODCLKEN0_SOC_M|AUX_WUC_MODCLKEN0_AUX_ADI4_M);
	printf("clock selected\r\n");
	
	// Connect AUX IO7 (DIO23 & DP2) as analog input.
	AUXADCSelectInput(ADC_COMPB_IN_AUXIO7);  
	printf("input selected\r\n");
	
	// Set up ADC range
	// AUXADC_REF_FIXED = nominally 4.3 V
	AUXADCEnableAsync(AUXADC_REF_FIXED, AUXADC_TRIGGER_MANUAL);
	printf("init adc --- OK\r\n");
		
	//Trigger ADC converting
	AUXADCGenManualTrigger();
	printf("trigger --- OK\r\n");
	
	//reading adc value
	singleSample = AUXADCReadFifo();
	printf("reading --- OK\r\n");
	
	AUXADCFlushFifo();
	printf("flush --- OK\r\n");
	
	//shut the adc down
	AUXADCDisable();
	printf("disable --- OK\r\n");
	
	return singleSample;
	
}



But this doesn't work. Actually i work only once, but then it does'nt.

I tried to separate the init to the trigger and reading, but it is the same. I think it should be a flag problem. Any ideas ?

 

  • Moving this to "Bluetooth Low Energy Forum"

    Regards,
    Gigi Joseph.
  • The error came from the use of an etimer in the while loop calling the function written up there.

    Here is the sample of code who works fine, showing the ADC value on DP2 each second.
    This code works on my CC2650 with contiki and the XDS110 devpack rev1.2.0 1520

    (based on the cc26xx-demo.c template)

    Interesting code starts with the init_adc(void) function,  line 396

    /*
     * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 3. Neither the name of the copyright holder nor the names of its
     *    contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
     * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     * OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    /*---------------------------------------------------------------------------*/
    /** 
     * \addtogroup cc26xx-platforms
     * @{
     *
     * \defgroup cc26xx-examples CC26xx Example Projects
     *
     * Example projects for CC26xx-based platforms.
     * @{
     *
     * \defgroup cc26xx-demo CC26xx Demo Project
     *
     *   Example project demonstrating the CC26xx platforms
     *
     *   This example will work for the following boards:
     *   - srf06-cc26xx: SmartRF06EB + CC26XX EM
     *   - sensortag-cc26xx: CC26XX sensortag
     *
     *   By default, the example will build for the srf06-cc26xx board. To switch
     *   between platforms:
     *   - make clean
     *   - make BOARD=sensortag-cc26xx savetarget
     *
     *     or
     *
     *     make BOARD=srf06-cc26xx savetarget
     *
     *   This is an IPv6/RPL-enabled example. Thus, if you have a border router in
     *   your installation (same RDC layer, same PAN ID and RF channel), you should
     *   be able to ping6 this demo node.
     *
     *   This example also demonstrates CC26xx BLE operation. The process starts
     *   the BLE beacon daemon (implemented in the RF driver). The daemon will
     *   send out a BLE beacon periodically. Use any BLE-enabled application (e.g.
     *   LightBlue on OS X or the TI BLE Multitool smartphone app) and after a few
     *   seconds the cc26xx device will be discovered.
     *
     * - etimer/clock : Every CC26XX_DEMO_LOOP_INTERVAL clock ticks the LED defined
     *                  as CC26XX_DEMO_LEDS_PERIODIC will toggle and the device
     *                  will print out readings from some supported sensors
     * - sensors      : Some sensortag sensors are read asynchronously (see sensor
     *                  documentation). For those, this example will print out
     *                  readings in a staggered fashion at a random interval
     * - Buttons      : CC26XX_DEMO_SENSOR_1 button will toggle CC26XX_DEMO_LEDS_BUTTON
     *                - CC26XX_DEMO_SENSOR_2 turns on LEDS_REBOOT and causes a
     *                  watchdog reboot
     *                - The remaining buttons will just print something
     *                - The example also shows how to retrieve the duration of a
     *                  button press (in ticks). The driver will generate a
     *                  sensors_changed event upon button release
     * - Reed Relay   : Will toggle the sensortag buzzer on/off
     *
     * @{
     *
     * \file
     *     Example demonstrating the cc26xx platforms
     */
    #include "contiki.h"
    #include "sys/etimer.h"
    #include "sys/ctimer.h"
    #include "dev/leds.h"
    #include "dev/serial-line.h"
    #include "dev/watchdog.h"
    #include "random.h"
    #include "button-sensor.h"
    #include "batmon-sensor.h"
    #include "board-peripherals.h"
    #include "cc26xx-rf.h"
    
    #include "ti-lib.h"
    
    #include <stdio.h>
    #include <stdint.h>
    
    #include "driverlib/aux_adc.h"
    #include "driverlib/aux_wuc.h"
    #include "contiki-net.h"
    
    #define SAMPLECOUNT 60
    #define SAMPLETYPE uint16_t
    
    SAMPLETYPE singleSample;
    
    
    /*---------------------------------------------------------------------------*/
    #define CC26XX_DEMO_LOOP_INTERVAL       (CLOCK_SECOND * 20)
    #define CC26XX_DEMO_LEDS_PERIODIC       LEDS_YELLOW
    #define CC26XX_DEMO_LEDS_BUTTON         LEDS_RED
    #define CC26XX_DEMO_LEDS_SERIAL_IN      LEDS_ORANGE
    #define CC26XX_DEMO_LEDS_REBOOT         LEDS_ALL
    /*---------------------------------------------------------------------------*/
    #define CC26XX_DEMO_SENSOR_NONE         (void *)0xFFFFFFFF
    
    #define CC26XX_DEMO_SENSOR_1     &button_left_sensor
    #define CC26XX_DEMO_SENSOR_2     &button_right_sensor
    
    #if BOARD_SENSORTAG
    #define CC26XX_DEMO_SENSOR_3     CC26XX_DEMO_SENSOR_NONE
    #define CC26XX_DEMO_SENSOR_4     CC26XX_DEMO_SENSOR_NONE
    #define CC26XX_DEMO_SENSOR_5     &reed_relay_sensor
    #else
    #define CC26XX_DEMO_SENSOR_3     &button_up_sensor
    #define CC26XX_DEMO_SENSOR_4     &button_down_sensor
    #define CC26XX_DEMO_SENSOR_5     &button_select_sensor
    #endif
    /*---------------------------------------------------------------------------*/
    static struct etimer et;
    /*---------------------------------------------------------------------------*/
    PROCESS(cc26xx_demo_process, "cc26xx demo process");
    AUTOSTART_PROCESSES(&cc26xx_demo_process);
    /*---------------------------------------------------------------------------*/
    #if BOARD_SENSORTAG
    /*---------------------------------------------------------------------------*/
    /*
     * Update sensor readings in a staggered fashion every SENSOR_READING_PERIOD
     * ticks + a random interval between 0 and SENSOR_READING_RANDOM ticks
     */
    #define SENSOR_READING_PERIOD (CLOCK_SECOND * 20)
    #define SENSOR_READING_RANDOM (CLOCK_SECOND << 4)
    
    static struct ctimer bmp_timer, opt_timer, hdc_timer, tmp_timer, mpu_timer;
    /*---------------------------------------------------------------------------*/
    static void init_bmp_reading(void *not_used);
    static void init_opt_reading(void *not_used);
    static void init_hdc_reading(void *not_used);
    static void init_tmp_reading(void *not_used);
    static void init_mpu_reading(void *not_used);
    /*---------------------------------------------------------------------------*/
    static void
    print_mpu_reading(int reading)
    {
      if(reading < 0) {
        printf("-");
        reading = -reading;
      }
    
      printf("%d.%02d", reading / 100, reading % 100);
    }
    /*---------------------------------------------------------------------------*/
    static void
    get_bmp_reading()
    {
      int value;
      clock_time_t next = SENSOR_READING_PERIOD +
        (random_rand() % SENSOR_READING_RANDOM);
    
      value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS);
      if(value != CC26XX_SENSOR_READING_ERROR) {
        printf("BAR: Pressure=%d.%02d hPa\r\n", value / 100, value % 100);
      } else {
        printf("BAR: Pressure Read Error\r\n");
      }
    
      value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_TEMP);
      if(value != CC26XX_SENSOR_READING_ERROR) {
        printf("BAR: Temp=%d.%02d C\r\n", value / 100, value % 100);
      } else {
        printf("BAR: Temperature Read Error\r\n");
      }
    
      SENSORS_DEACTIVATE(bmp_280_sensor);
    
      ctimer_set(&bmp_timer, next, init_bmp_reading, NULL);
    }
    /*---------------------------------------------------------------------------*/
    static void
    get_tmp_reading()
    {
      int value;
      clock_time_t next = SENSOR_READING_PERIOD +
        (random_rand() % SENSOR_READING_RANDOM);
    
      value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_ALL);
    
      if(value == CC26XX_SENSOR_READING_ERROR) {
        printf("TMP: Ambient Read Error\r\n");
        return;
      }
    
      value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_AMBIENT);
      printf("TMP: Ambient=%d.%03d C\r\n", value / 1000, value % 1000);
    
      value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_OBJECT);
      printf("TMP: Object=%d.%03d C\r\n", value / 1000, value % 1000);
    
      SENSORS_DEACTIVATE(tmp_007_sensor);
    
      ctimer_set(&tmp_timer, next, init_tmp_reading, NULL);
    }
    
    /*---------------------------------------------------------------------------*/
    static void
    get_hdc_reading()
    {
      int value;
      clock_time_t next = SENSOR_READING_PERIOD +
        (random_rand() % SENSOR_READING_RANDOM);
    
      value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP);
      if(value != CC26XX_SENSOR_READING_ERROR) {
        printf("HDC: Temp=%d.%02d C\r\n", value / 100, value % 100);
      } else {
        printf("HDC: Temp Read Error\r\n");
      }
    
      value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY);
      if(value != CC26XX_SENSOR_READING_ERROR) {
        printf("HDC: Humidity=%d.%02d %%RH\r\n", value / 100, value % 100);
      } else {
        printf("HDC: Humidity Read Error\r\n");
      }
    
      ctimer_set(&hdc_timer, next, init_hdc_reading, NULL);
    }
    /*---------------------------------------------------------------------------*/
    static void
    get_light_reading()
    {
      int value;
      clock_time_t next = SENSOR_READING_PERIOD +
        (random_rand() % SENSOR_READING_RANDOM);
    
      value = opt_3001_sensor.value(0);
      if(value != CC26XX_SENSOR_READING_ERROR) {
        printf("OPT: Light=%d.%02d lux\r\n", value / 100, value % 100);
      } else {
        printf("OPT: Light Read Error\r\n");
      }
    
      /* The OPT will turn itself off, so we don't need to call its DEACTIVATE */
      ctimer_set(&opt_timer, next, init_opt_reading, NULL);
    }
    /*---------------------------------------------------------------------------*/
    static void
    get_mpu_reading()
    {
      int value;
      clock_time_t next = SENSOR_READING_PERIOD +
        (random_rand() % SENSOR_READING_RANDOM);
    
      printf("MPU Gyro: X=");
      value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_X);
      print_mpu_reading(value);
      printf(" deg/sec\r\n");
    
      printf("MPU Gyro: Y=");
      value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Y);
      print_mpu_reading(value);
      printf(" deg/sec\r\n");
    
      printf("MPU Gyro: Z=");
      value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Z);
      print_mpu_reading(value);
      printf(" deg/sec\r\n");
    
      printf("MPU Acc: X=");
      value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_X);
      print_mpu_reading(value);
      printf(" G\r\n");
    
      printf("MPU Acc: Y=");
      value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Y);
      print_mpu_reading(value);
      printf(" G\r\n");
    
      printf("MPU Acc: Z=");
      value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Z);
      print_mpu_reading(value);
      printf(" G\r\n");
    
      SENSORS_DEACTIVATE(mpu_9250_sensor);
    
      ctimer_set(&mpu_timer, next, init_mpu_reading, NULL);
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_bmp_reading(void *not_used)
    {
      SENSORS_ACTIVATE(bmp_280_sensor);
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_opt_reading(void *not_used)
    {
      SENSORS_ACTIVATE(opt_3001_sensor);
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_hdc_reading(void *not_used)
    {
      SENSORS_ACTIVATE(hdc_1000_sensor);
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_tmp_reading(void *not_used)
    {
      SENSORS_ACTIVATE(tmp_007_sensor);
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_mpu_reading(void *not_used)
    {
      mpu_9250_sensor.configure(SENSORS_ACTIVE, MPU_9250_SENSOR_TYPE_ALL);
    }
    #endif
    /*---------------------------------------------------------------------------*/
    static void
    get_sync_sensor_readings(void)
    {
      int value;
    
      printf("-----------------------------------------\r\n");
    
      value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
      printf("Bat: Temp=%d C\r\n", value);
    
      value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
      printf("Bat: Volt=%d mV\r\n", (value * 125) >> 5);
    
      return;
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_sensors(void)
    {
    #if BOARD_SENSORTAG
      SENSORS_ACTIVATE(reed_relay_sensor);
    #endif
    
      SENSORS_ACTIVATE(batmon_sensor);
    }
    /*---------------------------------------------------------------------------*/
    static void
    init_sensor_readings(void)
    {
    #if BOARD_SENSORTAG
      SENSORS_ACTIVATE(hdc_1000_sensor);
      SENSORS_ACTIVATE(tmp_007_sensor);
      SENSORS_ACTIVATE(opt_3001_sensor);
      SENSORS_ACTIVATE(bmp_280_sensor);
    
      init_mpu_reading(NULL);
    #endif
    }
    /*---------------------------------------------------------------------------*/
    /*---------------------------------------------------------------------------*/
    /*---------------------------------------------------------------------------*/
    //DIY functions
    unsigned short get_tmp_object_value()
    {
      unsigned short value;
      
      value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_ALL);
    
      if(value == CC26XX_SENSOR_READING_ERROR) {
        value = 0;
      }
      else {
        value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_OBJECT);
      }
    
      return value;
    }
    
    static void
    init_adc(void)
    {
    	//intialisation of ADC
    
    	// Enable clock for ADC digital and analog interface (not currently enabled in driver)
    	AUXWUCClockEnable(AUX_WUC_ADI_CLOCK|AUX_WUC_SOC_CLOCK);   // was : AUX_WUC_MODCLKEN0_SOC_M|AUX_WUC_MODCLKEN0_AUX_ADI4_M);
    	printf("clock selected\r\n");
    	
    	// Connect AUX IO7 (DIO23, but also DP2 on XDS110) as analog input.
    	AUXADCSelectInput(ADC_COMPB_IN_AUXIO7);  
    	printf("input selected\r\n");
    	
    	// Set up ADC range
    	// AUXADC_REF_FIXED = nominally 4.3 V
    	AUXADCEnableSync(AUXADC_REF_FIXED,  AUXADC_SAMPLE_TIME_2P7_US, AUXADC_TRIGGER_MANUAL);
    	printf("init adc --- OK\r\n");
    	
    
    }
    /*---------------------------------------------------------------------------*/
    PROCESS_THREAD(cc26xx_demo_process, ev, data)
    	{
    	unsigned short i;
    	
    	PROCESS_BEGIN();
    	printf("CC26XX demo\r\n");
    
    	init_sensors();
    	
    	/* Init the BLE advertisement daemon */
    	cc26xx_rf_ble_beacond_config(0, BOARD_STRING);
    	cc26xx_rf_ble_beacond_start();
    
    	etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL);
    	get_sync_sensor_readings();
    	
    	init_sensor_readings();
    	printf("init sensors --- OK\r\n");
    	
    	init_adc();
    	
    	leds_on(LEDS_GREEN);
    	printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");
    	while(1)
    	{		
    		//Trigger ADC converting
    		AUXADCGenManualTrigger();
    		printf("trigger --- OK\r\n");
    		
    		//reading adc value
    		singleSample = AUXADCReadFifo();
    
    		printf("%d mv on ADC\r\n",singleSample);
    		
    		//This timer crashes the ADC's FIFO (please let me know why) 
                    //Please use the clock_delay_usec as shown below
    		//etimer_set(&timer, CLOCK_SECOND);
    		//PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
    
    
    		i=0;
    
    		for(i=0;i<100;i++)  
    			clock_delay_usec(10000);  //can't go up to 65535 that's why i use a for loop
    	}
    	 
    	//shut the adc down
    	AUXADCDisable();
    	printf("disable --- OK\r\n");
    	
    	
    	PROCESS_END();
    }
    /*---------------------------------------------------------------------------*/
    /**
     * @}
     * @}
     * @}
     */
    

  • I am playing Contiki now and Thanks for sharing this.
  • I realized that my application needs a multithread... So i'm not able to run this, because i need a etimer, or a PROCESS_WAIT.

    The adc got stuck, and application crashes when i call AUXADCReadFifo();

    Any idea ?
  • Hi, were you able to get this to work?

    I see you one place write "code who works fine, showing the ADC value on DP2 each second." but later "not able to run this" - could you elaborate a bit?

    I tried this quickly but I think it waits in the while loop inside AUXADCReadFifo(), however I only have a v1 .0 debugger though, so I will try more later when I get newer revisions.

    Regards,
    Andreas