Microchip MCP342x ADC library
mcp342x.cpp@3:03911aa07029, 2017-07-18 (annotated)
- Committer:
- antoniogonzalez
- Date:
- Tue Jul 18 09:43:27 2017 +0000
- Revision:
- 3:03911aa07029
- Parent:
- 1:c4da9889ff85
- Child:
- 4:9480edf3926d
Typo fixed
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
antoniogonzalez | 0:7dbf7356da6b | 1 | #include "mcp342x.h" |
antoniogonzalez | 0:7dbf7356da6b | 2 | |
antoniogonzalez | 0:7dbf7356da6b | 3 | #define LEN_ONE_BYTE 1 |
antoniogonzalez | 0:7dbf7356da6b | 4 | |
antoniogonzalez | 0:7dbf7356da6b | 5 | MCP342x::MCP342x(I2C *i2c, uint8_t device_address) |
antoniogonzalez | 0:7dbf7356da6b | 6 | { |
antoniogonzalez | 1:c4da9889ff85 | 7 | _i2c = i2c; |
antoniogonzalez | 1:c4da9889ff85 | 8 | |
antoniogonzalez | 0:7dbf7356da6b | 9 | // The address byte is the device code (4 bits, hardcoded in |
antoniogonzalez | 0:7dbf7356da6b | 10 | // factory) and the device address (3 bits). These are shifted one |
antoniogonzalez | 0:7dbf7356da6b | 11 | // bit to the left because mbed uses 8-bit addresses. |
antoniogonzalez | 0:7dbf7356da6b | 12 | _address = (_device_code << 4) | (device_address << 1); |
antoniogonzalez | 1:c4da9889ff85 | 13 | |
antoniogonzalez | 1:c4da9889ff85 | 14 | // Initialise to default settings: channel 1, gain 1x, 12 bits. |
antoniogonzalez | 1:c4da9889ff85 | 15 | // It is necessary to do this to ensure that the variables |
antoniogonzalez | 1:c4da9889ff85 | 16 | // _resolution and _pga are properly set. |
antoniogonzalez | 1:c4da9889ff85 | 17 | _configuration = 0x10; |
antoniogonzalez | 0:7dbf7356da6b | 18 | set_channel(CHANNEL_1); |
antoniogonzalez | 0:7dbf7356da6b | 19 | set_resolution(RESOLUTION_12); |
antoniogonzalez | 0:7dbf7356da6b | 20 | set_pga(PGA_1); |
antoniogonzalez | 0:7dbf7356da6b | 21 | } |
antoniogonzalez | 0:7dbf7356da6b | 22 | |
antoniogonzalez | 0:7dbf7356da6b | 23 | void MCP342x::set_channel(mcp342x_channel_t channel) |
antoniogonzalez | 0:7dbf7356da6b | 24 | { |
antoniogonzalez | 1:c4da9889ff85 | 25 | _configuration &= REG_CHANNEL_Clear; |
antoniogonzalez | 1:c4da9889ff85 | 26 | _configuration |= channel << REG_CHANNEL_Pos; |
antoniogonzalez | 0:7dbf7356da6b | 27 | _write_configuration(); |
antoniogonzalez | 0:7dbf7356da6b | 28 | } |
antoniogonzalez | 0:7dbf7356da6b | 29 | |
antoniogonzalez | 0:7dbf7356da6b | 30 | void MCP342x::set_conversion_mode(mcp342x_conversion_mode_t mode) |
antoniogonzalez | 0:7dbf7356da6b | 31 | { |
antoniogonzalez | 1:c4da9889ff85 | 32 | _configuration &= REG_MODE_Clear; |
antoniogonzalez | 1:c4da9889ff85 | 33 | _configuration |= mode << REG_MODE_Pos; |
antoniogonzalez | 0:7dbf7356da6b | 34 | _write_configuration(); |
antoniogonzalez | 0:7dbf7356da6b | 35 | } |
antoniogonzalez | 0:7dbf7356da6b | 36 | |
antoniogonzalez | 0:7dbf7356da6b | 37 | void MCP342x::set_resolution(mcp342x_resolution_t resolution) |
antoniogonzalez | 0:7dbf7356da6b | 38 | { |
antoniogonzalez | 1:c4da9889ff85 | 39 | _resolution = resolution; |
antoniogonzalez | 1:c4da9889ff85 | 40 | |
antoniogonzalez | 1:c4da9889ff85 | 41 | // _lsb and _max_code are variables required for converting the ADC |
antoniogonzalez | 1:c4da9889ff85 | 42 | // data into volts; see Section 4.9 of the MCP342x datasheet. Their |
antoniogonzalez | 1:c4da9889ff85 | 43 | // value depends on the resolution chosen, so it is useful to |
antoniogonzalez | 1:c4da9889ff85 | 44 | // calculate these values here, whenever the resolution setting is |
antoniogonzalez | 1:c4da9889ff85 | 45 | // changed. |
antoniogonzalez | 1:c4da9889ff85 | 46 | // |
antoniogonzalez | 1:c4da9889ff85 | 47 | // _lsb is the magnitude (in volts) of the last significant byte, |
antoniogonzalez | 1:c4da9889ff85 | 48 | // and it is calculated as 2 * 2.048 / (2^N), where N is the |
antoniogonzalez | 1:c4da9889ff85 | 49 | // resolution (datasheet Eq. 4-3). |
antoniogonzalez | 1:c4da9889ff85 | 50 | // |
antoniogonzalez | 1:c4da9889ff85 | 51 | // _max_code is the maximum output code, and it is equal to |
antoniogonzalez | 1:c4da9889ff85 | 52 | // 2^(N-1) - 1 (datasheet Table 4-3). |
antoniogonzalez | 1:c4da9889ff85 | 53 | switch(_resolution){ |
antoniogonzalez | 0:7dbf7356da6b | 54 | case RESOLUTION_12: |
antoniogonzalez | 1:c4da9889ff85 | 55 | _lsb = 2 * 2.048 / 4096; |
antoniogonzalez | 1:c4da9889ff85 | 56 | _max_code = 2047; |
antoniogonzalez | 0:7dbf7356da6b | 57 | break; |
antoniogonzalez | 0:7dbf7356da6b | 58 | case RESOLUTION_14: |
antoniogonzalez | 1:c4da9889ff85 | 59 | _lsb = 2 * 2.048 / 16384; |
antoniogonzalez | 1:c4da9889ff85 | 60 | _max_code = 8191; |
antoniogonzalez | 0:7dbf7356da6b | 61 | break; |
antoniogonzalez | 0:7dbf7356da6b | 62 | case RESOLUTION_16: |
antoniogonzalez | 1:c4da9889ff85 | 63 | _lsb = 2 * 2.048 / 65536; |
antoniogonzalez | 1:c4da9889ff85 | 64 | _max_code = 32767; |
antoniogonzalez | 0:7dbf7356da6b | 65 | break; |
antoniogonzalez | 0:7dbf7356da6b | 66 | case RESOLUTION_18: |
antoniogonzalez | 1:c4da9889ff85 | 67 | _lsb = 2 * 2.048 / 262144; |
antoniogonzalez | 1:c4da9889ff85 | 68 | _max_code = 131071; |
antoniogonzalez | 0:7dbf7356da6b | 69 | break; |
antoniogonzalez | 1:c4da9889ff85 | 70 | } |
antoniogonzalez | 1:c4da9889ff85 | 71 | |
antoniogonzalez | 1:c4da9889ff85 | 72 | _configuration &= REG_RESOLUTION_Clear; |
antoniogonzalez | 1:c4da9889ff85 | 73 | _configuration |= _resolution << REG_RESOLUTION_Pos; |
antoniogonzalez | 0:7dbf7356da6b | 74 | _write_configuration(); |
antoniogonzalez | 0:7dbf7356da6b | 75 | } |
antoniogonzalez | 0:7dbf7356da6b | 76 | |
antoniogonzalez | 0:7dbf7356da6b | 77 | void MCP342x::set_pga(mcp342x_pga_t pga) |
antoniogonzalez | 0:7dbf7356da6b | 78 | { |
antoniogonzalez | 1:c4da9889ff85 | 79 | // The gain value (1, 2, 4 or 8) is required for converting digital |
antoniogonzalez | 1:c4da9889ff85 | 80 | // output codes to voltage. For this purpose the actual PGA value is |
antoniogonzalez | 1:c4da9889ff85 | 81 | // kept in the variable _pga, instead of keeping the *position* in |
antoniogonzalez | 1:c4da9889ff85 | 82 | // the register of PGA, which is what the variable type |
antoniogonzalez | 1:c4da9889ff85 | 83 | // mcp342x_pga_t represents. |
antoniogonzalez | 1:c4da9889ff85 | 84 | switch (pga) { |
antoniogonzalez | 0:7dbf7356da6b | 85 | case PGA_1: |
antoniogonzalez | 0:7dbf7356da6b | 86 | _pga = 1; |
antoniogonzalez | 0:7dbf7356da6b | 87 | break; |
antoniogonzalez | 0:7dbf7356da6b | 88 | case PGA_2: |
antoniogonzalez | 0:7dbf7356da6b | 89 | _pga = 2; |
antoniogonzalez | 0:7dbf7356da6b | 90 | break; |
antoniogonzalez | 0:7dbf7356da6b | 91 | case PGA_4: |
antoniogonzalez | 0:7dbf7356da6b | 92 | _pga = 4; |
antoniogonzalez | 0:7dbf7356da6b | 93 | break; |
antoniogonzalez | 0:7dbf7356da6b | 94 | case PGA_8: |
antoniogonzalez | 0:7dbf7356da6b | 95 | _pga = 8; |
antoniogonzalez | 0:7dbf7356da6b | 96 | break; |
antoniogonzalez | 1:c4da9889ff85 | 97 | } |
antoniogonzalez | 1:c4da9889ff85 | 98 | |
antoniogonzalez | 1:c4da9889ff85 | 99 | _configuration &= REG_PGA_Clear; |
antoniogonzalez | 1:c4da9889ff85 | 100 | _configuration |= pga << REG_PGA_Pos; |
antoniogonzalez | 0:7dbf7356da6b | 101 | _write_configuration(); |
antoniogonzalez | 0:7dbf7356da6b | 102 | } |
antoniogonzalez | 0:7dbf7356da6b | 103 | |
antoniogonzalez | 0:7dbf7356da6b | 104 | void MCP342x::_write_configuration() |
antoniogonzalez | 0:7dbf7356da6b | 105 | { |
antoniogonzalez | 1:c4da9889ff85 | 106 | _i2c_command[0] = _configuration; |
antoniogonzalez | 1:c4da9889ff85 | 107 | _i2c->write(_address, _i2c_command, LEN_ONE_BYTE); |
antoniogonzalez | 0:7dbf7356da6b | 108 | } |
antoniogonzalez | 0:7dbf7356da6b | 109 | |
antoniogonzalez | 1:c4da9889ff85 | 110 | uint32_t MCP342x::read() |
antoniogonzalez | 0:7dbf7356da6b | 111 | { |
antoniogonzalez | 1:c4da9889ff85 | 112 | uint32_t adc_value = 0; |
antoniogonzalez | 1:c4da9889ff85 | 113 | _i2c->read(_address, _i2c_command, COMMAND_N_BYTES); |
antoniogonzalez | 0:7dbf7356da6b | 114 | |
antoniogonzalez | 0:7dbf7356da6b | 115 | switch (_resolution) { |
antoniogonzalez | 1:c4da9889ff85 | 116 | case RESOLUTION_12: |
antoniogonzalez | 1:c4da9889ff85 | 117 | adc_value = (_i2c_command[0] << 8) | _i2c_command[1]; |
antoniogonzalez | 0:7dbf7356da6b | 118 | adc_value &= 0xfff; |
antoniogonzalez | 0:7dbf7356da6b | 119 | break; |
antoniogonzalez | 0:7dbf7356da6b | 120 | |
antoniogonzalez | 1:c4da9889ff85 | 121 | case RESOLUTION_14: |
antoniogonzalez | 1:c4da9889ff85 | 122 | adc_value = (_i2c_command[0] << 8) | _i2c_command[1]; |
antoniogonzalez | 0:7dbf7356da6b | 123 | adc_value &= 0x3fff; |
antoniogonzalez | 0:7dbf7356da6b | 124 | break; |
antoniogonzalez | 0:7dbf7356da6b | 125 | |
antoniogonzalez | 1:c4da9889ff85 | 126 | case RESOLUTION_16: |
antoniogonzalez | 1:c4da9889ff85 | 127 | adc_value = (_i2c_command[0] << 8) | _i2c_command[1]; |
antoniogonzalez | 0:7dbf7356da6b | 128 | adc_value &= 0xffff; |
antoniogonzalez | 0:7dbf7356da6b | 129 | break; |
antoniogonzalez | 0:7dbf7356da6b | 130 | |
antoniogonzalez | 1:c4da9889ff85 | 131 | case RESOLUTION_18: |
antoniogonzalez | 1:c4da9889ff85 | 132 | adc_value = (_i2c_command[0] << 16) | |
antoniogonzalez | 1:c4da9889ff85 | 133 | (_i2c_command[1] << 8) | _i2c_command[2]; |
antoniogonzalez | 0:7dbf7356da6b | 134 | adc_value &= 0x3ffff; |
antoniogonzalez | 0:7dbf7356da6b | 135 | break; |
antoniogonzalez | 0:7dbf7356da6b | 136 | } |
antoniogonzalez | 0:7dbf7356da6b | 137 | return adc_value; |
antoniogonzalez | 0:7dbf7356da6b | 138 | } |
antoniogonzalez | 1:c4da9889ff85 | 139 | |
antoniogonzalez | 1:c4da9889ff85 | 140 | float MCP342x::read_volts(){ |
antoniogonzalez | 1:c4da9889ff85 | 141 | float volts = 0.0; |
antoniogonzalez | 1:c4da9889ff85 | 142 | uint32_t adc_value = read(); |
antoniogonzalez | 1:c4da9889ff85 | 143 | |
antoniogonzalez | 1:c4da9889ff85 | 144 | // The digital output of the MCP342x is in two's complement format; |
antoniogonzalez | 1:c4da9889ff85 | 145 | // see datasheet Section 4.9. This 'if... else' construction |
antoniogonzalez | 1:c4da9889ff85 | 146 | // determines whether the digital code is negative or positive; if |
antoniogonzalez | 3:03911aa07029 | 147 | // it is the former, its two's complement is calculated. |
antoniogonzalez | 1:c4da9889ff85 | 148 | if (adc_value > _max_code) { |
antoniogonzalez | 1:c4da9889ff85 | 149 | // if the output code is negative... |
antoniogonzalez | 1:c4da9889ff85 | 150 | volts = (~adc_value & _max_code) + 1; |
antoniogonzalez | 1:c4da9889ff85 | 151 | volts *= -1; |
antoniogonzalez | 1:c4da9889ff85 | 152 | } else { |
antoniogonzalez | 1:c4da9889ff85 | 153 | // if the output code is positive... |
antoniogonzalez | 1:c4da9889ff85 | 154 | volts = (float)adc_value; |
antoniogonzalez | 1:c4da9889ff85 | 155 | } |
antoniogonzalez | 1:c4da9889ff85 | 156 | |
antoniogonzalez | 1:c4da9889ff85 | 157 | // The actual voltage is proportional to the resolution and PGA |
antoniogonzalez | 1:c4da9889ff85 | 158 | // settings. This equation corresponds to Equation 4-4 in the |
antoniogonzalez | 1:c4da9889ff85 | 159 | // datasheet. The variables _lsb and _pga are calculated whenever |
antoniogonzalez | 1:c4da9889ff85 | 160 | // the user changes the resolution or PGA parameters. |
antoniogonzalez | 1:c4da9889ff85 | 161 | return volts * _lsb / _pga; |
antoniogonzalez | 1:c4da9889ff85 | 162 | } |