MCP3427 16-Bit Analog-to-Digital Converter with I2C Interface
Fork of MCP3425 by
MCP3427.cpp
- Committer:
- kenjiArai
- Date:
- 2018-09-21
- Revision:
- 2:bb3efa8c5b23
- Parent:
- MCP3425.cpp@ 1:223248a79e87
File content as of revision 2:bb3efa8c5b23:
/* * mbed library program * 2 channels 16-Bit(available 14/12bit mode) Analog-to-Digital Converter * with I2C Interface ---- MCP3427 by Microchip Technology Inc. * * Copyright (c) 2018 Kenji Arai / JH1PJL * http://www.page.sannet.ne.jp/kenjia/index.html * http://mbed.org/users/kenjiArai/ * Created: June 7th, 2018 * Revised: July 13th, 2018 */ #include "MCP3427.h" extern Serial pc; // BIT DEFINITION #define RDY_BIT (1UL << 7) #define CONVERSION_MODE_BIT (1UL << 4) #define SAMPLE_RATE_BIT (3UL << 2) #define PGA_GAIN_BIT (3UL << 0) #if (MBED_MAJOR_VERSION == 2) #define WAIT_MS(x) wait_ms(x) #elif (MBED_MAJOR_VERSION == 5) #define WAIT_MS(x) Thread::wait(x) #else #warning "Cannot control wait_ms()!!" #endif MCP3427::MCP3427 (PinName p_sda, PinName p_scl, uint8_t addr) : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) { mcp3427_addr = addr; init(); } MCP3427::MCP3427 (I2C& p_i2c, uint8_t addr) : _i2c(p_i2c) { mcp3427_addr = addr; init(); } void MCP3427::init() { offset_volt[0] = 0.0f; // none offset offset_volt[1] = 0.0f; // none offset compensation_ref = 1.0f; // no compensation pga_gain[0] = PGA_GAIN_1; // Gain x1 pga_gain[1] = PGA_GAIN_1; // Gain x1 sample_rate[0] = SAMPLE_RATE_15SPS_16BIT; // 16bit resolution sample_rate[1] = SAMPLE_RATE_15SPS_16BIT; // 16bit resolution conversion_mode[0] = CONV_MODE_CONTINUOUS; // Continuous conversion conversion_mode[1] = CONV_MODE_CONTINUOUS; // Continuous conversion convert_config2byte(); // make one byte buf[0] = config_byte[0]; _i2c.write((int)mcp3427_addr, (char *)buf, 1); // write into config reg. current_ch = 0; } int16_t MCP3427::read_16bit(uint8_t ch) { _ch = ch - 1; if (_ch != current_ch) { current_ch = _ch; _set_ch_and_config(current_ch); buf[0] = config_byte[current_ch] + RDY_BIT; _i2c.write((int)mcp3427_addr, (char *)buf, 1); } if (conversion_mode[current_ch] == CONV_MODE_ONE_SHOT) { // trigger for starting conversion buf[0] = config_byte[current_ch] + RDY_BIT; _i2c.write((int)mcp3427_addr, (char *)buf, 1); } return _read_16bit(); // internal channel 0 & 1 } int16_t MCP3427::_read_16bit(void) { uint32_t timeout = 1000U; // timeout do { _i2c.read( (int)mcp3427_addr, (char *)buf, 3); if ((buf[2] & RDY_BIT) == 0) { // check Config. reg. Ready bit break; // end of conversion (RDY = 0) } if (--timeout == 0) { return -1; // timeout then error } uint8_t spd = (buf[2] >> 2) & 0x03; // get current sampling rate if (spd == SAMPLE_RATE_60SPS_14BIT) { // wait next conversion period WAIT_MS(6); // conversion time = 16.7ms } else if (spd == SAMPLE_RATE_15SPS_16BIT) { WAIT_MS(24); // conversion time = 66.7ms } else { // == SAMPLE_RATE_240SPS_12BIT WAIT_MS(2); // conversion time = 4.2ms } } while(true); //printf("[%d,0x%02x,0x%02x,0x%02x]", _ch, buf[0], buf[1], buf[2]); dt_adc16 = (uint16_t)buf[0] << 8; // High byte dt_adc16 += (uint16_t)buf[1]; // Low byte return dt_adc16; } void MCP3427::start_conversion(uint8_t ch) { _ch = ch - 1; if (_ch != current_ch) { current_ch = _ch; _set_ch_and_config(current_ch); buf[0] = config_byte[current_ch] + RDY_BIT; _i2c.write((int)mcp3427_addr, (char *)buf, 1); } if (conversion_mode[current_ch] == CONV_MODE_ONE_SHOT) { // trigger for starting conversion buf[0] = config_byte[current_ch] + RDY_BIT; _i2c.write((int)mcp3427_addr, (char *)buf, 1); } } float MCP3427::read_voltage_from_current_ch(void) { float dt16 = (float)_read_16bit(); return _read_voltage(dt16); } float MCP3427::read_voltage(uint8_t ch) { float dt16 = (float)read_16bit(ch); return _read_voltage(dt16); } float MCP3427::_read_voltage(float dt16) { switch(sample_rate[current_ch]) { case SAMPLE_RATE_240SPS_12BIT: dt16 /= 2048.0f; // 11bit (0x7ff +1) break; case SAMPLE_RATE_60SPS_14BIT: dt16 /= 16384.0f; // 14bit (0x3fff +1) break; case SAMPLE_RATE_15SPS_16BIT: dt16 /= 32768.0f; // 15bit (0x7fff +1) break; default: return -1; // error } switch(pga_gain[current_ch]) { case PGA_GAIN_1: dt16 /= 1.0f; break; case PGA_GAIN_2: dt16 /= 2.0f; break; case PGA_GAIN_4: dt16 /= 4.0f; break; case PGA_GAIN_8: dt16 /= 8.0f; break; default: return -1; // error } dt_adc_f = dt16 * 2.048f; // Vref = 2.048V +/- 0.05% dt_adc_f -= offset_volt[current_ch];// adjust offset voltage dt_adc_f *= compensation_ref; // compensate Vref deviation return dt_adc_f; } void MCP3427::set_offset_volt(uint8_t ch, float offset) { offset_volt[ch - 1] = offset; // internal channel 0 & 1 } void MCP3427::set_vref_compensation(float compensation) { compensation_ref = compensation; } void MCP3427::set_config(mcp3427_config_t *parameter) { pga_gain[0] = parameter->pga_gain1 & 0x03; pga_gain[1] = parameter->pga_gain2 & 0x03; sample_rate[0] = parameter->sample_rate1 & 0x03; sample_rate[1] = parameter->sample_rate2 & 0x03; conversion_mode[0] = parameter->conversion_mode1 & 0x01; conversion_mode[1] = parameter->conversion_mode2 & 0x01; convert_config2byte(); _set_ch_and_config(0); // channel inf is dummy at this moment } void MCP3427::_set_ch_and_config(uint8_t n) { buf[0] = config_byte[n] + n << 5; _i2c.write((int)mcp3427_addr, (char *)buf, 1); } void MCP3427::frequency(uint32_t hz) { _i2c.frequency(hz); } void MCP3427::convert_config2byte() { uint8_t byte = pga_gain[0]; byte |= sample_rate[0] << 2; byte |= conversion_mode[0] << 4; config_byte[0] = byte; byte = pga_gain[1]; byte |= sample_rate[1] << 2; byte |= conversion_mode[1] << 4; byte |= 0x20; // Ch 2 config_byte[1] = byte; }