Library to communicate with LDC1614
Dependents: Inductive_Sensor_3
Fork of LDC1101 by
LDC1101.cpp@18:fc9bb81a631f, 2015-12-16 (annotated)
- 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?
User | Revision | Line number | New 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 *********************************************************** |