Microchip MCP342x ADC library

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
antoniogonzalez 0:7dbf7356da6b 1 /**
antoniogonzalez 0:7dbf7356da6b 2 * Author: Antonio Gonzalez <antgon@cantab.net>
antoniogonzalez 0:7dbf7356da6b 3 * Copyright (c) 2016 The Francis Crick Institute.
antoniogonzalez 0:7dbf7356da6b 4 *
antoniogonzalez 0:7dbf7356da6b 5 * This program is free software: you can redistribute it and/or modify
antoniogonzalez 0:7dbf7356da6b 6 * it under the terms of the GNU General Public License as published by
antoniogonzalez 0:7dbf7356da6b 7 * the Free Software Foundation, either version 3 of the License, or
antoniogonzalez 0:7dbf7356da6b 8 * (at your option) any later version.
antoniogonzalez 0:7dbf7356da6b 9 *
antoniogonzalez 0:7dbf7356da6b 10 * This program is distributed in the hope that it will be useful,
antoniogonzalez 0:7dbf7356da6b 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
antoniogonzalez 0:7dbf7356da6b 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
antoniogonzalez 0:7dbf7356da6b 13 * GNU General Public License for more details.
antoniogonzalez 0:7dbf7356da6b 14 *
antoniogonzalez 0:7dbf7356da6b 15 * You should have received a copy of the GNU General Public License
antoniogonzalez 0:7dbf7356da6b 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
antoniogonzalez 0:7dbf7356da6b 17 */
antoniogonzalez 0:7dbf7356da6b 18
antoniogonzalez 0:7dbf7356da6b 19 #ifndef MCP342x_h
antoniogonzalez 0:7dbf7356da6b 20 #define MCP342x_h
antoniogonzalez 0:7dbf7356da6b 21
antoniogonzalez 0:7dbf7356da6b 22 #include "mbed.h"
antoniogonzalez 0:7dbf7356da6b 23
antoniogonzalez 1:c4da9889ff85 24 #define COMMAND_N_BYTES 5
SomeRandomBloke 7:82a309e53326 25 #define MCP342X_FREQ 100000
antoniogonzalez 1:c4da9889ff85 26
antoniogonzalez 0:7dbf7356da6b 27 /**
antoniogonzalez 0:7dbf7356da6b 28 * @brief Microchip analog-to-digital converter MCP3422/3/4
antoniogonzalez 0:7dbf7356da6b 29 *
antoniogonzalez 0:7dbf7356da6b 30 * Library for using Microchip's family of analog-to-digital converters
antoniogonzalez 0:7dbf7356da6b 31 * MCP3422/3/4. Some features of these include:
antoniogonzalez 0:7dbf7356da6b 32 * - 12-, 14-, 16-, or 18-bit ADC.
antoniogonzalez 0:7dbf7356da6b 33 * - Two-wire I2C interface.
antoniogonzalez 0:7dbf7356da6b 34 * - Sampling rate, 3.75 (18-bit), 15 (16-bit), 60 (14-bit), or 240
antoniogonzalez 0:7dbf7356da6b 35 * (12-bit) SPS.
antoniogonzalez 0:7dbf7356da6b 36 * - Two (MCP3422/3) or four (MCP3424) channels, differential input.
antoniogonzalez 0:7dbf7356da6b 37 * - Internal voltage reference, 2.048 V.
antoniogonzalez 0:7dbf7356da6b 38 * - Selectable PGA, x1, x2, x4, or x8.
antoniogonzalez 0:7dbf7356da6b 39 * - Conversion modes: one-shot or continuous.
antoniogonzalez 0:7dbf7356da6b 40 *
antoniogonzalez 0:7dbf7356da6b 41 * TODO:
antoniogonzalez 0:7dbf7356da6b 42 * - Implement 'conversion mode one-shot'
antoniogonzalez 0:7dbf7356da6b 43 *
antoniogonzalez 2:639a5612903f 44 * Example 1: Minimum functionallity.
antoniogonzalez 0:7dbf7356da6b 45 * @code
antoniogonzalez 0:7dbf7356da6b 46 * #include "mbed.h"
antoniogonzalez 0:7dbf7356da6b 47 * #include "mcp342x.h"
antoniogonzalez 0:7dbf7356da6b 48 *
antoniogonzalez 0:7dbf7356da6b 49 * I2C i2c(p9, p10);
antoniogonzalez 0:7dbf7356da6b 50 * MCP342x mcp_adc(&i2c);
antoniogonzalez 0:7dbf7356da6b 51 *
antoniogonzalez 0:7dbf7356da6b 52 * int main(){
antoniogonzalez 0:7dbf7356da6b 53 * mcp_adc.set_channel(MCP342x::CHANNEL_2);
antoniogonzalez 0:7dbf7356da6b 54 * mcp_adc.set_pga(MCP342x::PGA_4);
antoniogonzalez 0:7dbf7356da6b 55 * mcp_adc.set_resolution(MCP342x::RESOLUTION_12);
antoniogonzalez 0:7dbf7356da6b 56 *
antoniogonzalez 0:7dbf7356da6b 57 * while(1){
antoniogonzalez 0:7dbf7356da6b 58 * // Channel 2 was selected above. Read data from this channel.
antoniogonzalez 1:c4da9889ff85 59 * float chan2_val = mcp_adc.read_volts();
antoniogonzalez 0:7dbf7356da6b 60 *
antoniogonzalez 0:7dbf7356da6b 61 * // Select now channel 1 and read it.
antoniogonzalez 0:7dbf7356da6b 62 * mcp_adc.set_channel(MCP342x::CHANNEL_1);
antoniogonzalez 1:c4da9889ff85 63 * float chan1_val = mcp_adc.read_volts();
antoniogonzalez 0:7dbf7356da6b 64 *
antoniogonzalez 1:c4da9889ff85 65 * printf("CH1 %.3f; CH2 %.3f\r\n", chan1_val, chan2_val);
antoniogonzalez 0:7dbf7356da6b 66 * wait(5);
antoniogonzalez 0:7dbf7356da6b 67 * }
antoniogonzalez 0:7dbf7356da6b 68 * }
antoniogonzalez 0:7dbf7356da6b 69 * @endcode
antoniogonzalez 2:639a5612903f 70 *
antoniogonzalez 2:639a5612903f 71 * Example 2: Compare MPC342x with mbed analog input.
antoniogonzalez 2:639a5612903f 72 *
antoniogonzalez 2:639a5612903f 73 * In this example a voltage is applied on pin 18 (AnalogOut), and this
antoniogonzalez 2:639a5612903f 74 * is read by both one of the mbed's analog inputs and by the MCP342x.
antoniogonzalez 2:639a5612903f 75 * It is useful for checking that the chip is properly connected and
antoniogonzalez 2:639a5612903f 76 * this library is working as expected, etc.
antoniogonzalez 2:639a5612903f 77 * @code
antoniogonzalez 2:639a5612903f 78 * // Connect:
antoniogonzalez 2:639a5612903f 79 * // - MCP342x CH1- to ground.
antoniogonzalez 2:639a5612903f 80 * // - MCP342x CH1+ to mbed p18.
antoniogonzalez 2:639a5612903f 81 * // - mbed ANALOG_IN (defined below) to mbed p18.
antoniogonzalez 2:639a5612903f 82 * // Then open a terminal.
antoniogonzalez 2:639a5612903f 83 * #include "mbed.h"
antoniogonzalez 2:639a5612903f 84 * #include "mcp342x.h"
antoniogonzalez 2:639a5612903f 85 *
antoniogonzalez 2:639a5612903f 86 * #define SDA_PIN p28
antoniogonzalez 2:639a5612903f 87 * #define SCL_PIN p27
antoniogonzalez 2:639a5612903f 88 * #define ANALOG_IN p20
antoniogonzalez 2:639a5612903f 89 * #define ANALOG_OUT p18
antoniogonzalez 2:639a5612903f 90 *
antoniogonzalez 2:639a5612903f 91 * I2C i2c(SDA_PIN, SCL_PIN);
antoniogonzalez 2:639a5612903f 92 * MCP342x mcp_adc(&i2c);
antoniogonzalez 2:639a5612903f 93 *
antoniogonzalez 2:639a5612903f 94 * DigitalOut led1(LED1);
antoniogonzalez 2:639a5612903f 95 * AnalogOut dac(ANALOG_OUT);
antoniogonzalez 2:639a5612903f 96 * AnalogIn ain(ANALOG_IN);
antoniogonzalez 2:639a5612903f 97 *
antoniogonzalez 2:639a5612903f 98 * float mbed_Vin;
antoniogonzalez 2:639a5612903f 99 * float Vout = 0.1/3.3;
antoniogonzalez 2:639a5612903f 100 * float mcp_Vin;
antoniogonzalez 2:639a5612903f 101 *
antoniogonzalez 2:639a5612903f 102 * int main(){
antoniogonzalez 2:639a5612903f 103 * i2c.frequency(400000);
antoniogonzalez 2:639a5612903f 104 * mcp_adc.set_resolution(MCP342x::RESOLUTION_16);
antoniogonzalez 2:639a5612903f 105 *
antoniogonzalez 2:639a5612903f 106 * while(1){
antoniogonzalez 2:639a5612903f 107 * // Set the output voltage.
antoniogonzalez 2:639a5612903f 108 * dac = Vout;
antoniogonzalez 2:639a5612903f 109 * wait(2);
antoniogonzalez 2:639a5612903f 110 *
antoniogonzalez 2:639a5612903f 111 * // Read voltage using both the mbed and the MCP342x.
antoniogonzalez 2:639a5612903f 112 * led1 = 1;
antoniogonzalez 2:639a5612903f 113 * mcp_Vin = mcp_adc.read_volts();
antoniogonzalez 2:639a5612903f 114 * mbed_Vin = ain.read() * 3.3;
antoniogonzalez 2:639a5612903f 115 *
antoniogonzalez 2:639a5612903f 116 * // Display both values.
antoniogonzalez 2:639a5612903f 117 * printf("\r\nmcp Vin = %.2f\r\n", mcp_Vin);
antoniogonzalez 2:639a5612903f 118 * printf("mbed Vin = %.2f\r\n", mbed_Vin);
antoniogonzalez 2:639a5612903f 119 * led1 = 0;
antoniogonzalez 2:639a5612903f 120 *
antoniogonzalez 2:639a5612903f 121 * // Increment output voltage by 0.1 V.
antoniogonzalez 2:639a5612903f 122 * Vout += 0.1/3.3;
antoniogonzalez 2:639a5612903f 123 *
antoniogonzalez 2:639a5612903f 124 * // If the output voltage goes above 2.5 V, reset to 0.5 V.
antoniogonzalez 2:639a5612903f 125 * if (Vout >= 2.5/3.3){
antoniogonzalez 2:639a5612903f 126 * Vout = 0.5/3.3;
antoniogonzalez 2:639a5612903f 127 * }
antoniogonzalez 2:639a5612903f 128 * }
antoniogonzalez 2:639a5612903f 129 * }
antoniogonzalez 2:639a5612903f 130 * @endcode
antoniogonzalez 0:7dbf7356da6b 131 */
antoniogonzalez 0:7dbf7356da6b 132 class MCP342x
antoniogonzalez 0:7dbf7356da6b 133 {
antoniogonzalez 0:7dbf7356da6b 134 public:
antoniogonzalez 0:7dbf7356da6b 135 // Registers.
antoniogonzalez 0:7dbf7356da6b 136 // The device has only one register, which is the configuration
antoniogonzalez 0:7dbf7356da6b 137 // byte. It consists of these bits:
antoniogonzalez 0:7dbf7356da6b 138 // 7 ~ready
antoniogonzalez 0:7dbf7356da6b 139 // 6-5 channel selection
antoniogonzalez 0:7dbf7356da6b 140 // 4 conversion mode (one-shot, continuous)
antoniogonzalez 0:7dbf7356da6b 141 // 3-2 sample rate selection (12, 14, 16, or 18)
antoniogonzalez 0:7dbf7356da6b 142 // 1-0 PGA gain selection (1x, 2x, 4x, or 8x)
antoniogonzalez 0:7dbf7356da6b 143 typedef enum {
antoniogonzalez 0:7dbf7356da6b 144 REG_PGA_Pos = 0,
antoniogonzalez 0:7dbf7356da6b 145 REG_RESOLUTION_Pos = 2,
antoniogonzalez 0:7dbf7356da6b 146 REG_MODE_Pos = 4,
antoniogonzalez 0:7dbf7356da6b 147 REG_CHANNEL_Pos = 5,
antoniogonzalez 0:7dbf7356da6b 148 REG_RDY_Pos = 7,
antoniogonzalez 0:7dbf7356da6b 149
antoniogonzalez 0:7dbf7356da6b 150 REG_PGA_Clear = ~(0x3 << REG_PGA_Pos),
antoniogonzalez 0:7dbf7356da6b 151 REG_RESOLUTION_Clear = ~(0x3 << REG_RESOLUTION_Pos),
antoniogonzalez 0:7dbf7356da6b 152 REG_MODE_Clear = ~(0x1 << REG_MODE_Pos),
antoniogonzalez 0:7dbf7356da6b 153 REG_CHANNEL_Clear = ~(0x3 << REG_CHANNEL_Pos),
antoniogonzalez 0:7dbf7356da6b 154 REG_RDY_Clear = ~(0x1 << REG_RDY_Pos)
antoniogonzalez 0:7dbf7356da6b 155 } mcp342x_reg_t;
antoniogonzalez 0:7dbf7356da6b 156
antoniogonzalez 0:7dbf7356da6b 157 // Programmable gain.
antoniogonzalez 0:7dbf7356da6b 158 typedef enum {
antoniogonzalez 0:7dbf7356da6b 159 PGA_1 = 0,
antoniogonzalez 0:7dbf7356da6b 160 PGA_2 = 1,
antoniogonzalez 0:7dbf7356da6b 161 PGA_4 = 2,
antoniogonzalez 0:7dbf7356da6b 162 PGA_8 = 3
antoniogonzalez 0:7dbf7356da6b 163 } mcp342x_pga_t;
antoniogonzalez 0:7dbf7356da6b 164
antoniogonzalez 0:7dbf7356da6b 165 // Resolution.
antoniogonzalez 0:7dbf7356da6b 166 typedef enum {
antoniogonzalez 0:7dbf7356da6b 167 RESOLUTION_12 = 0,
antoniogonzalez 0:7dbf7356da6b 168 RESOLUTION_14 = 1,
antoniogonzalez 0:7dbf7356da6b 169 RESOLUTION_16 = 2,
antoniogonzalez 0:7dbf7356da6b 170 RESOLUTION_18 = 3
antoniogonzalez 0:7dbf7356da6b 171 } mcp342x_resolution_t;
antoniogonzalez 0:7dbf7356da6b 172
antoniogonzalez 0:7dbf7356da6b 173 // Conversion mode.
antoniogonzalez 0:7dbf7356da6b 174 typedef enum {
antoniogonzalez 0:7dbf7356da6b 175 CONVERSION_MODE_ONESHOT = 0,
antoniogonzalez 0:7dbf7356da6b 176 CONVERSION_MODE_CONTINUOUS = 1
antoniogonzalez 0:7dbf7356da6b 177 } mcp342x_conversion_mode_t;
antoniogonzalez 0:7dbf7356da6b 178
antoniogonzalez 0:7dbf7356da6b 179 // Channels.
antoniogonzalez 0:7dbf7356da6b 180 typedef enum {
antoniogonzalez 0:7dbf7356da6b 181 CHANNEL_1 = 0,
antoniogonzalez 0:7dbf7356da6b 182 CHANNEL_2 = 1,
antoniogonzalez 0:7dbf7356da6b 183 CHANNEL_3 = 2,
antoniogonzalez 0:7dbf7356da6b 184 CHANNEL_4 = 3
antoniogonzalez 0:7dbf7356da6b 185 } mcp342x_channel_t;
antoniogonzalez 0:7dbf7356da6b 186
antoniogonzalez 0:7dbf7356da6b 187 /**
antoniogonzalez 0:7dbf7356da6b 188 * MCP342x constructor
antoniogonzalez 0:7dbf7356da6b 189 *
antoniogonzalez 0:7dbf7356da6b 190 * @param i2c Pointer to I2C
antoniogonzalez 0:7dbf7356da6b 191 * @param device_address Address for this sensor
antoniogonzalez 0:7dbf7356da6b 192 */
antoniogonzalez 0:7dbf7356da6b 193 MCP342x(I2C *i2c, uint8_t device_address = 0b000);
SomeRandomBloke 4:9480edf3926d 194
antoniogonzalez 0:7dbf7356da6b 195 /**
antoniogonzalez 0:7dbf7356da6b 196 * Set channel to read from.
antoniogonzalez 0:7dbf7356da6b 197 *
antoniogonzalez 0:7dbf7356da6b 198 * @param channel Channel number
antoniogonzalez 0:7dbf7356da6b 199 */
antoniogonzalez 0:7dbf7356da6b 200 void set_channel(mcp342x_channel_t channel);
antoniogonzalez 0:7dbf7356da6b 201
antoniogonzalez 0:7dbf7356da6b 202 /**
antoniogonzalez 0:7dbf7356da6b 203 * Set conversion mode.
antoniogonzalez 0:7dbf7356da6b 204 *
antoniogonzalez 0:7dbf7356da6b 205 * @param mode Conversion mode. Options are
antoniogonzalez 0:7dbf7356da6b 206 * MCP342x::CONVERSION_MODE_ONESHOT or
antoniogonzalez 0:7dbf7356da6b 207 * MCP342x::CONVERSION_MODE_CONTINUOUS.
antoniogonzalez 0:7dbf7356da6b 208 */
antoniogonzalez 0:7dbf7356da6b 209 void set_conversion_mode(mcp342x_conversion_mode_t mode);
antoniogonzalez 0:7dbf7356da6b 210
antoniogonzalez 0:7dbf7356da6b 211 /**
antoniogonzalez 0:7dbf7356da6b 212 * Set resolution.
antoniogonzalez 0:7dbf7356da6b 213 *
antoniogonzalez 0:7dbf7356da6b 214 * @param resolution Resolution, one of
antoniogonzalez 0:7dbf7356da6b 215 * MCP342x::RESOLUTION_12, MCP342x::RESOLUTION_14,
antoniogonzalez 0:7dbf7356da6b 216 * MCP342x::RESOLUTION_16 or MCP342x::RESOLUTION_18.
antoniogonzalez 0:7dbf7356da6b 217 */
antoniogonzalez 0:7dbf7356da6b 218 void set_resolution(mcp342x_resolution_t resolution);
antoniogonzalez 0:7dbf7356da6b 219
antoniogonzalez 0:7dbf7356da6b 220 /**
antoniogonzalez 0:7dbf7356da6b 221 * Set programable gain amplifier. Options are
antoniogonzalez 0:7dbf7356da6b 222 * MCP342x::PGA_1, MCP342x::PGA_2, MCP342x::PGA_4, or MCP342x::PGA_8.
antoniogonzalez 0:7dbf7356da6b 223 */
antoniogonzalez 0:7dbf7356da6b 224 void set_pga(mcp342x_pga_t pga);
antoniogonzalez 0:7dbf7356da6b 225
antoniogonzalez 0:7dbf7356da6b 226 /**
antoniogonzalez 1:c4da9889ff85 227 * Read the ADC value. The value will be that read from whatever
antoniogonzalez 1:c4da9889ff85 228 * channel was set previously (`set_channel`).
antoniogonzalez 0:7dbf7356da6b 229 *
antoniogonzalez 0:7dbf7356da6b 230 * @return Analog measurement in raw data (integer)
antoniogonzalez 0:7dbf7356da6b 231 */
antoniogonzalez 1:c4da9889ff85 232 uint32_t read();
antoniogonzalez 0:7dbf7356da6b 233
antoniogonzalez 0:7dbf7356da6b 234 /**
antoniogonzalez 1:c4da9889ff85 235 * Read the ADC value in volts. The value will be that read from
antoniogonzalez 1:c4da9889ff85 236 * whatever channel was set previously (`set_channel`).
antoniogonzalez 0:7dbf7356da6b 237 *
antoniogonzalez 0:7dbf7356da6b 238 * The data are coded in two's complements format, and the final
antoniogonzalez 0:7dbf7356da6b 239 * voltage is also a function of the resolution and gain settings.
antoniogonzalez 1:c4da9889ff85 240 * This function follows the equations presented in Section 4.9 of
antoniogonzalez 1:c4da9889ff85 241 * the device's datasheet (Microchip DS22088C).
antoniogonzalez 0:7dbf7356da6b 242 *
antoniogonzalez 0:7dbf7356da6b 243 * @return Analog measurement in volts (float)
antoniogonzalez 0:7dbf7356da6b 244 */
antoniogonzalez 0:7dbf7356da6b 245 float read_volts();
antoniogonzalez 0:7dbf7356da6b 246
antoniogonzalez 1:c4da9889ff85 247 //void start_conversion(void); For one-shot mode.
antoniogonzalez 1:c4da9889ff85 248
antoniogonzalez 0:7dbf7356da6b 249 private:
antoniogonzalez 1:c4da9889ff85 250 // Variables and functions for I2C communication.
antoniogonzalez 0:7dbf7356da6b 251 I2C *_i2c;
antoniogonzalez 1:c4da9889ff85 252 uint8_t _address;
antoniogonzalez 1:c4da9889ff85 253 char _i2c_command[COMMAND_N_BYTES];
antoniogonzalez 1:c4da9889ff85 254 uint8_t _configuration;
antoniogonzalez 0:7dbf7356da6b 255 static const uint8_t _device_code = 0b1101; // Hardcoded in factory
antoniogonzalez 0:7dbf7356da6b 256 void _write_configuration();
SomeRandomBloke 4:9480edf3926d 257 void _startRead();
antoniogonzalez 1:c4da9889ff85 258
antoniogonzalez 1:c4da9889ff85 259 // Variables needed for converting digital output codes to real
antoniogonzalez 1:c4da9889ff85 260 // values (i.e. voltage).
antoniogonzalez 1:c4da9889ff85 261 mcp342x_resolution_t _resolution;
antoniogonzalez 1:c4da9889ff85 262 uint8_t _pga;
antoniogonzalez 1:c4da9889ff85 263 float _lsb;
antoniogonzalez 1:c4da9889ff85 264 uint32_t _max_code;
antoniogonzalez 0:7dbf7356da6b 265 };
antoniogonzalez 0:7dbf7356da6b 266
antoniogonzalez 0:7dbf7356da6b 267 #endif