using AD5933 to measure impedances

Dependencies:   4DGL-uLCD-SE mbed

AD5933.cpp

Committer:
mvaca3
Date:
2016-12-13
Revision:
71:91f99e81cd1c
Parent:
69:cfee0a25ef44

File content as of revision 71:91f99e81cd1c:

#include <mbed.h>
#include "AD5933.h"
//#include <math.h>

AD5933::AD5933(I2C*i2c, Serial *pc, Serial *bt)
{
    //pass to private variables
    _i2c = i2c;
    _pc = pc;
    _bt = bt;
}

void AD5933::calibrate(double ref)
{
    //store reference resistance
    _ref = ref;
    
    //perform frequency sweep
    sweep();
    //for each step, calculate gain factor and phase
    for(int i=0; i <= 9; i+=1) {
        _gain[i] = (float)(1.0/ref)/sqrt((pow((double)_real[i],2)+pow((double)_imag[i],2)))*pow(10.0,11);
        _phase[i] = (float)atan((double)(_imag[i]/_real[i]));
    }
        for(int i = 0; i <=9; i++) {
        //_pc->printf("_gain[%i]: %f, _phase[%i]: %f\n\r", i, _gain[i], i, _phase[i]);
    }
    
    //take temperature
    _temp[0] = getTemp();

}

void AD5933::configure()
{
    _pga = 0x1;
    _range = 0x0;
    char buff[3];
    char b[10];
    
    _bt->putc('.');
    
        //set lower control byte to all 0 for internal clock
    buff[0] = 0x00;
    //_pc->printf("buff is %x\n\r", buff[0]);
    _i2c->write(CTRL_LOW, buff, 1);
    
    _i2c->read(CTRL_LOW, buff, 1);
    //_pc->printf("buff is %x\n\r", buff[0]);
    //_pc->printf("_freq: %i\n\r", _freq);
    //_pc->printf("%f\n\r", (_freq/(16776000/4.0)) * pow(2.0,27));
    float fModified = (_freq / (16776000/4.0)) * pow(2.0,27);
    sprintf(b, "%.0f", fModified);
    int fFinal = atoi(b);
    
    float iModified = (_inc / (16776000/4.0)) * pow(2.0,27);
    sprintf(b, "%.0f", iModified);
    int iFinal = atoi(b);
    //_pc->printf("fFinal: %i\n\riModified: %i\n\r", fFinal, iFinal);

    _bt->putc('.');
    //_pc->printf("Entering start frequency into registers.\n\r");
    buff[2] = fFinal & 0x0000FF;
    buff[1] = (fFinal & 0x00FF00) >> 8;
    buff[0] = (fFinal & 0xFF0000) >> 16;
    //_pc->printf("buff is %x%x%x\n\r", buff[0], buff[1], buff[2]);
    //set frequency sweep parameters
    _i2c->write(FREQ_HIGH, buff, 3);  //start frequency  
    
    _i2c->read(FREQ_HIGH, buff, 3);  //start frequency  

    //_pc->printf("buff is %x%x%x\n\r", buff[0], buff[1], buff[2]);
    
    //_pc->printf("Entering frequency increment into registers.\n\r");
    buff[2] = iFinal & 0xFF;
    buff[1] = (iFinal & 0xFF00) >> 8;
    buff[0] = (iFinal & 0xFF0000) >> 16;
    //_pc->printf("buff is %x%x%x\n\r", buff[0], buff[1], buff[2]);
    _i2c->write(FINC_HIGH, buff, 3);  //frequency increments 
    
    _i2c->read(FINC_HIGH, buff, 3);  //frequency increments 
    //_pc->printf("buff is %x%x%x\n\r", buff[0], buff[1], buff[2]);
    _bt->putc('.');
    //_pc->printf("Entering number of increments into registers.\n\r");

    buff[1] = _n & 0xFF;
    buff[0] = (_n & 0xFF00) >> 8;    
    //_pc->printf("buff is %x%x\n\r", buff[0], buff[1]);
    _i2c->write(NINC_HIGH, buff, 2);   //number of increments
    
    _i2c->read(NINC_HIGH, buff, 2);   //number of increments  
    //_pc->printf("buff is %x%x\n\r", buff[0], buff[1]);

    //_pc->printf("Entering settling cycles into registers.\n\r");

    buff[1] = 0xF4;
    buff[0] = 0x03;
    //_pc->printf("buff is %x%x\n\r", buff[0], buff[1]);
    _i2c->write(SET_CYCLE, buff, 2);   //number of settling cycles is 1000
    
    _i2c->read(SET_CYCLE, buff, 2);   //number of settling cycles is 1000
    //_pc->printf("buff is %x%x\n\r", buff[0], buff[1]);
    
   // _pc->printf("Standing by.\n\r");

    _bt->putc('.');
    //set to standby via reset command
    buff[0] = (0xB << 4) | (_range << 1) | _pga;
    //_pc->printf("buff is %x\n\r", buff[0]);

    _i2c->write(CTRL_HIGH, buff, 1);
    
    _i2c->read(CTRL_HIGH, buff, 1);
   //_pc->printf("buff is %x\n\r", buff[0]);
       
    _bt->putc('.');
    _pc->printf("Initialize with start frequency command.\n\r");

    //start frequency command
    buff[0] = (0x1 << 4) | (_range << 1) | _pga;
    //_pc->printf("buff is %x\n\r", buff[0]);
    _i2c->write(CTRL_HIGH, buff, 1);
    
    _i2c->read(CTRL_HIGH, buff, 1);
    //_pc->printf("buff is %x\n\r", buff[0]);
    
    //_pc->printf("Beginning frequency sweep.\n\r");

    for(int i = 0; i < 999; i++) {
        if (fmod((double)i,200.0) ==0) _bt->putc('.');    
    }

    //after sufficient time, sweep command
    buff[0] = (0x2 << 4) | (_range << 1) | _pga;
    //_pc->printf("buff is %x\n\r", buff[0]);
    _i2c->write(CTRL_HIGH, buff, 1);
    
    _i2c->read(CTRL_HIGH, buff, 1);
    //_pc->printf("buff is %x\n\r", buff[0]);
    
    //repeat initial frequency to remove error
    buff[0] = (0x4 << 4) | (_range << 1) | _pga;
    //_pc->printf("buff is %x\n\r", buff[0]);
    _i2c->write(CTRL_HIGH, buff, 1);
    
    _i2c->read(CTRL_HIGH, buff, 1);
    //_pc->printf("buff is %x\n\r", buff[0]);

}

