2 Replies Latest reply on Nov 11, 2016 3:37 PM by Intel Corporation

    Intel Edison with SparkFun Blocks ADC

    Pawek

      Hello,

      I have to use in my project C language so I refactored this example:

       

      GitHub - sparkfun/SparkFun_ADC_Block_for_Edison_CPP_Library: C++ library and example for using SparkFun's ADC block for …

       

      Into this code:
      #include <stdio.h>
      #include <string.h>
      #include <unistd.h>
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <sys/ioctl.h>
      #include "mraa.h"
      mraa_i2c_context edison_i2c_ADC;
      /*ADC On Sparkfun via I2C defines*/
      #define CONVERSION 0  // Conversion result register.
      #define CONFIG 1  // 16-bit configuration register.
      int scaler;
      void ads1015_setConfigRegister(uint16_t configValue);
      uint16_t ads1015_getConfigRegister();
      void ads1015_setRange(int range);
      int16_t ads1015_readADC();
      int16_t ads1015_getRawResult(uint8_t channel);
      float ads1015_getResult(uint8_t channel);
      
      // Channel selection and read start stuff- the high nibble of the 16-bit cfg
      // register controls the start of a single conversion, the channel(s) read,
      // and whether they're read single ended or differential.
      #define CHANNEL_MASK 0x3000 // There are four channels, and single ended reads
         // are specified by a two-bit address at bits 13:12
      #define SINGLE_ENDED 0x4000  // Set for single-ended
      #define START_READ 0x8000 // To start a read, we set the highest bit of the
       // highest nibble.
      #define CFG_REG_CHL_MASK 0xf000 // Used to clear the high nibble of the cfg reg
         // before we start our read request.
      #define BUSY_MASK 0x8000 // When the highest bit in the cfg reg is set, the
         // conversion is done.
      #define CHANNEL_SHIFT 12  // shift the raw channel # by this
      
      #define RANGE_SHIFT 9  // how far to shift our prepared data to drop it into the
         // right spot in the cfg reg
      #define RANGE_MASK 0x0E00 // bits to clear for gain parameter
      
      //#define _2_048V 2
      // PGA settings and stuff. These are bits 11:9 of the cfg reg
      enum VoltageRange { _6_144V = 0, _4_096V,_2_048V, _1_024V, _0_512V,
       _0_256V, VOLTAGE_MASK = 0x07};
      
      
      
      void ads1015_setRange(int range)
      {
      uint16_t cfgRegVal = ads1015_getConfigRegister();
      cfgRegVal &= ~RANGE_MASK;
      cfgRegVal |= (range << RANGE_SHIFT) & RANGE_MASK;
      ads1015_setConfigRegister(cfgRegVal);
      
      switch (range)
       {
       case _6_144V:
       scaler = 3.0; // each count represents 3.0 mV
       break;
       case _4_096V:
       scaler = 2.0; // each count represents 2.0 mV
       break;
       case _2_048V:
       scaler = 1.0; // each count represents 1.0 mV
       break;
       case _1_024V:
       scaler = 0.5; // each count represents 0.5mV
       break;
       case _0_512V:
       scaler = 0.25; // each count represents 0.25mV
       break;
       case _0_256V:
       scaler = 0.125; // each count represents 0.125mV
       break;
       default:
       scaler = 1.0;  // here be dragons
       break;
       }
      
      }
      
      void ads1015_setConfigRegister(uint16_t configValue){
      uint8_t data[3];
      data[0] = 0x01;  // address of the config register
      data[1] = configValue>>8;
      data[2] = configValue;
      mraa_i2c_write(edison_i2c_ADC,data,3);
      }
      uint16_t ads1015_getConfigRegister(){
      uint16_t cfgRegVal = 0;
      mraa_i2c_read_bytes_data(edison_i2c_ADC,CONFIG, (uint8_t*)&cfgRegVal, 2);
      cfgRegVal = (cfgRegVal>>8) | (cfgRegVal<<8);
      return cfgRegVal;
      }
      
      float ads1015_getResult(uint8_t channel)
      {
      int16_t rawVal = ads1015_getRawResult(channel);
      return (float)rawVal * scaler/1000;
      }
      
      int16_t ads1015_getRawResult(uint8_t channel)
      {
      uint16_t cfgRegVal = ads1015_getConfigRegister();
      cfgRegVal &= ~CHANNEL_MASK; // clear existing channel settings
      cfgRegVal |= SINGLE_ENDED;  // set the SE bit for a s-e read
      cfgRegVal |= (channel<<CHANNEL_SHIFT) & CHANNEL_MASK; // put the channel bits in
      cfgRegVal |= START_READ;   // set the start read bit
      ads1015_setConfigRegister(cfgRegVal);
      return ads1015_readADC();
      }
      
      int16_t ads1015_readADC()
      {
      uint16_t cfgRegVal = ads1015_getConfigRegister();
      cfgRegVal |= START_READ; // set the start read bit
      ads1015_setConfigRegister(cfgRegVal);
      
      uint8_t result[2];
      int16_t fullValue=0;
      uint8_t busyDelay = 0;
      
      while ((ads1015_getConfigRegister() & BUSY_MASK) == 0)
      {
       usleep(100);
       if(busyDelay++ > 100) return 0xffff;
      }
      
      mraa_i2c_read_bytes_data(edison_i2c_ADC,CONVERSION,result,2);
      fullValue = (result[0]<<8) + result[1];
      
      return (int)(fullValue >> 4);
      }
      
      
      /*
       *@brief main
       */
      int main(void)
      {
        /*Initialize mraa libraries*/
        mraa_init();
      
      edison_i2c_ADC = mraa_i2c_init(1);
      printf("\n\n\nEDISSON I2c = %d\n\n",(int)edison_i2c_ADC);
      mraa_i2c_address(edison_i2c_ADC,0x48);
      
      ads1015_setRange(_0_512V);
      
        /*Main loop*/
        while(1)
        {
      
      printf("\n\n\n\nCh 0: %f\n\n\n\n",ads1015_getResult(0));
      printf("\n\n\n\nCh 1: %f\n\n\n\n",ads1015_getResult(1));
      
        return 0;
      }
      

      But all i get is constantly 0.

       

      I give a try to this:

      GitHub - humberto-garza/SparkFunEdisonADC: SparkFun Block for Intel® Edison - ADC Arduino and C Libraries

      But this time I get wrong values, but which react (for example when I touch temp sensor it increase or when I make change distance from distance it changes too).

      #include <stdio.h>
      #include <string.h>
      #include <unistd.h>
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <sys/ioctl.h>
      #include "mraa.h"
      uint16_t command;
      void set_config_command(int os, int imc, int pga, int mode, int rate, int comp_mode, int comp_pol, int comp_lat, int comp_que);
      int adc_read();
      mraa_i2c_context edison_i2c_ADC;
      void set_config_command(int os, int imc, int pga, int mode, int rate, int comp_mode, int comp_pol, int comp_lat, int comp_que)
      {
        rate = rate << 13;
        comp_mode = comp_mode << 12;
        comp_pol = comp_pol << 11;
        comp_lat = comp_lat << 10;
        comp_que = comp_que << 8;
        os = os << 7;
        imc = imc << 4;
        pga = pga << 1;
         //mode = mode << 0 ;
        command = os + imc + pga + mode + rate + comp_mode + comp_pol + comp_lat + comp_que;
      }
      int adc_read()
      {
      
      
        //-2048 is a value that cannot be reported by the ADC so it used as an error code
        if (mraa_i2c_write_word_data(edison_i2c_ADC, command, 0x01) != MRAA_SUCCESS)
        return -2048;
      
      
        uint16_t data = mraa_i2c_read_word_data (edison_i2c_ADC, 0);
      
      
        int result = 0;
        result += (data & 0XF000) >>12;
        result += (data & 0X00F0) << 4;
        result += (data & 0X000F) << 4;
      
      
        if(result > 0x7FF)
        {
        int aux =  -1*(~result-0xFFFFF000);
        return aux;
        }
        else
        return  result;
      }
      /*
       *@brief main
       */
      int main(void)
      {
        /*Initialize mraa libraries*/
        mraa_init();
      
      edison_i2c_ADC = mraa_i2c_init(1);
        printf("\n\n\nEDISSON I2c = %d\n\n",(int)edison_i2c_ADC);
        if (mraa_i2c_address(edison_i2c_ADC, 0x48) != MRAA_SUCCESS)
          command = 555;
          else
          {
        command = 0b0000000000000000; //operational_status
        command += 0b0000000000000100; //input_multiplexer_configuration
        command += 0b0000000000000100; //programmable_gain_amplifier_configuration
        command += 0b0000000000000000; //device_operating_mode
        command += 0b1000000000000000; //date_rate
        command += 0b0000000000000000; //comparator_mode
        command += 0b0000000000000000; //compulator_polarity
        command += 0b0000000000000000; //latching_comparator
        command += 0b0000001100000000; //comparator_queue_and_disable
          }
      
        int ain1_operational_status = 0b0;
        int ain1_input_multiplexer_configuration = 0b100;
        int ain1_programmable_gain_amplifier_configuration = 0b010;
        int ain1_device_operating_mode = 0b0;
        int ain1_date_rate = 0b100;
        int ain1_comparator_mode = 0b0;
        int ain1_compulator_polarity = 0b0;
        int ain1_latching_comparator = 0b0;
        int ain1_comparator_queue_and_disable = 0b11;
      
      
        /*Main loop*/
        while(1)
        {
      
        set_config_command(
        ain1_operational_status,
        ain1_input_multiplexer_configuration,
        ain1_programmable_gain_amplifier_configuration,
        ain1_device_operating_mode,
        ain1_date_rate,
        ain1_comparator_mode,
        ain1_compulator_polarity,
        ain1_latching_comparator,
        ain1_comparator_queue_and_disable
        );
        printf("\n\n\n%d\n\n\n",adc_read());
      
        set_config_command(
        ain1_operational_status,
        0b101,
        ain1_programmable_gain_amplifier_configuration,
        ain1_device_operating_mode,
        ain1_date_rate,
        ain1_comparator_mode,
        ain1_compulator_polarity,
        ain1_latching_comparator,
        ain1_comparator_queue_and_disable
        );
        printf("\n\n\n%d\n\n\n",adc_read());
        sleep(1);
        }
      
      
        return 0;
      }
      

       

      Could anybody provide me any advices how to get proper values? For that temp sensor TMP36  i get values around 750. When i use formula from datasheet (((read * 3.3)/1024) - 0.5)*100 the temp seems wrong (~190).

       

      I would be grateful,

      Paweł

       

       

       

      Btw am i doing it right, when i want to read from 2 sensors i use following functions:

      int get_temp_in_celcius(void) // [! IMPORTANT] VCC 3.3 -> 5 on board
      {
        int ain1_operational_status = 0b0;
        int ain1_input_multiplexer_configuration = 0b100;
        int ain1_programmable_gain_amplifier_configuration = 0b010;
        int ain1_device_operating_mode = 0b0;
        int ain1_date_rate = 0b100;
        int ain1_comparator_mode = 0b0;
        int ain1_compulator_polarity = 0b0;
        int ain1_latching_comparator = 0b0;
        int ain1_comparator_queue_and_disable = 0b11;
        set_config_command(
        ain1_operational_status,
        ain1_input_multiplexer_configuration,
        ain1_programmable_gain_amplifier_configuration,
        ain1_device_operating_mode,
        ain1_date_rate,
        ain1_comparator_mode,
        ain1_compulator_polarity,
        ain1_latching_comparator,
        ain1_comparator_queue_and_disable
        );
        int read = 0;
        read = adc_read();
      
      
      
      
          int temperature = (read - 500)/10;
        return  temperature;
      }
      
      
      int get_distance(void)
      {
      
      
        int ain1_operational_status = 0b0;
        int ain1_input_multiplexer_configuration = 0b111;
        int ain1_programmable_gain_amplifier_configuration = 0b010;
        int ain1_device_operating_mode = 0b0;
        int ain1_date_rate = 0b100;
        int ain1_comparator_mode = 0b0;
        int ain1_compulator_polarity = 0b0;
        int ain1_latching_comparator = 0b0;
        int ain1_comparator_queue_and_disable = 0b11;
        set_config_command(
        ain1_operational_status,
        ain1_input_multiplexer_configuration,
        ain1_programmable_gain_amplifier_configuration,
        ain1_device_operating_mode,
        ain1_date_rate,
        ain1_comparator_mode,
        ain1_compulator_polarity,
        ain1_latching_comparator,
        ain1_comparator_queue_and_disable
        );
        int read = 0;
        read = adc_read();
      
      
        float distance = (read * 3.3)/1024;
        distance = 65* pow(distance,-1.1);
      return (int)distance;
      
      
      }
      

      Because if im doung it this way, they seems to corrupt each other.