Microchip MCP342x ADC library

Committer:
SomeRandomBloke
Date:
Mon Sep 10 17:02:22 2018 +0000
Revision:
4:9480edf3926d
Parent:
2:639a5612903f
Child:
5:0ca445d2d2bc
Updates to add end of conversion checking

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