Antonio Gonzalez / MCP342x
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mcp342x.h Source File

mcp342x.h

00001 /**
00002  * Author: Antonio Gonzalez <antgon@cantab.net>
00003  * Copyright (c) 2016 The Francis Crick Institute.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #ifndef MCP342x_h
00020 #define MCP342x_h
00021 
00022 #include "mbed.h"
00023 
00024 #define COMMAND_N_BYTES 5
00025 
00026 /**
00027  * @brief Microchip analog-to-digital converter MCP3422/3/4
00028  *
00029  * Library for using Microchip's family of analog-to-digital converters
00030  * MCP3422/3/4. Some features of these include:
00031  * - 12-, 14-, 16-, or 18-bit ADC.
00032  * - Two-wire I2C interface.
00033  * - Sampling rate, 3.75 (18-bit), 15 (16-bit), 60 (14-bit), or 240
00034  *   (12-bit) SPS.
00035  * - Two (MCP3422/3) or four (MCP3424) channels, differential input.
00036  * - Internal voltage reference, 2.048 V.
00037  * - Selectable PGA, x1, x2, x4, or x8.
00038  * - Conversion modes: one-shot or continuous.
00039  *
00040  * TODO:
00041  * - Implement 'conversion mode one-shot'
00042  *
00043  * Example 1: Minimum functionallity.
00044  * @code
00045  * #include "mbed.h"
00046  * #include "mcp342x.h"
00047  *
00048  * I2C i2c(p9, p10);
00049  * MCP342x mcp_adc(&i2c);
00050  *
00051  * int main(){
00052  *     mcp_adc.set_channel(MCP342x::CHANNEL_2);
00053  *     mcp_adc.set_pga(MCP342x::PGA_4);
00054  *     mcp_adc.set_resolution(MCP342x::RESOLUTION_12);
00055  *
00056  *     while(1){
00057  *         // Channel 2 was selected above. Read data from this channel.
00058  *         float chan2_val = mcp_adc.read_volts();
00059  *
00060  *         // Select now channel 1 and read it.
00061  *         mcp_adc.set_channel(MCP342x::CHANNEL_1);
00062  *         float chan1_val = mcp_adc.read_volts();
00063  *
00064  *         printf("CH1 %.3f; CH2 %.3f\r\n", chan1_val, chan2_val);
00065  *         wait(5);
00066  *     }
00067  * }
00068  * @endcode
00069  *
00070  * Example 2: Compare MPC342x with mbed analog input.
00071  *
00072  * In this example a voltage is applied on pin 18 (AnalogOut), and this
00073  * is read by both one of the mbed's analog inputs and by the MCP342x.
00074  * It is useful for checking that the chip is properly connected and
00075  * this library is working as expected, etc.
00076  * @code
00077  * // Connect:
00078  * //     - MCP342x CH1- to ground.
00079  * //     - MCP342x CH1+ to mbed p18.
00080  * //     - mbed ANALOG_IN (defined below) to mbed p18.
00081  * // Then open a terminal.
00082  * #include "mbed.h"
00083  * #include "mcp342x.h"
00084  *
00085  * #define SDA_PIN p28
00086  * #define SCL_PIN p27
00087  * #define ANALOG_IN p20
00088  * #define ANALOG_OUT p18
00089  *
00090  * I2C i2c(SDA_PIN, SCL_PIN);
00091  * MCP342x mcp_adc(&i2c);
00092  *
00093  * DigitalOut led1(LED1);
00094  * AnalogOut dac(ANALOG_OUT);
00095  * AnalogIn ain(ANALOG_IN);
00096  *
00097  * float mbed_Vin;
00098  * float Vout = 0.1/3.3;
00099  * float mcp_Vin;
00100  *
00101  * int main(){
00102  *     i2c.frequency(400000);
00103  *     mcp_adc.set_resolution(MCP342x::RESOLUTION_16);
00104  *
00105  *     while(1){
00106  *         // Set the output voltage.
00107  *         dac = Vout;
00108  *         wait(2);
00109  *
00110  *         // Read voltage using both the mbed and the MCP342x.
00111  *         led1 = 1;
00112  *         mcp_Vin = mcp_adc.read_volts();
00113  *         mbed_Vin = ain.read() * 3.3;
00114  *
00115  *         // Display both values.
00116  *         printf("\r\nmcp Vin = %.2f\r\n", mcp_Vin);
00117  *         printf("mbed Vin = %.2f\r\n", mbed_Vin);
00118  *         led1 = 0;
00119  *
00120  *         // Increment output voltage by 0.1 V.
00121  *         Vout += 0.1/3.3;
00122  *
00123  *         // If the output voltage goes above 2.5 V, reset to 0.5 V.
00124  *         if (Vout >= 2.5/3.3){
00125  *             Vout = 0.5/3.3;
00126  *         }
00127  * }
00128  * }
00129  * @endcode
00130  */
00131 class MCP342x
00132 {
00133 public:
00134     // Registers.
00135     // The device has only one register, which is the configuration
00136     // byte. It consists of these bits:
00137     //   7    ~ready
00138     //   6-5  channel selection
00139     //   4    conversion mode (one-shot, continuous)
00140     //   3-2  sample rate selection (12, 14, 16, or 18)
00141     //   1-0  PGA gain selection (1x, 2x, 4x, or 8x)
00142     typedef enum {
00143         REG_PGA_Pos = 0,
00144         REG_RESOLUTION_Pos = 2,
00145         REG_MODE_Pos = 4,
00146         REG_CHANNEL_Pos = 5,
00147         REG_RDY_Pos = 7,
00148 
00149         REG_PGA_Clear = ~(0x3 << REG_PGA_Pos),
00150         REG_RESOLUTION_Clear = ~(0x3 << REG_RESOLUTION_Pos),
00151         REG_MODE_Clear = ~(0x1 << REG_MODE_Pos),
00152         REG_CHANNEL_Clear = ~(0x3 << REG_CHANNEL_Pos),
00153         REG_RDY_Clear = ~(0x1 << REG_RDY_Pos)
00154     } mcp342x_reg_t;
00155 
00156     // Programmable gain.
00157     typedef enum {
00158         PGA_1 = 0,
00159         PGA_2 = 1,
00160         PGA_4 = 2,
00161         PGA_8 = 3
00162     } mcp342x_pga_t;
00163 
00164     // Resolution.
00165     typedef enum {
00166         RESOLUTION_12 = 0,
00167         RESOLUTION_14 = 1,
00168         RESOLUTION_16 = 2,
00169         RESOLUTION_18 = 3
00170     } mcp342x_resolution_t;
00171 
00172     // Conversion mode.
00173     typedef enum {
00174         CONVERSION_MODE_ONESHOT = 0,
00175         CONVERSION_MODE_CONTINUOUS = 1
00176     } mcp342x_conversion_mode_t;
00177 
00178     // Channels.
00179     typedef enum {
00180         CHANNEL_1 = 0,
00181         CHANNEL_2 = 1,
00182         CHANNEL_3 = 2,
00183         CHANNEL_4 = 3
00184     } mcp342x_channel_t;
00185 
00186     /**
00187     * MCP342x constructor
00188     *
00189     * @param i2c Pointer to I2C
00190     * @param device_address Address for this sensor
00191     */
00192     MCP342x(I2C *i2c, uint8_t device_address = 0b000);
00193 
00194     /**
00195     * Set channel to read from.
00196     *
00197     * @param channel Channel number
00198     */
00199     void set_channel(mcp342x_channel_t channel);
00200 
00201     /**
00202     * Set conversion mode.
00203     *
00204     * @param mode Conversion mode. Options are
00205     * MCP342x::CONVERSION_MODE_ONESHOT or
00206     * MCP342x::CONVERSION_MODE_CONTINUOUS.
00207     */
00208     void set_conversion_mode(mcp342x_conversion_mode_t mode);
00209 
00210     /**
00211     * Set resolution.
00212     *
00213     * @param resolution Resolution, one of
00214     * MCP342x::RESOLUTION_12, MCP342x::RESOLUTION_14,
00215     * MCP342x::RESOLUTION_16 or MCP342x::RESOLUTION_18.
00216     */
00217     void set_resolution(mcp342x_resolution_t resolution);
00218 
00219     /**
00220     * Set programable gain amplifier. Options are
00221     * MCP342x::PGA_1, MCP342x::PGA_2, MCP342x::PGA_4, or MCP342x::PGA_8.
00222     */
00223     void set_pga(mcp342x_pga_t pga);
00224 
00225     /**
00226     * Read the ADC value. The value will be that read from whatever
00227     * channel was set previously (`set_channel`).
00228     *
00229     * @return Analog measurement in raw data (integer)
00230     */
00231     uint32_t read();
00232 
00233     /**
00234     * Read the ADC value in volts. The value will be that read from
00235     * whatever channel was set previously (`set_channel`).
00236     *
00237     * The data are coded in two's complements format, and the final
00238     * voltage is also a function of the resolution and gain settings.
00239     * This function follows the equations presented in Section 4.9 of
00240     * the device's datasheet (Microchip DS22088C).
00241     *
00242     * @return Analog measurement in volts (float)
00243     */
00244     float read_volts();
00245 
00246     //void start_conversion(void); For one-shot mode.
00247 
00248 private:
00249     // Variables and functions for I2C communication.
00250     I2C *_i2c;
00251     uint8_t _address;
00252     char _i2c_command[COMMAND_N_BYTES];
00253     uint8_t _configuration;
00254     static const uint8_t _device_code = 0b1101; // Hardcoded in factory
00255     void _write_configuration();
00256 
00257     // Variables needed for converting digital output codes to real
00258     // values (i.e. voltage).
00259     mcp342x_resolution_t _resolution;
00260     uint8_t _pga;
00261     float _lsb;
00262     uint32_t _max_code;
00263 };
00264 
00265 #endif