Library to communicate with LDC1614

Dependencies:   SHTx

Dependents:   Inductive_Sensor_3

Fork of LDC1101 by Bob Giesberts

Revision:
34:b03d7bb9010c
Parent:
33:2f4c791f37b2
Child:
35:00c9c01f0c0f
--- a/LDC1614.cpp	Sun Sep 11 15:08:43 2016 +0000
+++ b/LDC1614.cpp	Wed Sep 21 14:25:20 2016 +0000
@@ -22,25 +22,26 @@
 */
 
 #include "LDC1614.h"
-#include "mbed_debug.h"
 
-#include "i2c.hpp"
-
-
-LDC1614::LDC1614(PinName sda, PinName scl, PinName sd, float f_CLKIN, int channels, float capacitor) : _i2c(sda, scl), _shutdown_pin(sd)
+LDC1614::LDC1614(PinName sda, PinName scl, PinName sd, uint8_t f_CLKIN, int channels, uint8_t capacitor) : _i2c(sda, scl), _shutdown_pin(sd)
 {
     // settings
-    _channels = channels;   // number of sensors
+    _channels = channels;     // number of sensors
     _cap      = capacitor;
-    _fCLKIN  = f_CLKIN;
+    _fCLKIN   = f_CLKIN;
 
-    _Offset = 0;            // highest 16-bit of 32-bit number (so e.g. 100E6 / 65536 = 1525) 
-    _Rcount = 0xffff;       // maximum for greatest precision
-    _SettleCount = 500;     // CHx_SETTLECOUNT = t_settle * f_REFx/16 = 50 (p.12)
-    _DriveCurrent = 20;     // max = 31, automatically settles at 20
+    _Offset         = 0;      // highest 16-bit of 32-bit number (so e.g. 100E6 / 65536 = 1525) 
+    _Rcount         = 0xffff; // maximum for greatest precision (0xffff)
+    _SettleCount    = 50;     // CHx_SETTLECOUNT = t_settle * f_REFx/16 = 50 (p.12)
+    _DriveCurrent   = 21;     // max = 31, automatically settles at 20
+    _dividerREF     = 2;      // 2 (f_REF = f_CLKIN/2  =  40/2 = 20  < 35) (p.10)
+    _dividerIN      = 2;      // 2 (f_IN  = f_SENSOR/2 = 6.5/2 = 3.4 < 5 = 20/4 = f_REF/4
+    
+    for(int i = 0; i < channels; i++)
+        error[i] = 0;
        
     // start communication
-    _i2c.setFrequency( 400000 ); // 400 kHz (p.6)
+    _i2c.setFrequency( 400000 ); // max 400 kHz (p.6)
     
     // Initilialize the LDC1614
     init();
@@ -58,16 +59,9 @@
     ** L_sensor     =     5 uH
     ** Rp_min       =  1500 Ohm
     **
-    ** RCount       = 65535     (max)
-    ** Settlecount  =    50
-    ** Samplerate   =    15.3 Hz
-    ** t_conv       =    65.5 ms
-    **
     ** f_sensor_min =     6.4 MHz (d = inf)
     ** f_sensor_max =    10   MHz (d = 0)
     ** 
-    ** CHx_FIN_DIVIDER  =     2       (6.4/2 = 3.2 < 16.0/4 = 4)
-    ** CHx_FREF_DIVIDER =     1       (16.0 MHz)    
     ************************************/
     
     // Configuring setup, set LDC in configuration modus
@@ -80,10 +74,11 @@
 
         // set the settling time
         // t_settle = (settlecount * 16) /f_REF
+        // settlecount > Q * f_REF / (16 * f_SENSOR)
         setSettlecount( i, _SettleCount );
         
         // set Divider to 1 (for large range / ENOB / resolution)
-        setDivider( i, 1, 2 ); // IN = 2 | REF = 1
+        setDivider( i, _dividerIN, _dividerREF ); 
         
         // set the drive current during sampling 
         setDriveCurrent( i, _DriveCurrent );   // (p. 15 | Figure 14)
@@ -92,12 +87,12 @@
         setOffset( i, _Offset );
     }
 
