Library to communicate with LDC1101

Dependents:   Inductive_Sensor Inductive_Sensor_Jasper Inductive_Sensor_3

Fork of LDC1000 by First Last

LDC1101.cpp

Committer:
bobgiesberts
Date:
2015-12-16
Revision:
18:fc9bb81a631f
Parent:
17:a5cf2b4bec13
Child:
19:e205ab9142d8

File content as of revision 18:fc9bb81a631f:

/**
* @file LDC1101.cpp
* @brief this C++ file contains all required
* functions to interface with Texas
* Instruments' LDC1101.
*
* @author Victor Sluiter
*
* @date 2015-12-09
*/

#include "LDC1101.h"

 
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)
{
    // settings
    cap = capacitor;
    _spiport.format(8,3);
    _spiport.frequency(1E6);
    setFrequency(f_CLKIN);
    
    _cs_pin.write(1);
    wait_us(100);
    
    init();
}

void LDC1101::init()
{
    // Set LDC1101 in configuration modus
    mode(LDC_MODE_STANDBY);     // STANDBY = 0x01 naar 0x0B  
    
    wait(0.1);
    wait_us(10);


    /** --- [LHR modus] --- */
    // L-Only Measurement
    writeSPIregister(0x05, 0x01);   // ALT_CONFIG:  0000 0011 --> Shutdown enabled + LHR modus
    writeSPIregister(0x0C, 0x01);   // D_CONFIG:    Register 0x0C enables a function that can improve L measurements while disabling RP measurements 



    /** --- [Responsetime] --- */
    // The number of sensor periods used per conversion.
    // This setting MUST be applied, default does not work.
    //              Responsetime
    // t_conv (s) = ------------
    //              3 x f_sensor
    // Does NOT apply to the LHR mode!!! (p. 17)
    setResponseTime(LDC_RESPONSE_6144); // 6144 = 0x07 naar 0x04
    //
    // For LHR mode, the conversion time is set by the reference count LHR_RCOUNT (0x30 & 0x31) (p.34)
    // The conversion time represents the number of clock cycles used to measure the sensor frequency.
    // The reference count value must be chosen to support the required number of effective bits (ENOB).
    // e.g. ENOB 13 bits --> minimum converstion time 2^13 = 8192 clock cycles required. 8192 = 0x2000 = RCOUNT.
    // Higher values for LHR_COUNT have a higher effective measurement resolution but a lower sample rate
    // The maximum setting (0xffff) is required for full resolution (p. 35)
    //              (55 + RCOUNT*16)
    // t_conv (s) = ----------------
    //                  f_CLKIN
    // writeSPIregister(0x30, 0xff);    // LHR_RCOUNT_LSB
    // writeSPIregister(0x31, 0xff);    // LHR_RCOUNT_MSB
    // Disable current drive? (RP_SET.RPMAX_DIS - 0x01[7] = 1)(p.15)



    
    /** --- [RpMIN] --- */
    // In LHR mode, this sets a fixed current into the sensor
    // RP_SET.RPMIN (2:0)         (p.35)
    //       pi * V_amp 
    // R_p = -----------
    //       4 * I_drive
    // This setting can be calibrated with the target closest to the sensor: R_p(d = 0mm)
    // RPMIN < 0.8 x R_p(d = 0mm)
    // If R_p < 750 Ohm --> increase distance to target
    // 000: RPMIN = 96    kOhm | I_drive =   4.7 uA
    // 001: RPMIN = 48    kOhm | I_drive =   9.4 uA
    // 010: RPMIN = 24    kOhm | I_drive =  18.7 uA
    // 011: RPMIN = 12    kOhm | I_drive =  37.5 uA
    // 100: RPMIN =  6    kOhm | I_drive =  75   uA
    // 101: RPMIN =  3    kOhm | I_drive = 150   uA
    // 110: RPMIN =  1.5  kOhm | I_drive = 300   uA
    // 111: RPMIN =  0.75 kOhm | I_drive = 600   uA    (default)
    // writeSPIregister(0x01, 0x0?);    // RP_SET


    
    /** --- [Divider] --- */
    // Sensor input divider         (p.35)
    // Because f_CLKIN > 4*f_sensor is not realisable for higher frequencies, so there is a divider
    // f_CLKIN > 4 * f_sensor / SENSOR_DIV
    setDivider(DIVIDER_2);  



 

    // Done configuring settings, set LDC1101 in measuring modus
    mode(LDC_MODE_ACTIVE);      // ACTIVE = 0x00 naar 0x0B
}

void LDC1101::setResponseTime(LDC_RESPONSE responsetime)
{
    uint16_t resps[] = {0, 0, 192, 384, 768, 1536, 3072, 6144};
    _responsetime = resps[responsetime];
    writeSPIregister(0x04, responsetime);
}

void LDC1101::setDivider(DIVIDER div)
{
    uint16_t divs[] = {1, 2, 4, 8};
    _divider = divs[div];
    writeSPIregister(0x34, div);
}   


void LDC1101::setFrequency(float frequency)
{
    _fCLKIN = frequency;
    //_clock.period(1.0/frequency);
    //_clock.pulsewidth(0.5/frequency);
}

float LDC1101::get_fsensor()
{
    _L_data = get_LHR_Data();
    _fsensor = _fCLKIN * _divider * _L_data/16777216;       // (p.26)
    return _fsensor;
};   


float LDC1101::get_Inductance()
{  
    _fsensor = get_fsensor();
    
    //               1
    // L = ---------------------        --> p. 34
    //     C * (2*PI*f_sensor)^2
    return 1./(cap * 4*PI*PI*_fsensor*_fsensor);
};


uint32_t LDC1101::get_LHR_Data(void)
{
    // LHR_DATA (p.26 & p.27)
    uint8_t LHR_DATA[3];
    readSPI(LHR_DATA, 0x38, 3);     // 0x38 + 0x39 + 0x3A
    uint32_t combinedbytes = (LHR_DATA[2]<<16) | (LHR_DATA[1]<<8) | LHR_DATA[0];
    return combinedbytes;
}

void LDC1101::readSPI(uint8_t *data, uint8_t address, uint8_t num_bytes)
{
    // CSB down
    _cs_pin.write(0);
    
    // makes sure the address starts with 1... Why?
    _spiport.write(address | 0x80); //read flag 
    for(int i=0; i < num_bytes ; i++)
    {
        data[i] = _spiport.write(0xFF);
    }
    // CSB up
    _cs_pin.write(1);
}

void LDC1101::writeSPI(uint8_t *data, uint8_t address, uint8_t num_bytes)
{
    // CSB down
    _cs_pin.write(0);
    
    _spiport.write(address); 
    for(int i=0; i < num_bytes ; i++)
    {
        _spiport.write(data[i]);
    }
    // CSB up
    _cs_pin.write(1);
}


// EXTRA test: Get&print values of all variables to verify (to calculate the induction)
// The data will be printed on the screen using RealTerm: baud 9600.
// Begin ***********************************************************
    // float LDC1101::get_L_data()         {_L_data = get_LHR_Data(); 
    //                                    return _L_data;};        
    float LDC1101::get_fCLKIN()      {return _fCLKIN;};    
    float LDC1101::get_responsetime()   {return _responsetime;};    
    float LDC1101::get_cap()            {return cap;};
// END ***********************************************************