Microchip MCP342x ADC library

Committer:
SomeRandomBloke
Date:
Thu Sep 24 19:09:51 2020 +0000
Revision:
7:82a309e53326
Parent:
6:5c60f0b0b1c1
First push

Who changed what in which revision?

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