void AD5933::sweep()
{
    _bt->putc('.');
    _pc->printf("Entering sweep\n\r");
    _freq = 100000;
    _inc = 100000;
    _n = 9;
    int i = 0;
    char buff;
    configure();
    read(i);
    
    _i2c->read(STATUS, &buff, 1);
    while(i < 9)
    {
        _bt->putc('.');
        i++;
        buff = (0x3 << 4) | (_range << 1) | _pga;
        _i2c->write(CTRL_HIGH, &buff, 1);
        read(i);
        _i2c->read(STATUS, &buff, 1);
    }
}

void AD5933::sweep1()
{
    _n = 0;
    int i = -2;
    _bt->putc('.');
    configure();
    _bt->putc('.');
    read(i);
    _bt->putc('.');
    i++;
    char buff = (0x3 << 4) | (_range << 1) | _pga;
    _i2c->write(CTRL_HIGH, &buff, 1);
    read(i);
}

void AD5933::read(int i)
{
    _bt->putc('.');
    char buff;
    
       //repeat initial frequency to remove error
    buff = (0x4 << 4) | (_range << 1) | _pga;
    //_pc->printf("buff is %x\n\r", &buff);
    _i2c->write(CTRL_HIGH, &buff, 1);
    
    _i2c->read(CTRL_HIGH, &buff, 1);
    //_pc->printf("buff is %x\n\r", &buff);
    //update impedance
    _i2c->read(STATUS, &buff, 1);
    //while(!(buff & 0x2)&&!(i==0))
    {
        _i2c->read(STATUS, &buff, 1);
    }
    char temp[2];
    _bt->putc('.');
    if(i > -1){
        _i2c->read((int) REAL_HIGH, temp, 2);
        _real[i] = (int)temp[0] << 8 + (int)temp[1];
        _i2c->read((int) IMAG_HIGH, temp, 2);
        _imag[i] = (int)temp[0] << 8 + (int)temp[1];
    }
    else if(i > -2) {
        _i2c->read((int) REAL_HIGH, &temp[0], 2);
        _r = (int)temp[0] << 8 + temp[1];
        _i2c->read((int) IMAG_HIGH, &temp[0], 2);
        _i = (int)temp[0] << 8 + temp[1];
    }
}

float AD5933::getTemp()
{
    double result = 0;
    char buff[2];
    //measure temperature for correction
    buff[0] = (0x9 << 4) | (_range << 1) | _pga;
    _i2c->write(CTRL_HIGH, &buff[0], 1);
    
    _i2c->read(STATUS, &buff[0], 1);
    
    _bt->putc('.');
    
    //while(!(buff[0] & 0x1))
    //{
        _i2c->read(STATUS, &buff[0], 1);
    //}
    
    if (!_i2c->read((int) TEMP_HIGH, &buff[0], 2))
    {
        result += (buff[1] & 0x1);
        result += (buff[1] & 0x2)*2;
        result += (buff[1] & 0x4)*4;
        result += (buff[1] & 0x8)*8;
        result += (buff[1] & 0x16)*16;
        result += (buff[1] & 0x32)*32;
        result += (buff[1] & 0x64)*64;
        result += (buff[1] & 0x128)*128;
        _bt->putc('.');
        
        result += (buff[0] & 0x1)*256;
        result += (buff[0] & 0x2)*512;
        result += (buff[0] & 0x4)*1024;
        result += (buff[0] & 0x8)*2048;
        result += (buff[0] & 0x16)*4096;
        result += (buff[0] & 0x32)* -8192;
    }
    return result/32;
}

void AD5933::findZ(int f)
{        
    _bt->putc('.');
    //set frequency for sweep
    _freq = f*100000;
    
    //sweep
    sweep1();
    
    //_pc->printf("Got values for _r: %i, _i: %i\n\r", _r, _i);
    
    //get temperature
    _temp[1] = getTemp();
    
    //perform gain/phase correction
    //_pc->printf("_gain[%i]: %f, _gain[%i] corrected: %le", f-1, _gain[f-1], f-1, _gain[f-1] * pow(10.0,-11));
    
    _z = (1.0/((_gain[f-1] * pow(10.0,-11))*sqrt((double)(pow((double)_r, 2)+pow((double)_i,2 )))));
    _phs = (float)atan((double)(_i/_r));
    _phs = _phs - _phase[f-1];
    
    
    //perform temperature correction
    _z = _z + (_temp[1]-_temp[0])*0.00003*_z;
    _bt->putc('.');

}

float AD5933::getZ()
{
    return _z;
}

float AD5933::getPhase()
{
    return _phs;
}