Library to communicate with LDC1614

Dependencies:   SHTx

Dependents:   Inductive_Sensor_3

Fork of LDC1101 by Bob Giesberts

Committer:
bobgiesberts
Date:
Tue Aug 23 08:25:40 2016 +0000
Revision:
28:76a2fc42f888
Parent:
LDC1101.cpp@27:05dd145c7997
Child:
29:41815fd13822
First version of the library for the LDC1614 which will soon replace the older LDC1101

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bobgiesberts 16:07d0e43c2d12 1 /**
bobgiesberts 28:76a2fc42f888 2 * @file LDC1614.cpp
bobgiesberts 16:07d0e43c2d12 3 * @brief this C++ file contains all required
bobgiesberts 16:07d0e43c2d12 4 * functions to interface with Texas
bobgiesberts 28:76a2fc42f888 5 * Instruments' LDC1614.
bobgiesberts 28:76a2fc42f888 6 *
bobgiesberts 28:76a2fc42f888 7 * @author Bob Giesberts
bobgiesberts 28:76a2fc42f888 8 *
bobgiesberts 28:76a2fc42f888 9 * @date 2016-08-09
bobgiesberts 16:07d0e43c2d12 10 *
bobgiesberts 28:76a2fc42f888 11 * @example
bobgiesberts 28:76a2fc42f888 12 * Serial pc(USBTX, USBRX);
bobgiesberts 28:76a2fc42f888 13 * LDC1614 ldc(PTC6, PTC7, PTC5, 16E6, 2, 120E-12);
bobgiesberts 28:76a2fc42f888 14 * int main(){
bobgiesberts 28:76a2fc42f888 15 * while(1) {
bobgiesberts 28:76a2fc42f888 16 * while( !ldc.is_ready() ) {}
bobgiesberts 28:76a2fc42f888 17 *
bobgiesberts 28:76a2fc42f888 18 * pc.printf("sensor 1: %d | sensor 2: %d\r\n", ldc.get_Data(0), ldc.get_Data(1) );
bobgiesberts 28:76a2fc42f888 19 * }
bobgiesberts 28:76a2fc42f888 20 * }
bobgiesberts 16:07d0e43c2d12 21 */
bobgiesberts 16:07d0e43c2d12 22
bobgiesberts 28:76a2fc42f888 23 #include "LDC1614.h"
bobgiesberts 16:07d0e43c2d12 24
bobgiesberts 28:76a2fc42f888 25
bobgiesberts 28:76a2fc42f888 26 LDC1614::LDC1614(PinName sda, PinName scl, PinName sd, float f_CLKIN, int channels, float capacitor) : _i2c(sda, scl), _shutdown_pin(sd)
bobgiesberts 16:07d0e43c2d12 27 {
bobgiesberts 18:fc9bb81a631f 28 // settings
bobgiesberts 28:76a2fc42f888 29 _channels = channels; // number of sensors
bobgiesberts 28:76a2fc42f888 30 _cap = capacitor;
bobgiesberts 28:76a2fc42f888 31 _fCLKIN = f_CLKIN;
bobgiesberts 28:76a2fc42f888 32
bobgiesberts 28:76a2fc42f888 33 _Offset = 0; // no offset needed
bobgiesberts 28:76a2fc42f888 34 _Rcount = 0xffff; // maximum for greatest precision
bobgiesberts 28:76a2fc42f888 35 _SettleCount = 50; // CHx_SETTLECOUNT = t_settle * f_REFx/16 = 50 (p.12)
bobgiesberts 28:76a2fc42f888 36 _DriveCurrent = 31; // max???
bobgiesberts 22:8da965ce5af3 37
bobgiesberts 28:76a2fc42f888 38 _i2c.frequency(400000); // 400 kHz (p.6)
bobgiesberts 16:07d0e43c2d12 39
bobgiesberts 28:76a2fc42f888 40 // Turn the LDC1614 on (exit shutdown)
bobgiesberts 28:76a2fc42f888 41 _shutdown_pin.write(0);
bobgiesberts 16:07d0e43c2d12 42 wait_us(100);
bobgiesberts 16:07d0e43c2d12 43
bobgiesberts 16:07d0e43c2d12 44 init();
bobgiesberts 16:07d0e43c2d12 45 }
bobgiesberts 16:07d0e43c2d12 46
bobgiesberts 28:76a2fc42f888 47 LDC1614::~LDC1614()
bobgiesberts 26:1ef9172cd355 48 {
bobgiesberts 28:76a2fc42f888 49
bobgiesberts 26:1ef9172cd355 50 }
bobgiesberts 26:1ef9172cd355 51
bobgiesberts 28:76a2fc42f888 52 void LDC1614::init()
bobgiesberts 16:07d0e43c2d12 53 {
bobgiesberts 20:8e1b1efdbb49 54 /********* SETTINGS *****************
bobgiesberts 25:ae111662ee03 55 ** C_sensor = 120 pF
bobgiesberts 25:ae111662ee03 56 ** L_sensor = 5 uH
bobgiesberts 25:ae111662ee03 57 ** Rp_min = 1500 Ohm
bobgiesberts 20:8e1b1efdbb49 58 **
bobgiesberts 25:ae111662ee03 59 ** RCount = 65535 (max)
bobgiesberts 28:76a2fc42f888 60 ** Settlecount = 50
bobgiesberts 20:8e1b1efdbb49 61 ** Samplerate = 15.3 Hz
bobgiesberts 20:8e1b1efdbb49 62 ** t_conv = 65.5 ms
bobgiesberts 20:8e1b1efdbb49 63 **
bobgiesberts 25:ae111662ee03 64 ** f_sensor_min = 6.4 MHz (d = inf)
bobgiesberts 25:ae111662ee03 65 ** f_sensor_max = 10 MHz (d = 0)
bobgiesberts 28:76a2fc42f888 66 **
bobgiesberts 28:76a2fc42f888 67 ** CHx_FIN_DIVIDER = 2 (6.4/2 = 3.2 < 16.0/4 = 4)
bobgiesberts 28:76a2fc42f888 68 ** CHx_FREF_DIVIDER = 1 (16.0 MHz)
bobgiesberts 20:8e1b1efdbb49 69 ************************************/
bobgiesberts 20:8e1b1efdbb49 70
bobgiesberts 28:76a2fc42f888 71 for(int i = 0; i < _channels; i++)
bobgiesberts 28:76a2fc42f888 72 {
bobgiesberts 28:76a2fc42f888 73 // set Reference Count to highest resolution
bobgiesberts 28:76a2fc42f888 74 setReferenceCount( i, _Rcount );
bobgiesberts 18:fc9bb81a631f 75
bobgiesberts 28:76a2fc42f888 76 // set the settling time
bobgiesberts 28:76a2fc42f888 77 // t_settle = (settlecount * 16) /f_REF
bobgiesberts 28:76a2fc42f888 78 setSettlecount( i, _SettleCount );
bobgiesberts 28:76a2fc42f888 79
bobgiesberts 28:76a2fc42f888 80 // set Divider to 1 (for large range / ENOB / resolution)
bobgiesberts 28:76a2fc42f888 81 setDivider( i, 1, 2 ); // IN = 2 | REF = 1
bobgiesberts 28:76a2fc42f888 82
bobgiesberts 28:76a2fc42f888 83 // set the drive current during sampling
bobgiesberts 28:76a2fc42f888 84 setDriveCurrent( i, _DriveCurrent ); // (p. 15 | Figure 14)
bobgiesberts 28:76a2fc42f888 85
bobgiesberts 28:76a2fc42f888 86 // shift the signal down a bit
bobgiesberts 28:76a2fc42f888 87 setOffset( i, _Offset );
bobgiesberts 28:76a2fc42f888 88 }
bobgiesberts 16:07d0e43c2d12 89
bobgiesberts 28:76a2fc42f888 90 // error_config (all is standard)
bobgiesberts 20:8e1b1efdbb49 91
bobgiesberts 28:76a2fc42f888 92 // mux_config
bobgiesberts 28:76a2fc42f888 93 set( MUX_CONFIG, AUTOSCAN_EN, _channels > 1 );
bobgiesberts 28:76a2fc42f888 94 set( MUX_CONFIG, RR_SEQUENCE, max(0, _channels - 2) );
bobgiesberts 28:76a2fc42f888 95 set( MUX_CONFIG, DEGLITCH, DEGLITCH_10M );
bobgiesberts 18:fc9bb81a631f 96
bobgiesberts 28:76a2fc42f888 97 // override Rp and use own Drive Current to reduce power consumption
bobgiesberts 28:76a2fc42f888 98 set( CONFIG, RP_OVERRIDE_EN, 1 );
bobgiesberts 28:76a2fc42f888 99 set( CONFIG, SENSOR_ACTIVATE_SEL, 1 );
bobgiesberts 28:76a2fc42f888 100 set( CONFIG, AUTO_AMP_DIS, 1 );
bobgiesberts 28:76a2fc42f888 101 set( CONFIG, REF_CLK_SRC, 1 ); // external f_CLKIN
bobgiesberts 28:76a2fc42f888 102 set( CONFIG, INTB_DIS, 1 );
bobgiesberts 28:76a2fc42f888 103 set( CONFIG, HIGH_CURRENT_DRV, 0 );
bobgiesberts 28:76a2fc42f888 104
bobgiesberts 28:76a2fc42f888 105 // Done configuring settings, set LDC1614 in measuring modus
bobgiesberts 28:76a2fc42f888 106 wakeup();
bobgiesberts 16:07d0e43c2d12 107 }
bobgiesberts 16:07d0e43c2d12 108
bobgiesberts 28:76a2fc42f888 109
bobgiesberts 28:76a2fc42f888 110 void LDC1614::func_mode(LDC_MODE mode)
bobgiesberts 28:76a2fc42f888 111 {
bobgiesberts 28:76a2fc42f888 112 switch (mode)
bobgiesberts 28:76a2fc42f888 113 {
bobgiesberts 28:76a2fc42f888 114 case LDC_MODE_ACTIVE:
bobgiesberts 28:76a2fc42f888 115 case LDC_MODE_SLEEP:
bobgiesberts 28:76a2fc42f888 116 _shutdown_pin.write( 0 );
bobgiesberts 28:76a2fc42f888 117 set( CONFIG, SLEEP_MODE_EN, LDC_MODE_ACTIVE );
bobgiesberts 28:76a2fc42f888 118 break;
bobgiesberts 28:76a2fc42f888 119
bobgiesberts 28:76a2fc42f888 120 case LDC_MODE_SHUTDOWN:
bobgiesberts 28:76a2fc42f888 121 _shutdown_pin.write( 1 );
bobgiesberts 28:76a2fc42f888 122 break;
bobgiesberts 28:76a2fc42f888 123 }
bobgiesberts 19:e205ab9142d8 124 }
bobgiesberts 28:76a2fc42f888 125 void LDC1614::sleep( void ) { func_mode( LDC_MODE_SLEEP ); }
bobgiesberts 28:76a2fc42f888 126 void LDC1614::wakeup( void ) { func_mode( LDC_MODE_ACTIVE ); }
bobgiesberts 19:e205ab9142d8 127
bobgiesberts 28:76a2fc42f888 128 void LDC1614::setReferenceCount( uint8_t channel, uint16_t rcount )
bobgiesberts 28:76a2fc42f888 129 {
bobgiesberts 28:76a2fc42f888 130 writeI2Cregister( RCOUNT_CH0 + channel, rcount );
bobgiesberts 25:ae111662ee03 131 }
bobgiesberts 25:ae111662ee03 132
bobgiesberts 28:76a2fc42f888 133 void LDC1614::setOffset( uint8_t channel, uint32_t offset )
bobgiesberts 19:e205ab9142d8 134 {
bobgiesberts 28:76a2fc42f888 135 _Offset = offset;
bobgiesberts 28:76a2fc42f888 136 writeI2Cregister( OFFSET_CH0 + channel, uint16_t (offset >> 16) );
bobgiesberts 19:e205ab9142d8 137 }
bobgiesberts 19:e205ab9142d8 138
bobgiesberts 28:76a2fc42f888 139 void LDC1614::setSettlecount( uint8_t channel, uint16_t settlecount )
bobgiesberts 17:a5cf2b4bec13 140 {
bobgiesberts 28:76a2fc42f888 141 // _t_settle = (settlecount * 16) / (_f_CLKIN / dividerREF[channel])
bobgiesberts 28:76a2fc42f888 142 writeI2Cregister( SETTLECOUNT_CH0 + channel, settlecount );
bobgiesberts 28:76a2fc42f888 143 }
bobgiesberts 28:76a2fc42f888 144
bobgiesberts 28:76a2fc42f888 145 void LDC1614::setDivider( uint8_t channel, uint8_t divIN, uint8_t divREF )
bobgiesberts 28:76a2fc42f888 146 {
bobgiesberts 28:76a2fc42f888 147 // make sure the values fit
bobgiesberts 28:76a2fc42f888 148 _dividerIN = min(max(divIN, 1), 15); // 4 bit
bobgiesberts 28:76a2fc42f888 149 _dividerREF = min(max(divREF, 1), 255); // 8 bit
bobgiesberts 28:76a2fc42f888 150 writeI2Cregister( CLOCK_DIVIDERS_CH0 + channel, uint16_t ((_dividerIN << 12) + _dividerREF) );
bobgiesberts 20:8e1b1efdbb49 151 }
bobgiesberts 20:8e1b1efdbb49 152
bobgiesberts 28:76a2fc42f888 153 void LDC1614::setDriveCurrent( uint8_t channel, uint8_t idrive )
bobgiesberts 28:76a2fc42f888 154 {
bobgiesberts 28:76a2fc42f888 155 _DriveCurrent = min( idrive, 31 ); // 5-bit (b1 1111)
bobgiesberts 28:76a2fc42f888 156 // todo: read initial idrive [10:6]
bobgiesberts 28:76a2fc42f888 157
bobgiesberts 28:76a2fc42f888 158 writeI2Cregister(DRIVE_CURRENT_CH0 + channel, uint16_t (_DriveCurrent<<10) );
bobgiesberts 25:ae111662ee03 159 }
bobgiesberts 25:ae111662ee03 160
bobgiesberts 28:76a2fc42f888 161 void LDC1614::set( ADDR addr, SETTING setting, uint8_t value )
bobgiesberts 20:8e1b1efdbb49 162 {
bobgiesberts 28:76a2fc42f888 163 uint8_t mask = 1;
bobgiesberts 28:76a2fc42f888 164 if ( addr == MUX_CONFIG )
bobgiesberts 28:76a2fc42f888 165 {
bobgiesberts 28:76a2fc42f888 166 switch (setting){
bobgiesberts 28:76a2fc42f888 167 case AUTOSCAN_EN: mask = 1; break; // 1
bobgiesberts 28:76a2fc42f888 168 case RR_SEQUENCE: mask = 3; break; // 11
bobgiesberts 28:76a2fc42f888 169 case DEGLITCH: mask = 7; break; // 111
bobgiesberts 28:76a2fc42f888 170 }
bobgiesberts 28:76a2fc42f888 171 }
bobgiesberts 28:76a2fc42f888 172 regchange( addr, setting, value, mask );
bobgiesberts 20:8e1b1efdbb49 173 }
bobgiesberts 20:8e1b1efdbb49 174
bobgiesberts 28:76a2fc42f888 175
bobgiesberts 28:76a2fc42f888 176
bobgiesberts 28:76a2fc42f888 177
bobgiesberts 28:76a2fc42f888 178
bobgiesberts 28:76a2fc42f888 179
bobgiesberts 28:76a2fc42f888 180 /* GETTING DATA FROM SENSOR */
bobgiesberts 28:76a2fc42f888 181
bobgiesberts 28:76a2fc42f888 182 uint16_t LDC1614::get_status( void )
bobgiesberts 20:8e1b1efdbb49 183 {
bobgiesberts 28:76a2fc42f888 184 uint16_t status[1];
bobgiesberts 28:76a2fc42f888 185 readI2C( status, STATUS );
bobgiesberts 28:76a2fc42f888 186 return status[0];
bobgiesberts 20:8e1b1efdbb49 187 }
bobgiesberts 28:76a2fc42f888 188 bool LDC1614::is_ready( void ) { return ( get_status() & 0x0080 ); }
bobgiesberts 17:a5cf2b4bec13 189
bobgiesberts 17:a5cf2b4bec13 190
bobgiesberts 28:76a2fc42f888 191 uint16_t LDC1614::get_Rcount( uint8_t channel )
bobgiesberts 16:07d0e43c2d12 192 {
bobgiesberts 28:76a2fc42f888 193 uint16_t rcount[1];
bobgiesberts 28:76a2fc42f888 194 readI2C( rcount, RCOUNT_CH0 + channel );
bobgiesberts 28:76a2fc42f888 195 return rcount[0];
bobgiesberts 20:8e1b1efdbb49 196 }
bobgiesberts 20:8e1b1efdbb49 197
bobgiesberts 28:76a2fc42f888 198 uint32_t LDC1614::get_Data( uint8_t channel )
bobgiesberts 22:8da965ce5af3 199 {
bobgiesberts 28:76a2fc42f888 200 uint16_t data[2];
bobgiesberts 28:76a2fc42f888 201 readI2C(data, DATA_MSB_CH0 + channel, 2);
bobgiesberts 28:76a2fc42f888 202 return ( (data[0] & 0x0fff)<<16) | data[1]; // MSB + LSB
bobgiesberts 22:8da965ce5af3 203 }
bobgiesberts 20:8e1b1efdbb49 204
bobgiesberts 28:76a2fc42f888 205
bobgiesberts 28:76a2fc42f888 206
bobgiesberts 28:76a2fc42f888 207
bobgiesberts 20:8e1b1efdbb49 208
bobgiesberts 28:76a2fc42f888 209 void LDC1614::readI2C( uint16_t *data, uint8_t address, uint8_t length )
bobgiesberts 22:8da965ce5af3 210 {
bobgiesberts 28:76a2fc42f888 211 // I2C reads per 8-bits, char is 8-bit, combine 8-bit in 16-bit sets
bobgiesberts 28:76a2fc42f888 212 char temp[length*2];
bobgiesberts 28:76a2fc42f888 213 _i2c.read( address, temp, length*2 );
bobgiesberts 28:76a2fc42f888 214
bobgiesberts 28:76a2fc42f888 215 for ( int i = 0; i < length; i++ )
bobgiesberts 28:76a2fc42f888 216 data[i] = (uint16_t) (temp[2*i+1]<<8) | temp[2*i];
bobgiesberts 22:8da965ce5af3 217 }
bobgiesberts 20:8e1b1efdbb49 218
bobgiesberts 28:76a2fc42f888 219 void LDC1614::writeI2C( uint16_t *data, uint8_t address, uint8_t length )
bobgiesberts 22:8da965ce5af3 220 {
bobgiesberts 28:76a2fc42f888 221 // I2C reads per 8-bits, char is 8-bit, split 16-bit data up in sets of 8-bit
bobgiesberts 28:76a2fc42f888 222 char temp[length*2];
bobgiesberts 28:76a2fc42f888 223 for ( int i = 0; i < length; i++ )
bobgiesberts 28:76a2fc42f888 224 {
bobgiesberts 28:76a2fc42f888 225 temp[2*i] = (data[i] & 0x00ff) >> 0; // 0, 2, 4 ...
bobgiesberts 28:76a2fc42f888 226 temp[2*i+1] = (data[i] & 0xff00) >> 8; // 1, 3, 5 ...
bobgiesberts 28:76a2fc42f888 227 }
bobgiesberts 28:76a2fc42f888 228 _i2c.write( address, temp, length*2 );
bobgiesberts 22:8da965ce5af3 229 }
bobgiesberts 20:8e1b1efdbb49 230
bobgiesberts 28:76a2fc42f888 231 void LDC1614::writeI2Cregister(uint8_t reg, uint16_t value)
bobgiesberts 28:76a2fc42f888 232 {
bobgiesberts 28:76a2fc42f888 233 writeI2C( &value, reg );
bobgiesberts 28:76a2fc42f888 234 }
bobgiesberts 28:76a2fc42f888 235
bobgiesberts 28:76a2fc42f888 236 void LDC1614::regchange( uint8_t addr, uint8_t setting, uint8_t value, uint8_t mask )
bobgiesberts 28:76a2fc42f888 237 {
bobgiesberts 28:76a2fc42f888 238 uint16_t config[1];
bobgiesberts 28:76a2fc42f888 239 readI2C( config, addr );
bobgiesberts 28:76a2fc42f888 240 writeI2Cregister( addr, uint16_t ( (config[0] & !(mask<<setting)) | (value<<setting)) ); // replace bits with number SETTING
bobgiesberts 28:76a2fc42f888 241 }
bobgiesberts 28:76a2fc42f888 242
bobgiesberts 28:76a2fc42f888 243
bobgiesberts 25:ae111662ee03 244
bobgiesberts 25:ae111662ee03 245 /* CALCULATE STUFF WITH SENSOR DATA */
bobgiesberts 25:ae111662ee03 246
bobgiesberts 28:76a2fc42f888 247 float LDC1614::get_fsensor( uint32_t LData )
bobgiesberts 28:76a2fc42f888 248 {
bobgiesberts 28:76a2fc42f888 249 _fsensor = _dividerIN * (_fCLKIN/_dividerREF) * ((LData / 268435456) + (_Offset / 65536)); // (p.14)
bobgiesberts 28:76a2fc42f888 250
bobgiesberts 18:fc9bb81a631f 251 return _fsensor;
bobgiesberts 19:e205ab9142d8 252 }
bobgiesberts 18:fc9bb81a631f 253
bobgiesberts 28:76a2fc42f888 254 float LDC1614::get_Inductance( uint32_t Ldata )
bobgiesberts 18:fc9bb81a631f 255 {
bobgiesberts 25:ae111662ee03 256 float fsensor = get_fsensor( Ldata );
bobgiesberts 28:76a2fc42f888 257 _inductance = 1.0 / (_cap * 4 * PI*PI * fsensor*fsensor ); // ???
bobgiesberts 19:e205ab9142d8 258 return _inductance;
bobgiesberts 19:e205ab9142d8 259 }
bobgiesberts 16:07d0e43c2d12 260
bobgiesberts 16:07d0e43c2d12 261
bobgiesberts 16:07d0e43c2d12 262
bobgiesberts 16:07d0e43c2d12 263 // EXTRA test: Get&print values of all variables to verify (to calculate the induction)
bobgiesberts 16:07d0e43c2d12 264 // The data will be printed on the screen using RealTerm: baud 9600.
bobgiesberts 16:07d0e43c2d12 265 // Begin ***********************************************************
bobgiesberts 28:76a2fc42f888 266 float LDC1614::get_fCLKIN() {return _fCLKIN;}
bobgiesberts 28:76a2fc42f888 267 uint8_t LDC1614::get_dividerIN() {return _dividerIN;}
bobgiesberts 28:76a2fc42f888 268 uint8_t LDC1614::get_dividerREF() {return _dividerREF;}
bobgiesberts 28:76a2fc42f888 269 uint32_t LDC1614::get_Offset() {return _Offset;}
bobgiesberts 28:76a2fc42f888 270 float LDC1614::get_cap() {return _cap;}
bobgiesberts 16:07d0e43c2d12 271 // END ***********************************************************