-    // error_config
+    // error_config (does not work?)
     set( ERROR_CONFIG, UR_ERR2OUT,    1 );
     set( ERROR_CONFIG, OR_ERR2OUT,    1 );
     set( ERROR_CONFIG, WD_ERR2OUT,    1 );
-    // set( ERROR_CONFIG, AH_ERR2OUT,    1 );
-    // set( ERROR_CONFIG, AL_ERR2OUT,    1 );    
+    set( ERROR_CONFIG, AH_ERR2OUT,    1 );
+    set( ERROR_CONFIG, AL_ERR2OUT,    1 );    
     
     // mux_config    
     set( MUX_CONFIG, AUTOSCAN_EN,     _channels > 1 );
@@ -118,7 +113,7 @@
 }
 
 
-void LDC1614::func_mode(LDC_MODE mode)
+void LDC1614::func_mode( LDC_MODE mode )
 { 
     switch (mode)
     {
@@ -145,6 +140,7 @@
 void LDC1614::setReferenceCount( uint8_t channel, uint16_t rcount )
 {
     writeI2Cregister( RCOUNT_CH0 + channel, rcount );
+    // debug("[ReferenceCount channel %d: 0x%02x]\r\n", channel, get_ReferenceCount( channel ) );
 }
 
 void LDC1614::setOffset( uint8_t channel, uint16_t offset )
@@ -155,7 +151,6 @@
 
 void LDC1614::setSettlecount( uint8_t channel, uint16_t settlecount )
 {
-    // _t_settle = (settlecount * 16) / (_f_CLKIN / dividerREF[channel])
     writeI2Cregister( SETTLECOUNT_CH0 + channel, settlecount );    
 }
 
@@ -163,17 +158,15 @@
 {
     // make sure the values fit
     _dividerIN  = (( divIN <  15) ? (( divIN > 1) ? divIN  : 1) :  15 ); // 4 bit
-    _dividerIN  = ((divREF < 255) ? ((divREF > 1) ? divREF : 1) : 255 ); // 8 bit
-    writeI2Cregister( CLOCK_DIVIDERS_CH0 + channel, uint16_t ((_dividerIN << 12) + _dividerREF) );
+    _dividerREF = ((divREF < 255) ? ((divREF > 1) ? divREF : 1) : 255 ); // 8 bit
+    writeI2Cregister( CLOCK_DIVIDERS_CH0 + channel, uint16_t ((_dividerIN << CHx_FIN_DIVIDER) | (_dividerREF << CHx_FREF_DIVIDER)) );
 } 
 
 void LDC1614::setDriveCurrent( uint8_t channel, uint8_t idrive )
 {   
     _DriveCurrent = ((idrive < 31) ? idrive : 31 ); // 5-bit (b1 1111)
-    
-    // todo: read initial idrive [10:6]
-
-    writeI2Cregister(DRIVE_CURRENT_CH0 + channel, uint16_t (_DriveCurrent<<10) );
+    regchange( DRIVE_CURRENT_CH0 + channel, CHx_IDRIVE, _DriveCurrent, 31 );    
+    // debug("[DriveCurrent channel %d: 0x%02x]\r\n", channel, get_DriveCurrent( channel ) );
 }
 
 void LDC1614::set( ADDR addr, SETTING setting, uint8_t value )
@@ -190,6 +183,12 @@
     regchange( addr, setting, value, mask );
 }
 
+
+
+
+
+/* GETTING DATA FROM SENSOR */
+
 uint8_t LDC1614::get( ADDR addr, SETTING setting, uint8_t mask )
 {
     if ( addr == MUX_CONFIG )
@@ -220,14 +219,11 @@
     return data[0];
 }
 
-
-/* GETTING DATA FROM SENSOR */
-
 uint16_t LDC1614::get_status( void )
 {
-    uint16_t status[1]; 
-    readI2C( status, STATUS );  
-    return status[0];
+    uint16_t data[1]; 
+    readI2C( data, STATUS );  
+    return data[0];
 }
 bool LDC1614::is_ready( uint8_t channel )
 {
@@ -241,11 +237,15 @@
 }
 bool LDC1614::is_error( uint8_t status )
 {
+    // DOES NOT WORK PROPERLY YET!!
+    // STATUS is reset after reading DATA_MSB_CHx
     if( status == 17 ) { status = get_status(); }
     return ((( status>>ERR_ZC ) & 7) != 0);
 }
 uint8_t LDC1614::what_error( uint8_t channel )
 {
+    // DOES NOT WORK PROPERLY YET!!
+    // STATUS is reset after reading DATA_MSB_CHx
     uint8_t status = get_status();
     if ( ( ( status>>ERR_CHAN ) & 2 ) == channel )
     {
@@ -253,31 +253,47 @@
         if ((( status>>ERR_ALE ) & 1) != 0) return 2; // Amplitide Low Error
         if ((( status>>ERR_ZC  ) & 1) != 0) return 3; // Zero Count Error
     }
-    return 0;                                     // no error?
+    return 0;
+}
+uint8_t LDC1614::get_error( uint8_t channel )
+{
+    if( ( (error[channel]>>(CHx_ERR_UR - CHx_ERR_AE)) & 1) == 1 ) { debug( "Sensor %d: Under-range Error\r\n", channel ); }
+    if( ( (error[channel]>>(CHx_ERR_OR - CHx_ERR_AE)) & 1) == 1 ) { debug( "Sensor %d: Over-range Error\r\n", channel ); }
+    if( ( (error[channel]>>(CHx_ERR_WD - CHx_ERR_AE)) & 1) == 1 ) { debug( "Sensor %d: Watchdog Timeout Error\r\n", channel ); }
+    if( ( (error[channel]>>(CHx_ERR_AE - CHx_ERR_AE)) & 1) == 1 ) { debug( "Sensor %d: Amplitude Error\r\n", channel ); }
+    return error[channel];
 }
 
-uint16_t LDC1614::get_Rcount( uint8_t channel )
+
+uint16_t LDC1614::get_ReferenceCount( uint8_t channel )
 {
     uint16_t rcount[1]; 
     readI2C( rcount, RCOUNT_CH0 + channel ); 
     return rcount[0];
 }
 
+uint8_t LDC1614::get_DriveCurrent( uint8_t channel )
+{
+    ADDR addr;
+    switch ( channel ){        
+        case 1:  addr = DRIVE_CURRENT_CH1; break;    
+        case 2:  addr = DRIVE_CURRENT_CH2; break;    
+        case 3:  addr = DRIVE_CURRENT_CH3; break;    
+        default: addr = DRIVE_CURRENT_CH0; break;    
+    }    
+    return get( addr, CHx_IDRIVE, 31 );
+}
+
 uint32_t LDC1614::get_Data( uint8_t channel )
 {
     uint16_t data[2];
-    readI2C( data, DATA_MSB_CH0 + channel, 2 );
-    
-    if( ((data[0]>>CHx_ERR_UR) & 1) == 1 ) { debug( "Sensor %d: Under-range Error\r\n", channel ); }
-    if( ((data[0]>>CHx_ERR_OR) & 1) == 1 ) { debug( "Sensor %d: Over-range Error\r\n", channel ); }
-    if( ((data[0]>>CHx_ERR_WD) & 1) == 1 ) { debug( "Sensor %d: Watchdog Timeout Error\r\n", channel ); }
-    if( ((data[0]>>CHx_ERR_AE) & 1) == 1 ) { debug( "Sensor %d: Amplitude Error\r\n", channel ); }
-    
+    readI2C( data, DATA_MSB_CH0 + 2*channel, 2 );    
+    error[channel] = ((data[0]>>CHx_ERR_AE) & 0x0f);
+    // debug("[Error channel %d (0x%02X): 0x%01X] 0x%04X %04X\r\n", channel, DATA_MSB_CH0 + 2*channel, error[channel], data[0], data[1] );
     return ( (data[0] & 0x0fff)<<16 ) | data[1]; // MSB + LSB
-    // return data[1];
 }
 
-uint16_t LDC1614::get_ID( void )
+uint16_t LDC1614::get_device_ID( void )
 {
     uint16_t ID[1]; 
     readI2C( ID, DEVICE_ID, 1 );
@@ -287,43 +303,9 @@
 
 uint16_t LDC1614::get_manufacturer_ID( void )
 {
-    // uint16_t ID[1]; 
-    // readI2C( ID, MANUFACTURER_ID, 1 );
-    // return ID[0];
-
-    _i2c.start();
-    
-    // Write address + 0 (write)
-    if( _i2c.write( 0x2A << 1 ) == true ){ // NACK = true
-        _i2c.stop();
-        return 1;
-    }
-    
-    // Write register address
-    if ( _i2c.write( 0x7E ) == true ) { // NACK = true
-        _i2c.stop();
-        return 2;
-    }
-
-    _i2c.start();
-
-    // Write address + 1 (read)
-    if ( _i2c.write( (0x2A << 1) | 0x01 ) == true ) { // NACK = true
-        _i2c.stop();
-        return 3;
-    }
-        
-    uint16_t data;
-    data = _i2c.read(1) << 8;   // ACK
-    data |= _i2c.read(0);       // NACK
-    _i2c.stop();
-    return data;
-    
-    //return _i2c.read(1) << 8;    // MSB
-    //return data[i] |= _i2c.read(0);        // LSB
-    //_i2c.stop();
-
-
+    uint16_t ID[1]; 
+    readI2C( ID, MANUFACTURER_ID, 1 );
+    return ID[0];
 }
 
 
@@ -333,22 +315,27 @@
 {
     for( int i = 0; i < length; i++ )
     {
+        // start sequence (Device ID + Register Address + write)
         _i2c.start();
-        _i2c.write( ( 0x2A << 1 ) | 0 ); // 7 bit 0x2A + 0 (write) = 0x55
+        _i2c.write( ( 0x2A << 1 ) | 0 );
         _i2c.write( address + i );
+        
+        // start sequence (Register Address + read)
+        _i2c.start();
+        _i2c.write( ( 0x2A << 1 ) | 1 );        
 
-        _i2c.start();
-        _i2c.write( ( 0x2A << 1 ) | 1 ); // 7 bit 0x2A + 1 (read) = 0x55
-
+        // Build up 16 bit result
         data[i] = _i2c.read(1) << 8;    // MSB
         data[i] |= _i2c.read(0);        // LSB
+        // debug("Read from 0x%02X : 0x%04X\r\n", address + i, data[i]);
+                
+        // Stop command
         _i2c.stop();
     }        
 }
 
 void LDC1614::writeI2C( uint16_t *data, uint8_t address, uint8_t length )
 {
-   
     for ( int i = 0; i < length; i++ )
     {
         _i2c.start();
@@ -359,8 +346,6 @@
         _i2c.write( ( data[i] & 0x00ff ) >> 0 ); // LSB
         _i2c.stop();
     }
-    
-    
 }
 
 void LDC1614::writeI2Cregister(uint8_t reg, uint16_t value)
@@ -381,14 +366,14 @@
 
 float LDC1614::get_fsensor( uint32_t LData )
 {    
-    _fsensor = _dividerIN * (_fCLKIN/_dividerREF) * ((LData / 268435456) + _Offset); // (p.14)
+    _fsensor = _dividerIN * ((_fCLKIN*1E6)/_dividerREF) * (LData / 268435456.0); // (p.14)
     return _fsensor;
 }   
 
 float LDC1614::get_Inductance( uint32_t Ldata )
 {  
     float fsensor = get_fsensor( Ldata );
-    _inductance = 1.0 / (_cap * 4 * PI*PI * fsensor*fsensor ); // ???
+    _inductance = 1.0 / ((_cap*1E-12) * 4 * PI*PI * fsensor*fsensor ); // ???
     return _inductance;
 }