30/5/2018
Fork of max31865 by
MAX31865.cpp@0:ae18c7b91185, 2016-08-14 (annotated)
- Committer:
- lzbpli
- Date:
- Sun Aug 14 05:09:52 2016 +0000
- Revision:
- 0:ae18c7b91185
max31865 driver
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lzbpli | 0:ae18c7b91185 | 1 | /************************************************************************** |
lzbpli | 0:ae18c7b91185 | 2 | * Arduino driver library for the MAX31865. |
lzbpli | 0:ae18c7b91185 | 3 | * |
lzbpli | 0:ae18c7b91185 | 4 | * Copyright (C) 2015 Ole Wolf <wolf@blazingangles.com> |
lzbpli | 0:ae18c7b91185 | 5 | * |
lzbpli | 0:ae18c7b91185 | 6 | * |
lzbpli | 0:ae18c7b91185 | 7 | * Wire the circuit as follows, assuming that level converters have been |
lzbpli | 0:ae18c7b91185 | 8 | * added for the 3.3V signals: |
lzbpli | 0:ae18c7b91185 | 9 | * |
lzbpli | 0:ae18c7b91185 | 10 | * Arduino Uno --> MAX31865 |
lzbpli | 0:ae18c7b91185 | 11 | * ------------------------------------ |
lzbpli | 0:ae18c7b91185 | 12 | * CS: any available pin --> CS |
lzbpli | 0:ae18c7b91185 | 13 | * MOSI: pin 11 --> SDI (mandatory for hardware SPI) |
lzbpli | 0:ae18c7b91185 | 14 | * MISO: pin 12 --> SDO (mandatory for hardware SPI) |
lzbpli | 0:ae18c7b91185 | 15 | * SCK: pin 13 --> SCLK (mandatory for hardware SPI) |
lzbpli | 0:ae18c7b91185 | 16 | * |
lzbpli | 0:ae18c7b91185 | 17 | * |
lzbpli | 0:ae18c7b91185 | 18 | * This program is free software: you can redistribute it and/or modify |
lzbpli | 0:ae18c7b91185 | 19 | * it under the terms of the GNU General Public License as published by |
lzbpli | 0:ae18c7b91185 | 20 | * the Free Software Foundation, either version 3 of the License, or |
lzbpli | 0:ae18c7b91185 | 21 | * (at your option) any later version. |
lzbpli | 0:ae18c7b91185 | 22 | * |
lzbpli | 0:ae18c7b91185 | 23 | * This program is distributed in the hope that it will be useful, |
lzbpli | 0:ae18c7b91185 | 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
lzbpli | 0:ae18c7b91185 | 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
lzbpli | 0:ae18c7b91185 | 26 | * GNU General Public License for more details. |
lzbpli | 0:ae18c7b91185 | 27 | * |
lzbpli | 0:ae18c7b91185 | 28 | * You should have received a copy of the GNU General Public License |
lzbpli | 0:ae18c7b91185 | 29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
lzbpli | 0:ae18c7b91185 | 30 | **************************************************************************/ |
lzbpli | 0:ae18c7b91185 | 31 | |
lzbpli | 0:ae18c7b91185 | 32 | //#include <Arduino.h> |
lzbpli | 0:ae18c7b91185 | 33 | //#include <SPI.h> |
lzbpli | 0:ae18c7b91185 | 34 | #include <MAX31865.h> |
lzbpli | 0:ae18c7b91185 | 35 | #include "mbed.h" |
lzbpli | 0:ae18c7b91185 | 36 | |
lzbpli | 0:ae18c7b91185 | 37 | /** |
lzbpli | 0:ae18c7b91185 | 38 | * The constructor for the MAX31865_RTD class registers the CS pin and |
lzbpli | 0:ae18c7b91185 | 39 | * configures it as an output. |
lzbpli | 0:ae18c7b91185 | 40 | * |
lzbpli | 0:ae18c7b91185 | 41 | * @param [in] cs_pin Arduino pin selected for the CS signal. |
lzbpli | 0:ae18c7b91185 | 42 | */ |
lzbpli | 0:ae18c7b91185 | 43 | MAX31865_RTD::MAX31865_RTD( ptd_type type,PinName mosi, PinName miso, PinName sclk, PinName nss) |
lzbpli | 0:ae18c7b91185 | 44 | :spi( mosi, miso, sclk ), |
lzbpli | 0:ae18c7b91185 | 45 | nss( nss ) |
lzbpli | 0:ae18c7b91185 | 46 | |
lzbpli | 0:ae18c7b91185 | 47 | |
lzbpli | 0:ae18c7b91185 | 48 | { |
lzbpli | 0:ae18c7b91185 | 49 | /* Set the type of PTD. */ |
lzbpli | 0:ae18c7b91185 | 50 | this->type = type; |
lzbpli | 0:ae18c7b91185 | 51 | |
lzbpli | 0:ae18c7b91185 | 52 | spi.format(8,3); |
lzbpli | 0:ae18c7b91185 | 53 | spi.frequency(1000000); |
lzbpli | 0:ae18c7b91185 | 54 | |
lzbpli | 0:ae18c7b91185 | 55 | //nss = 1; |
lzbpli | 0:ae18c7b91185 | 56 | /* CS pin for the SPI device. */ |
lzbpli | 0:ae18c7b91185 | 57 | //this->cs_pin = cs_pin; |
lzbpli | 0:ae18c7b91185 | 58 | //pinMode( this->cs_pin, OUTPUT ); |
lzbpli | 0:ae18c7b91185 | 59 | |
lzbpli | 0:ae18c7b91185 | 60 | /* Pull the CS pin high to avoid conflicts on SPI bus. */ |
lzbpli | 0:ae18c7b91185 | 61 | //nss = 1; |
lzbpli | 0:ae18c7b91185 | 62 | //nss = type; |
lzbpli | 0:ae18c7b91185 | 63 | } |
lzbpli | 0:ae18c7b91185 | 64 | |
lzbpli | 0:ae18c7b91185 | 65 | |
lzbpli | 0:ae18c7b91185 | 66 | |
lzbpli | 0:ae18c7b91185 | 67 | /** |
lzbpli | 0:ae18c7b91185 | 68 | * Configure the MAX31865. The parameters correspond to Table 2 in the MAX31865 |
lzbpli | 0:ae18c7b91185 | 69 | * datasheet. The parameters are combined into a control bit-field that is stored |
lzbpli | 0:ae18c7b91185 | 70 | * internally in the class for later reconfiguration, as are the fault threshold values. |
lzbpli | 0:ae18c7b91185 | 71 | * |
lzbpli | 0:ae18c7b91185 | 72 | * @param [in] v_bias Vbias enabled (@a true) or disabled (@a false). |
lzbpli | 0:ae18c7b91185 | 73 | * @param [in] conversion_mode Conversion mode auto (@a true) or off (@a false). |
lzbpli | 0:ae18c7b91185 | 74 | * @param [in] one_shot 1-shot measurement enabled (@a true) or disabled (@a false). |
lzbpli | 0:ae18c7b91185 | 75 | * @param [in] three_wire 3-wire enabled (@a true) or 2-wire/4-wire (@a false). |
lzbpli | 0:ae18c7b91185 | 76 | * @param [in] fault_detection Fault detection cycle control (see Table 3 in the MAX31865 |
lzbpli | 0:ae18c7b91185 | 77 | * datasheet). |
lzbpli | 0:ae18c7b91185 | 78 | * @param [in] fault_clear Fault status auto-clear (@a true) or manual clear (@a false). |
lzbpli | 0:ae18c7b91185 | 79 | * @param [in] filter_50hz 50 Hz filter enabled (@a true) or 60 Hz filter enabled |
lzbpli | 0:ae18c7b91185 | 80 | * (@a false). |
lzbpli | 0:ae18c7b91185 | 81 | * @param [in] low_threshold Low fault threshold. |
lzbpli | 0:ae18c7b91185 | 82 | * @param [in] high_threshold High fault threshold. |
lzbpli | 0:ae18c7b91185 | 83 | */ |
lzbpli | 0:ae18c7b91185 | 84 | void MAX31865_RTD::configure( bool v_bias, bool conversion_mode, bool one_shot, |
lzbpli | 0:ae18c7b91185 | 85 | bool three_wire, uint8_t fault_cycle, bool fault_clear, |
lzbpli | 0:ae18c7b91185 | 86 | bool filter_50hz, uint16_t low_threshold, |
lzbpli | 0:ae18c7b91185 | 87 | uint16_t high_threshold ) |
lzbpli | 0:ae18c7b91185 | 88 | { |
lzbpli | 0:ae18c7b91185 | 89 | uint8_t control_bits = 0; |
lzbpli | 0:ae18c7b91185 | 90 | nss = 1; |
lzbpli | 0:ae18c7b91185 | 91 | /* Assemble the control bit mask. */ |
lzbpli | 0:ae18c7b91185 | 92 | control_bits |= ( v_bias ? 0x80 : 0 ); |
lzbpli | 0:ae18c7b91185 | 93 | control_bits |= ( conversion_mode ? 0x40 : 0 ); |
lzbpli | 0:ae18c7b91185 | 94 | control_bits |= ( one_shot ? 0x20 : 0 ); |
lzbpli | 0:ae18c7b91185 | 95 | control_bits |= ( three_wire ? 0x10 : 0 ); |
lzbpli | 0:ae18c7b91185 | 96 | control_bits |= fault_cycle & 0b00001100; |
lzbpli | 0:ae18c7b91185 | 97 | control_bits |= ( fault_clear ? 0x02 : 0 ); |
lzbpli | 0:ae18c7b91185 | 98 | control_bits |= ( filter_50hz ? 0x01 : 0 ); |
lzbpli | 0:ae18c7b91185 | 99 | |
lzbpli | 0:ae18c7b91185 | 100 | /* Store the control bits and the fault threshold limits for reconfiguration |
lzbpli | 0:ae18c7b91185 | 101 | purposes. */ |
lzbpli | 0:ae18c7b91185 | 102 | this->configuration_control_bits = control_bits; |
lzbpli | 0:ae18c7b91185 | 103 | this->configuration_low_threshold = low_threshold; |
lzbpli | 0:ae18c7b91185 | 104 | this->configuration_high_threshold = high_threshold; |
lzbpli | 0:ae18c7b91185 | 105 | |
lzbpli | 0:ae18c7b91185 | 106 | /* Perform an initial "reconfiguration." */ |
lzbpli | 0:ae18c7b91185 | 107 | reconfigure( ); |
lzbpli | 0:ae18c7b91185 | 108 | } |
lzbpli | 0:ae18c7b91185 | 109 | |
lzbpli | 0:ae18c7b91185 | 110 | |
lzbpli | 0:ae18c7b91185 | 111 | |
lzbpli | 0:ae18c7b91185 | 112 | /** |
lzbpli | 0:ae18c7b91185 | 113 | * Reconfigure the MAX31865 by writing the stored control bits and the stored fault |
lzbpli | 0:ae18c7b91185 | 114 | * threshold values back to the chip. |
lzbpli | 0:ae18c7b91185 | 115 | */ |
lzbpli | 0:ae18c7b91185 | 116 | void MAX31865_RTD::reconfigure( ) |
lzbpli | 0:ae18c7b91185 | 117 | { |
lzbpli | 0:ae18c7b91185 | 118 | /* Write the configuration to the MAX31865. */ |
lzbpli | 0:ae18c7b91185 | 119 | nss = 0; |
lzbpli | 0:ae18c7b91185 | 120 | // wait_us(100); |
lzbpli | 0:ae18c7b91185 | 121 | spi.write( 0x80 ); |
lzbpli | 0:ae18c7b91185 | 122 | spi.write( this->configuration_control_bits ); |
lzbpli | 0:ae18c7b91185 | 123 | nss = 1; |
lzbpli | 0:ae18c7b91185 | 124 | |
lzbpli | 0:ae18c7b91185 | 125 | /* Write the threshold values. */ |
lzbpli | 0:ae18c7b91185 | 126 | nss = 0; |
lzbpli | 0:ae18c7b91185 | 127 | // wait_us(100); |
lzbpli | 0:ae18c7b91185 | 128 | spi.write( 0x83 ); |
lzbpli | 0:ae18c7b91185 | 129 | spi.write( ( this->configuration_high_threshold >> 8 ) & 0x00ff ); |
lzbpli | 0:ae18c7b91185 | 130 | spi.write( this->configuration_high_threshold & 0x00ff ); |
lzbpli | 0:ae18c7b91185 | 131 | spi.write( ( this->configuration_low_threshold >> 8 ) & 0x00ff ); |
lzbpli | 0:ae18c7b91185 | 132 | spi.write( this->configuration_low_threshold & 0x00ff ); |
lzbpli | 0:ae18c7b91185 | 133 | nss = 1; |
lzbpli | 0:ae18c7b91185 | 134 | |
lzbpli | 0:ae18c7b91185 | 135 | } |
lzbpli | 0:ae18c7b91185 | 136 | |
lzbpli | 0:ae18c7b91185 | 137 | |
lzbpli | 0:ae18c7b91185 | 138 | |
lzbpli | 0:ae18c7b91185 | 139 | /** |
lzbpli | 0:ae18c7b91185 | 140 | * Apply the Callendar-Van Dusen equation to convert the RTD resistance |
lzbpli | 0:ae18c7b91185 | 141 | * to temperature: |
lzbpli | 0:ae18c7b91185 | 142 | * |
lzbpli | 0:ae18c7b91185 | 143 | * \f[ |
lzbpli | 0:ae18c7b91185 | 144 | * t=\frac{-A\pm \sqrt{A^2-4B\left(1-\frac{R_t}{R_0}\right)}}{2B} |
lzbpli | 0:ae18c7b91185 | 145 | * \f], |
lzbpli | 0:ae18c7b91185 | 146 | * |
lzbpli | 0:ae18c7b91185 | 147 | * where |
lzbpli | 0:ae18c7b91185 | 148 | * |
lzbpli | 0:ae18c7b91185 | 149 | * \f$A\f$ and \f$B\f$ are the RTD coefficients, \f$R_t\f$ is the current |
lzbpli | 0:ae18c7b91185 | 150 | * resistance of the RTD, and \f$R_0\f$ is the resistance of the RTD at 0 |
lzbpli | 0:ae18c7b91185 | 151 | * degrees Celcius. |
lzbpli | 0:ae18c7b91185 | 152 | * |
lzbpli | 0:ae18c7b91185 | 153 | * For more information on measuring with an RTD, see: |
lzbpli | 0:ae18c7b91185 | 154 | * <http://newton.ex.ac.uk/teaching/CDHW/Sensors/an046.pdf>. |
lzbpli | 0:ae18c7b91185 | 155 | * |
lzbpli | 0:ae18c7b91185 | 156 | * @param [in] resistance The measured RTD resistance. |
lzbpli | 0:ae18c7b91185 | 157 | * @return Temperature in degrees Celcius. |
lzbpli | 0:ae18c7b91185 | 158 | */ |
lzbpli | 0:ae18c7b91185 | 159 | double MAX31865_RTD::temperature( ) const |
lzbpli | 0:ae18c7b91185 | 160 | { |
lzbpli | 0:ae18c7b91185 | 161 | static const double a2 = 2.0 * RTD_B; |
lzbpli | 0:ae18c7b91185 | 162 | static const double b_sq = RTD_A * RTD_A; |
lzbpli | 0:ae18c7b91185 | 163 | |
lzbpli | 0:ae18c7b91185 | 164 | const double rtd_resistance = |
lzbpli | 0:ae18c7b91185 | 165 | ( this->type == RTD_PT100 ) ? RTD_RESISTANCE_PT100 : RTD_RESISTANCE_PT1000; |
lzbpli | 0:ae18c7b91185 | 166 | |
lzbpli | 0:ae18c7b91185 | 167 | double c = 1.0 - resistance( ) / rtd_resistance; |
lzbpli | 0:ae18c7b91185 | 168 | double D = b_sq - 2.0 * a2 * c; |
lzbpli | 0:ae18c7b91185 | 169 | double temperature_deg_C = ( -RTD_A + sqrt( D ) ) / a2; |
lzbpli | 0:ae18c7b91185 | 170 | |
lzbpli | 0:ae18c7b91185 | 171 | return( temperature_deg_C ); |
lzbpli | 0:ae18c7b91185 | 172 | } |
lzbpli | 0:ae18c7b91185 | 173 | |
lzbpli | 0:ae18c7b91185 | 174 | |
lzbpli | 0:ae18c7b91185 | 175 | |
lzbpli | 0:ae18c7b91185 | 176 | /** |
lzbpli | 0:ae18c7b91185 | 177 | * Read all settings and measurements from the MAX31865 and store them |
lzbpli | 0:ae18c7b91185 | 178 | * internally in the class. |
lzbpli | 0:ae18c7b91185 | 179 | * |
lzbpli | 0:ae18c7b91185 | 180 | * @return Fault status byte |
lzbpli | 0:ae18c7b91185 | 181 | */ |
lzbpli | 0:ae18c7b91185 | 182 | uint8_t MAX31865_RTD::read_all( ) |
lzbpli | 0:ae18c7b91185 | 183 | { |
lzbpli | 0:ae18c7b91185 | 184 | uint16_t combined_bytes; |
lzbpli | 0:ae18c7b91185 | 185 | |
lzbpli | 0:ae18c7b91185 | 186 | /* Start the read operation. */ |
lzbpli | 0:ae18c7b91185 | 187 | nss = 0; |
lzbpli | 0:ae18c7b91185 | 188 | /* Tell the MAX31865 that we want to read, starting at register 0. */ |
lzbpli | 0:ae18c7b91185 | 189 | spi.write( 0x00 ); |
lzbpli | 0:ae18c7b91185 | 190 | |
lzbpli | 0:ae18c7b91185 | 191 | /* Read the MAX31865 registers in the following order: |
lzbpli | 0:ae18c7b91185 | 192 | Configuration |
lzbpli | 0:ae18c7b91185 | 193 | RTD |
lzbpli | 0:ae18c7b91185 | 194 | High Fault Threshold |
lzbpli | 0:ae18c7b91185 | 195 | Low Fault Threshold |
lzbpli | 0:ae18c7b91185 | 196 | Fault Status */ |
lzbpli | 0:ae18c7b91185 | 197 | |
lzbpli | 0:ae18c7b91185 | 198 | this->measured_configuration = spi.write( 0x00 ); |
lzbpli | 0:ae18c7b91185 | 199 | |
lzbpli | 0:ae18c7b91185 | 200 | combined_bytes = spi.write( 0x00 ) << 8; |
lzbpli | 0:ae18c7b91185 | 201 | combined_bytes |= spi.write( 0x00 ); |
lzbpli | 0:ae18c7b91185 | 202 | this->measured_resistance = combined_bytes >> 1; |
lzbpli | 0:ae18c7b91185 | 203 | |
lzbpli | 0:ae18c7b91185 | 204 | combined_bytes = spi.write( 0x00 ) << 8; |
lzbpli | 0:ae18c7b91185 | 205 | combined_bytes |= spi.write( 0x00 ); |
lzbpli | 0:ae18c7b91185 | 206 | this->measured_high_threshold = combined_bytes >> 1; |
lzbpli | 0:ae18c7b91185 | 207 | |
lzbpli | 0:ae18c7b91185 | 208 | combined_bytes = spi.write( 0x00 ) << 8; |
lzbpli | 0:ae18c7b91185 | 209 | combined_bytes |= spi.write( 0x00 ); |
lzbpli | 0:ae18c7b91185 | 210 | this->measured_low_threshold = combined_bytes >> 1; |
lzbpli | 0:ae18c7b91185 | 211 | |
lzbpli | 0:ae18c7b91185 | 212 | this->measured_status = spi.write( 0x00 ); |
lzbpli | 0:ae18c7b91185 | 213 | |
lzbpli | 0:ae18c7b91185 | 214 | nss = 1; |
lzbpli | 0:ae18c7b91185 | 215 | |
lzbpli | 0:ae18c7b91185 | 216 | /* Reset the configuration if the measured resistance is |
lzbpli | 0:ae18c7b91185 | 217 | zero or a fault occurred. */ |
lzbpli | 0:ae18c7b91185 | 218 | if( ( this->measured_resistance == 0 ) |
lzbpli | 0:ae18c7b91185 | 219 | || ( this->measured_status != 0 ) ) |
lzbpli | 0:ae18c7b91185 | 220 | { |
lzbpli | 0:ae18c7b91185 | 221 | reconfigure( ); |
lzbpli | 0:ae18c7b91185 | 222 | } |
lzbpli | 0:ae18c7b91185 | 223 | |
lzbpli | 0:ae18c7b91185 | 224 | return( status( ) ); |
lzbpli | 0:ae18c7b91185 | 225 | } |
lzbpli | 0:ae18c7b91185 | 226 | |
lzbpli | 0:ae18c7b91185 | 227 |