Kenji Arai / MCP3427

Fork of MCP3425 by Kenji Arai

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MCP3427.cpp Source File

MCP3427.cpp

00001 /*
00002  * mbed library program
00003  *  2 channels 16-Bit(available 14/12bit mode) Analog-to-Digital Converter
00004  *      with I2C Interface ---- MCP3427 by Microchip Technology Inc.
00005  *
00006  * Copyright (c) 2018 Kenji Arai / JH1PJL
00007  *  http://www.page.sannet.ne.jp/kenjia/index.html
00008  *  http://mbed.org/users/kenjiArai/
00009  *      Created:    June       7th, 2018
00010  *      Revised:    July      13th, 2018
00011  */
00012 
00013 #include "MCP3427.h"
00014 
00015 extern Serial pc;
00016 
00017 // BIT DEFINITION
00018 #define RDY_BIT                     (1UL << 7)
00019 #define CONVERSION_MODE_BIT         (1UL << 4)
00020 #define SAMPLE_RATE_BIT             (3UL << 2)
00021 #define PGA_GAIN_BIT                (3UL << 0)
00022 
00023 #if (MBED_MAJOR_VERSION == 2)
00024 #define WAIT_MS(x)              wait_ms(x)
00025 #elif (MBED_MAJOR_VERSION == 5)
00026 #define WAIT_MS(x)              Thread::wait(x)
00027 #else
00028 #warning "Cannot control wait_ms()!!"
00029 #endif
00030 
00031 MCP3427::MCP3427 (PinName p_sda, PinName p_scl, uint8_t addr)
00032     : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
00033 {
00034     mcp3427_addr = addr;
00035     init();
00036 }
00037 
00038 MCP3427::MCP3427 (I2C& p_i2c, uint8_t addr)
00039     : _i2c(p_i2c)
00040 {
00041     mcp3427_addr = addr;
00042     init();
00043 }
00044 
00045 void MCP3427::init()
00046 {
00047     offset_volt[0] = 0.0f;          // none offset
00048     offset_volt[1] = 0.0f;          // none offset
00049     compensation_ref = 1.0f;        // no compensation
00050     pga_gain[0] = PGA_GAIN_1;       // Gain x1
00051     pga_gain[1] = PGA_GAIN_1;       // Gain x1
00052     sample_rate[0] = SAMPLE_RATE_15SPS_16BIT;   // 16bit resolution
00053     sample_rate[1] = SAMPLE_RATE_15SPS_16BIT;   // 16bit resolution
00054     conversion_mode[0] = CONV_MODE_CONTINUOUS;  // Continuous conversion
00055     conversion_mode[1] = CONV_MODE_CONTINUOUS;  // Continuous conversion
00056     convert_config2byte(); // make one byte
00057     buf[0] = config_byte[0];
00058     _i2c.write((int)mcp3427_addr, (char *)buf, 1);  // write into config reg.
00059     current_ch = 0;
00060 }
00061 
00062 int16_t MCP3427::read_16bit(uint8_t ch)
00063 {
00064     _ch = ch - 1;
00065     if (_ch != current_ch) {
00066         current_ch = _ch;
00067         _set_ch_and_config(current_ch);
00068         buf[0] = config_byte[current_ch] + RDY_BIT;
00069         _i2c.write((int)mcp3427_addr, (char *)buf, 1);
00070     }
00071     if (conversion_mode[current_ch] == CONV_MODE_ONE_SHOT) {
00072         // trigger for starting conversion
00073         buf[0] = config_byte[current_ch] + RDY_BIT;
00074         _i2c.write((int)mcp3427_addr, (char *)buf, 1);
00075     }
00076     return _read_16bit(); // internal channel 0 & 1
00077     
00078 }
00079 
00080 int16_t MCP3427::_read_16bit(void)
00081 {
00082     uint32_t timeout = 1000U;   // timeout
00083     do {
00084         _i2c.read( (int)mcp3427_addr, (char *)buf, 3);
00085         if ((buf[2] & RDY_BIT) == 0) {  // check Config. reg. Ready bit
00086             break;      // end of conversion (RDY = 0)
00087         }
00088         if (--timeout == 0) {
00089             return -1;  // timeout then error
00090         }
00091         uint8_t spd = (buf[2] >> 2) & 0x03; // get current sampling rate
00092         if (spd == SAMPLE_RATE_60SPS_14BIT) {   // wait next conversion period
00093             WAIT_MS(6);     // conversion time = 16.7ms
00094         } else if (spd == SAMPLE_RATE_15SPS_16BIT) {
00095             WAIT_MS(24);    // conversion time = 66.7ms
00096         } else {  // == SAMPLE_RATE_240SPS_12BIT
00097             WAIT_MS(2);     // conversion time = 4.2ms
00098         }
00099     } while(true);
00100     //printf("[%d,0x%02x,0x%02x,0x%02x]", _ch, buf[0], buf[1], buf[2]);
00101     dt_adc16 = (uint16_t)buf[0] << 8;   // High byte
00102     dt_adc16 += (uint16_t)buf[1];       // Low byte
00103     return dt_adc16;
00104 }
00105 
00106 void MCP3427::start_conversion(uint8_t ch)
00107 {
00108     _ch = ch - 1;
00109     if (_ch != current_ch) {
00110         current_ch = _ch;
00111         _set_ch_and_config(current_ch);
00112         buf[0] = config_byte[current_ch] + RDY_BIT;
00113         _i2c.write((int)mcp3427_addr, (char *)buf, 1);
00114     }
00115     if (conversion_mode[current_ch] == CONV_MODE_ONE_SHOT) {
00116         // trigger for starting conversion
00117         buf[0] = config_byte[current_ch] + RDY_BIT;
00118         _i2c.write((int)mcp3427_addr, (char *)buf, 1);
00119     }
00120 }
00121 
00122 float MCP3427::read_voltage_from_current_ch(void)
00123 {
00124     float dt16 = (float)_read_16bit();
00125     return _read_voltage(dt16);
00126 }
00127 
00128 float MCP3427::read_voltage(uint8_t ch)
00129 {
00130     float dt16 = (float)read_16bit(ch);
00131     return _read_voltage(dt16);
00132 }
00133 
00134 float MCP3427::_read_voltage(float dt16)
00135 {
00136     switch(sample_rate[current_ch]) {
00137         case SAMPLE_RATE_240SPS_12BIT:
00138             dt16 /=  2048.0f; // 11bit (0x7ff +1)
00139             break;
00140         case SAMPLE_RATE_60SPS_14BIT:
00141             dt16 /= 16384.0f; // 14bit (0x3fff +1)
00142             break;
00143         case SAMPLE_RATE_15SPS_16BIT:
00144             dt16 /= 32768.0f; // 15bit (0x7fff +1)
00145             break;
00146         default:
00147             return -1;      // error
00148     }
00149     switch(pga_gain[current_ch]) {
00150         case PGA_GAIN_1:
00151             dt16 /= 1.0f;
00152             break;
00153         case PGA_GAIN_2:
00154             dt16 /= 2.0f;
00155             break;
00156         case PGA_GAIN_4:
00157             dt16 /= 4.0f;
00158             break;
00159         case PGA_GAIN_8:
00160             dt16 /= 8.0f;
00161             break;
00162         default:
00163             return -1;      // error
00164     }
00165     dt_adc_f = dt16 * 2.048f;           // Vref = 2.048V +/- 0.05%
00166     dt_adc_f -= offset_volt[current_ch];// adjust offset voltage
00167     dt_adc_f *= compensation_ref;       // compensate Vref deviation
00168     return dt_adc_f;
00169 }
00170 
00171 void MCP3427::set_offset_volt(uint8_t ch, float offset)
00172 {
00173    offset_volt[ch - 1] = offset;    // internal channel 0 & 1
00174 }
00175 
00176 void MCP3427::set_vref_compensation(float compensation)
00177 {
00178     compensation_ref = compensation;
00179 }
00180 
00181 void MCP3427::set_config(mcp3427_config_t *parameter)
00182 {
00183     pga_gain[0] = parameter->pga_gain1 & 0x03;
00184     pga_gain[1] = parameter->pga_gain2 & 0x03;
00185     sample_rate[0] = parameter->sample_rate1 & 0x03;
00186     sample_rate[1] = parameter->sample_rate2 & 0x03;
00187     conversion_mode[0] = parameter->conversion_mode1 & 0x01;
00188     conversion_mode[1] = parameter->conversion_mode2 & 0x01;
00189     convert_config2byte();
00190     _set_ch_and_config(0);   // channel inf is dummy at this moment
00191 }
00192 
00193 void MCP3427::_set_ch_and_config(uint8_t n)
00194 {
00195     buf[0] = config_byte[n] + n << 5;
00196     _i2c.write((int)mcp3427_addr, (char *)buf, 1);
00197 }
00198 
00199 void MCP3427::frequency(uint32_t hz)
00200 {
00201     _i2c.frequency(hz);
00202 }
00203 
00204 void MCP3427::convert_config2byte()
00205 {
00206     uint8_t byte = pga_gain[0];
00207     byte |= sample_rate[0] << 2;
00208     byte |= conversion_mode[0] << 4;
00209     config_byte[0] = byte;
00210     byte = pga_gain[1];
00211     byte |= sample_rate[1] << 2;
00212     byte |= conversion_mode[1] << 4;
00213     byte |= 0x20;   // Ch 2
00214     config_byte[1] = byte;
00215 }