Library to communicate with LDC1614
Dependents: Inductive_Sensor_3
Fork of LDC1101 by
Diff: LDC1614.cpp
- 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; }