Kenji Arai / MCP3425

Dependents:   check_ADC_MCP3425

MCP3425.cpp

Committer:
kenjiArai
Date:
2018-03-18
Revision:
0:29be5dda6cf2
Child:
1:223248a79e87

File content as of revision 0:29be5dda6cf2:

/*
 * mbed library program
 *  16-Bit Analog-to-Digital Converter with I2C Interface
 *  MCP3425 by Microchip Technology Inc.
 *
 * Copyright (c) 2018 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Modify:     March     17th, 2018
 *      Revised:    March     18th, 2018
 */

#include "MCP3425.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 "I cannot control wait_ms()!!"
#endif

MCP3425::MCP3425 (PinName p_sda, PinName p_scl)
    : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
{
    mcp3425_addr = MCP3425A0T_ADDR; // Chip MCP3425A0T-E/CH
    init();
}

MCP3425::MCP3425 (PinName p_sda, PinName p_scl, uint8_t addr)
    : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
{
    mcp3425_addr = addr;    // you need get diffrent part nuber of chip
    init();
}

MCP3425::MCP3425 (I2C& p_i2c)
    : _i2c(p_i2c)
{
    mcp3425_addr = MCP3425A0T_ADDR; // Chip MCP3425A0T-E/CH
    init();
}

MCP3425::MCP3425 (I2C& p_i2c, uint8_t addr)
    : _i2c(p_i2c)
{
    mcp3425_addr = addr;    // you need get diffrent part nuber of chip
    init();
}

void MCP3425::init()
{
    offset_volt = 0.0f;             // none offset
    compensation_ref = 1.0f;        // no compensation
    config.pga_gain = PGA_GAIN_1;   // Gain x1
    config.sample_rate = SAMPLE_RATE_15SPS_16BIT;   // 16bit resolution
    config.conversion_mode = CONV_MODE_CONTINUOUS;  // Continuous conversion
    config_byte = convert_config2byte(&config); // make one byte
    buf[0] = config_byte;
    _i2c.write((int)mcp3425_addr, (char *)buf, 1);  // write into config reg.
}

int16_t MCP3425::read_16bit()
{
    uint32_t timeout = 1000U;   // timeout
    if (config.conversion_mode == CONV_MODE_ONE_SHOT) {
        // trigger for starting conversion
        buf[0] = config_byte + RDY_BIT;
        _i2c.write((int)mcp3425_addr, (char *)buf, 1);
    }
    do {
        _i2c.read( (int)mcp3425_addr, (char *)buf, 3);
        if ((buf[2] & RDY_BIT) == 0) {
            break;      // end of conversion
        }
        if (--timeout == 0) {
            return -1;  // error
        }
        uint8_t spd = (buf[2] >> 2) & 0x03;
        if (spd == SAMPLE_RATE_60SPS_14BIT) {
            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);     // no wait
        }
    } while(true);
    dt_adc16 = (uint16_t)buf[0] << 8;
    dt_adc16 += (uint16_t)buf[1];
    return dt_adc16;
}

float MCP3425::read_voltage()
{
    float dt16 = (float)read_16bit();
    switch(config.sample_rate) {
        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;
    }
    switch(config.pga_gain) {
        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;
    }
    dt_adc_f = dt16 * 2.048f;
    dt_adc_f -= offset_volt;
    dt_adc_f *= compensation_ref;
    return dt_adc_f;
}

void MCP3425::set_offset_volt(float offset)
{
    offset_volt = offset;
}

void MCP3425::set_vref_compensation(float compensation)
{
    compensation_ref = compensation;
}

void MCP3425::set_config(mcp3425_config_t *parameter)
{
    config.pga_gain = parameter->pga_gain & 0x03;
    config.sample_rate = parameter->sample_rate & 0x03;
    config.conversion_mode = parameter->conversion_mode & 0x01;
    config_byte = convert_config2byte(&config);
    buf[0] = config_byte;
    _i2c.write((int)mcp3425_addr, (char *)buf, 1);
}

void MCP3425::read_config(mcp3425_config_t *parameter)
{
    _i2c.read( (int)mcp3425_addr, (char *)buf, 3);
    config_byte = buf[2] & 0x1f;
    parameter->pga_gain = config_byte & PGA_GAIN_BIT;
    parameter->sample_rate  = (config_byte & SAMPLE_RATE_BIT) >> 2;
    parameter->conversion_mode  = (config_byte & CONVERSION_MODE_BIT) >> 4;
    config = *parameter;
}

void MCP3425::frequency(uint32_t hz)
{
    _i2c.frequency(hz);
}

uint8_t MCP3425::convert_config2byte(mcp3425_config_t *config)
{
    uint8_t byte = config->pga_gain;
    byte |= config->sample_rate << 2;
    byte |= config->conversion_mode << 4;
    config_byte = byte;
    return config_byte;
}