Library to communicate with LDC1614

Dependencies:   SHTx

Dependents:   Inductive_Sensor_3

Fork of LDC1101 by Bob Giesberts

Committer:
bobgiesberts
Date:
Wed Dec 16 10:58:31 2015 +0000
Revision:
18:fc9bb81a631f
Parent:
17:a5cf2b4bec13
Child:
19:e205ab9142d8
First working code with realistic outcome values. Removed a lot of double coding and corrected an error in reading LHR_data. Some tweaking is still possible (necessary) to increase resolution, stability and accuracy.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bobgiesberts 16:07d0e43c2d12 1 /**
bobgiesberts 16:07d0e43c2d12 2 * @file LDC1101.cpp
bobgiesberts 16:07d0e43c2d12 3 * @brief this C++ file contains all required
bobgiesberts 16:07d0e43c2d12 4 * functions to interface with Texas
bobgiesberts 16:07d0e43c2d12 5 * Instruments' LDC1101.
bobgiesberts 16:07d0e43c2d12 6 *
bobgiesberts 16:07d0e43c2d12 7 * @author Victor Sluiter
bobgiesberts 16:07d0e43c2d12 8 *
bobgiesberts 16:07d0e43c2d12 9 * @date 2015-12-09
bobgiesberts 16:07d0e43c2d12 10 */
bobgiesberts 16:07d0e43c2d12 11
bobgiesberts 16:07d0e43c2d12 12 #include "LDC1101.h"
bobgiesberts 16:07d0e43c2d12 13
bobgiesberts 16:07d0e43c2d12 14
bobgiesberts 18:fc9bb81a631f 15 LDC1101::LDC1101(PinName mosi, PinName miso, PinName sck, PinName cs, float capacitor, float f_CLKIN, PinName clock_out) : _spiport(mosi,miso,sck, NC), _cs_pin(cs)//, _clock(clock_out,1)
bobgiesberts 16:07d0e43c2d12 16 {
bobgiesberts 18:fc9bb81a631f 17 // settings
bobgiesberts 16:07d0e43c2d12 18 cap = capacitor;
bobgiesberts 16:07d0e43c2d12 19 _spiport.format(8,3);
bobgiesberts 16:07d0e43c2d12 20 _spiport.frequency(1E6);
bobgiesberts 18:fc9bb81a631f 21 setFrequency(f_CLKIN);
bobgiesberts 16:07d0e43c2d12 22
bobgiesberts 16:07d0e43c2d12 23 _cs_pin.write(1);
bobgiesberts 16:07d0e43c2d12 24 wait_us(100);
bobgiesberts 16:07d0e43c2d12 25
bobgiesberts 16:07d0e43c2d12 26 init();
bobgiesberts 16:07d0e43c2d12 27 }
bobgiesberts 16:07d0e43c2d12 28
bobgiesberts 16:07d0e43c2d12 29 void LDC1101::init()
bobgiesberts 16:07d0e43c2d12 30 {
bobgiesberts 18:fc9bb81a631f 31 // Set LDC1101 in configuration modus
bobgiesberts 18:fc9bb81a631f 32 mode(LDC_MODE_STANDBY); // STANDBY = 0x01 naar 0x0B
bobgiesberts 16:07d0e43c2d12 33
bobgiesberts 16:07d0e43c2d12 34 wait(0.1);
bobgiesberts 16:07d0e43c2d12 35 wait_us(10);
bobgiesberts 16:07d0e43c2d12 36
bobgiesberts 18:fc9bb81a631f 37
bobgiesberts 18:fc9bb81a631f 38 /** --- [LHR modus] --- */
bobgiesberts 18:fc9bb81a631f 39 // L-Only Measurement
bobgiesberts 18:fc9bb81a631f 40 writeSPIregister(0x05, 0x01); // ALT_CONFIG: 0000 0011 --> Shutdown enabled + LHR modus
bobgiesberts 18:fc9bb81a631f 41 writeSPIregister(0x0C, 0x01); // D_CONFIG: Register 0x0C enables a function that can improve L measurements while disabling RP measurements
bobgiesberts 18:fc9bb81a631f 42
bobgiesberts 18:fc9bb81a631f 43
bobgiesberts 16:07d0e43c2d12 44
bobgiesberts 18:fc9bb81a631f 45 /** --- [Responsetime] --- */
bobgiesberts 18:fc9bb81a631f 46 // The number of sensor periods used per conversion.
bobgiesberts 18:fc9bb81a631f 47 // This setting MUST be applied, default does not work.
bobgiesberts 18:fc9bb81a631f 48 // Responsetime
bobgiesberts 18:fc9bb81a631f 49 // t_conv (s) = ------------
bobgiesberts 18:fc9bb81a631f 50 // 3 x f_sensor
bobgiesberts 18:fc9bb81a631f 51 // Does NOT apply to the LHR mode!!! (p. 17)
bobgiesberts 18:fc9bb81a631f 52 setResponseTime(LDC_RESPONSE_6144); // 6144 = 0x07 naar 0x04
bobgiesberts 18:fc9bb81a631f 53 //
bobgiesberts 18:fc9bb81a631f 54 // For LHR mode, the conversion time is set by the reference count LHR_RCOUNT (0x30 & 0x31) (p.34)
bobgiesberts 18:fc9bb81a631f 55 // The conversion time represents the number of clock cycles used to measure the sensor frequency.
bobgiesberts 18:fc9bb81a631f 56 // The reference count value must be chosen to support the required number of effective bits (ENOB).
bobgiesberts 18:fc9bb81a631f 57 // e.g. ENOB 13 bits --> minimum converstion time 2^13 = 8192 clock cycles required. 8192 = 0x2000 = RCOUNT.
bobgiesberts 18:fc9bb81a631f 58 // Higher values for LHR_COUNT have a higher effective measurement resolution but a lower sample rate
bobgiesberts 18:fc9bb81a631f 59 // The maximum setting (0xffff) is required for full resolution (p. 35)
bobgiesberts 18:fc9bb81a631f 60 // (55 + RCOUNT*16)
bobgiesberts 18:fc9bb81a631f 61 // t_conv (s) = ----------------
bobgiesberts 18:fc9bb81a631f 62 // f_CLKIN
bobgiesberts 18:fc9bb81a631f 63 // writeSPIregister(0x30, 0xff); // LHR_RCOUNT_LSB
bobgiesberts 18:fc9bb81a631f 64 // writeSPIregister(0x31, 0xff); // LHR_RCOUNT_MSB
bobgiesberts 18:fc9bb81a631f 65 // Disable current drive? (RP_SET.RPMAX_DIS - 0x01[7] = 1)(p.15)
bobgiesberts 18:fc9bb81a631f 66
bobgiesberts 18:fc9bb81a631f 67
bobgiesberts 16:07d0e43c2d12 68
bobgiesberts 18:fc9bb81a631f 69
bobgiesberts 18:fc9bb81a631f 70 /** --- [RpMIN] --- */
bobgiesberts 18:fc9bb81a631f 71 // In LHR mode, this sets a fixed current into the sensor
bobgiesberts 18:fc9bb81a631f 72 // RP_SET.RPMIN (2:0) (p.35)
bobgiesberts 18:fc9bb81a631f 73 // pi * V_amp
bobgiesberts 18:fc9bb81a631f 74 // R_p = -----------
bobgiesberts 18:fc9bb81a631f 75 // 4 * I_drive
bobgiesberts 18:fc9bb81a631f 76 // This setting can be calibrated with the target closest to the sensor: R_p(d = 0mm)
bobgiesberts 18:fc9bb81a631f 77 // RPMIN < 0.8 x R_p(d = 0mm)
bobgiesberts 18:fc9bb81a631f 78 // If R_p < 750 Ohm --> increase distance to target
bobgiesberts 18:fc9bb81a631f 79 // 000: RPMIN = 96 kOhm | I_drive = 4.7 uA
bobgiesberts 18:fc9bb81a631f 80 // 001: RPMIN = 48 kOhm | I_drive = 9.4 uA
bobgiesberts 18:fc9bb81a631f 81 // 010: RPMIN = 24 kOhm | I_drive = 18.7 uA
bobgiesberts 18:fc9bb81a631f 82 // 011: RPMIN = 12 kOhm | I_drive = 37.5 uA
bobgiesberts 18:fc9bb81a631f 83 // 100: RPMIN = 6 kOhm | I_drive = 75 uA
bobgiesberts 18:fc9bb81a631f 84 // 101: RPMIN = 3 kOhm | I_drive = 150 uA
bobgiesberts 18:fc9bb81a631f 85 // 110: RPMIN = 1.5 kOhm | I_drive = 300 uA
bobgiesberts 18:fc9bb81a631f 86 // 111: RPMIN = 0.75 kOhm | I_drive = 600 uA (default)
bobgiesberts 18:fc9bb81a631f 87 // writeSPIregister(0x01, 0x0?); // RP_SET
bobgiesberts 16:07d0e43c2d12 88
bobgiesberts 18:fc9bb81a631f 89
bobgiesberts 18:fc9bb81a631f 90
bobgiesberts 18:fc9bb81a631f 91 /** --- [Divider] --- */
bobgiesberts 18:fc9bb81a631f 92 // Sensor input divider (p.35)
bobgiesberts 18:fc9bb81a631f 93 // Because f_CLKIN > 4*f_sensor is not realisable for higher frequencies, so there is a divider
bobgiesberts 18:fc9bb81a631f 94 // f_CLKIN > 4 * f_sensor / SENSOR_DIV
bobgiesberts 18:fc9bb81a631f 95 setDivider(DIVIDER_2);
bobgiesberts 18:fc9bb81a631f 96
bobgiesberts 18:fc9bb81a631f 97
bobgiesberts 18:fc9bb81a631f 98
bobgiesberts 18:fc9bb81a631f 99
bobgiesberts 18:fc9bb81a631f 100
bobgiesberts 18:fc9bb81a631f 101 // Done configuring settings, set LDC1101 in measuring modus
bobgiesberts 18:fc9bb81a631f 102 mode(LDC_MODE_ACTIVE); // ACTIVE = 0x00 naar 0x0B
bobgiesberts 16:07d0e43c2d12 103 }
bobgiesberts 16:07d0e43c2d12 104
bobgiesberts 16:07d0e43c2d12 105 void LDC1101::setResponseTime(LDC_RESPONSE responsetime)
bobgiesberts 16:07d0e43c2d12 106 {
bobgiesberts 18:fc9bb81a631f 107 uint16_t resps[] = {0, 0, 192, 384, 768, 1536, 3072, 6144};
bobgiesberts 18:fc9bb81a631f 108 _responsetime = resps[responsetime];
bobgiesberts 16:07d0e43c2d12 109 writeSPIregister(0x04, responsetime);
bobgiesberts 16:07d0e43c2d12 110 }
bobgiesberts 16:07d0e43c2d12 111
bobgiesberts 17:a5cf2b4bec13 112 void LDC1101::setDivider(DIVIDER div)
bobgiesberts 17:a5cf2b4bec13 113 {
bobgiesberts 18:fc9bb81a631f 114 uint16_t divs[] = {1, 2, 4, 8};
bobgiesberts 18:fc9bb81a631f 115 _divider = divs[div];
bobgiesberts 17:a5cf2b4bec13 116 writeSPIregister(0x34, div);
bobgiesberts 17:a5cf2b4bec13 117 }
bobgiesberts 17:a5cf2b4bec13 118
bobgiesberts 17:a5cf2b4bec13 119
bobgiesberts 16:07d0e43c2d12 120 void LDC1101::setFrequency(float frequency)
bobgiesberts 16:07d0e43c2d12 121 {
bobgiesberts 18:fc9bb81a631f 122 _fCLKIN = frequency;
bobgiesberts 17:a5cf2b4bec13 123 //_clock.period(1.0/frequency);
bobgiesberts 17:a5cf2b4bec13 124 //_clock.pulsewidth(0.5/frequency);
bobgiesberts 16:07d0e43c2d12 125 }
bobgiesberts 16:07d0e43c2d12 126
bobgiesberts 18:fc9bb81a631f 127 float LDC1101::get_fsensor()
bobgiesberts 16:07d0e43c2d12 128 {
bobgiesberts 18:fc9bb81a631f 129 _L_data = get_LHR_Data();
bobgiesberts 18:fc9bb81a631f 130 _fsensor = _fCLKIN * _divider * _L_data/16777216; // (p.26)
bobgiesberts 18:fc9bb81a631f 131 return _fsensor;
bobgiesberts 18:fc9bb81a631f 132 };
bobgiesberts 18:fc9bb81a631f 133
bobgiesberts 18:fc9bb81a631f 134
bobgiesberts 18:fc9bb81a631f 135 float LDC1101::get_Inductance()
bobgiesberts 18:fc9bb81a631f 136 {
bobgiesberts 18:fc9bb81a631f 137 _fsensor = get_fsensor();
bobgiesberts 16:07d0e43c2d12 138
bobgiesberts 18:fc9bb81a631f 139 // 1
bobgiesberts 18:fc9bb81a631f 140 // L = --------------------- --> p. 34
bobgiesberts 18:fc9bb81a631f 141 // C * (2*PI*f_sensor)^2
bobgiesberts 18:fc9bb81a631f 142 return 1./(cap * 4*PI*PI*_fsensor*_fsensor);
bobgiesberts 16:07d0e43c2d12 143 };
bobgiesberts 16:07d0e43c2d12 144
bobgiesberts 16:07d0e43c2d12 145
bobgiesberts 18:fc9bb81a631f 146 uint32_t LDC1101::get_LHR_Data(void)
bobgiesberts 16:07d0e43c2d12 147 {
bobgiesberts 18:fc9bb81a631f 148 // LHR_DATA (p.26 & p.27)
bobgiesberts 18:fc9bb81a631f 149 uint8_t LHR_DATA[3];
bobgiesberts 18:fc9bb81a631f 150 readSPI(LHR_DATA, 0x38, 3); // 0x38 + 0x39 + 0x3A
bobgiesberts 18:fc9bb81a631f 151 uint32_t combinedbytes = (LHR_DATA[2]<<16) | (LHR_DATA[1]<<8) | LHR_DATA[0];
bobgiesberts 16:07d0e43c2d12 152 return combinedbytes;
bobgiesberts 16:07d0e43c2d12 153 }
bobgiesberts 16:07d0e43c2d12 154
bobgiesberts 16:07d0e43c2d12 155 void LDC1101::readSPI(uint8_t *data, uint8_t address, uint8_t num_bytes)
bobgiesberts 16:07d0e43c2d12 156 {
bobgiesberts 16:07d0e43c2d12 157 // CSB down
bobgiesberts 16:07d0e43c2d12 158 _cs_pin.write(0);
bobgiesberts 16:07d0e43c2d12 159
bobgiesberts 16:07d0e43c2d12 160 // makes sure the address starts with 1... Why?
bobgiesberts 16:07d0e43c2d12 161 _spiport.write(address | 0x80); //read flag
bobgiesberts 16:07d0e43c2d12 162 for(int i=0; i < num_bytes ; i++)
bobgiesberts 16:07d0e43c2d12 163 {
bobgiesberts 16:07d0e43c2d12 164 data[i] = _spiport.write(0xFF);
bobgiesberts 16:07d0e43c2d12 165 }
bobgiesberts 16:07d0e43c2d12 166 // CSB up
bobgiesberts 16:07d0e43c2d12 167 _cs_pin.write(1);
bobgiesberts 16:07d0e43c2d12 168 }
bobgiesberts 16:07d0e43c2d12 169
bobgiesberts 16:07d0e43c2d12 170 void LDC1101::writeSPI(uint8_t *data, uint8_t address, uint8_t num_bytes)
bobgiesberts 16:07d0e43c2d12 171 {
bobgiesberts 16:07d0e43c2d12 172 // CSB down
bobgiesberts 16:07d0e43c2d12 173 _cs_pin.write(0);
bobgiesberts 16:07d0e43c2d12 174
bobgiesberts 16:07d0e43c2d12 175 _spiport.write(address);
bobgiesberts 16:07d0e43c2d12 176 for(int i=0; i < num_bytes ; i++)
bobgiesberts 16:07d0e43c2d12 177 {
bobgiesberts 16:07d0e43c2d12 178 _spiport.write(data[i]);
bobgiesberts 16:07d0e43c2d12 179 }
bobgiesberts 16:07d0e43c2d12 180 // CSB up
bobgiesberts 16:07d0e43c2d12 181 _cs_pin.write(1);
bobgiesberts 16:07d0e43c2d12 182 }
bobgiesberts 16:07d0e43c2d12 183
bobgiesberts 16:07d0e43c2d12 184
bobgiesberts 16:07d0e43c2d12 185 // EXTRA test: Get&print values of all variables to verify (to calculate the induction)
bobgiesberts 16:07d0e43c2d12 186 // The data will be printed on the screen using RealTerm: baud 9600.
bobgiesberts 16:07d0e43c2d12 187 // Begin ***********************************************************
bobgiesberts 18:fc9bb81a631f 188 // float LDC1101::get_L_data() {_L_data = get_LHR_Data();
bobgiesberts 18:fc9bb81a631f 189 // return _L_data;};
bobgiesberts 18:fc9bb81a631f 190 float LDC1101::get_fCLKIN() {return _fCLKIN;};
bobgiesberts 16:07d0e43c2d12 191 float LDC1101::get_responsetime() {return _responsetime;};
bobgiesberts 16:07d0e43c2d12 192 float LDC1101::get_cap() {return cap;};
bobgiesberts 16:07d0e43c2d12 193 // END ***********************************************************