MRD Lab / SpindleBot_1_5b

Dependencies:   MX12 ServoRingBuffer mbed-src

Fork of SpindleBot by MRD Lab

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AD7730.cpp Source File

AD7730.cpp

00001 #include "AD7730.h"
00002 
00003 /************************************************************************************************************************/
00004 //default constructor requires pin names for spi and ready pin
00005 /************************************************************************************************************************/
00006 AD7730::AD7730(PinName mosi, PinName miso, PinName sclk, PinName ready, PinName cs) : _spi(mosi, miso, sclk), _cs(cs), _readyDig(ready), _LED3(LED3){
00007     
00008     _readyPin = ready;
00009       
00010     //setup default parameters for spi
00011     //_spi.format(8, 1);  //8bits with polarity 0 (clock idle low), phase 1 (write on falling edge, read on rising edge)
00012     //_spi.frequency(2000000); //2Mhz
00013     
00014     //set default setup
00015     _minWeight = 1;
00016     _maxWeight = 5;
00017     _fullScaleWeight = 11.023; //5kgs
00018     
00019     //reset the device
00020     reset(true);
00021     
00022     //get default registry values
00023     _mode = readRegistry(MODE_REG);
00024     _filter = readRegistry(FILTER_REG);
00025     _dac = readRegistry(DAC_REG);
00026     _offset = readRegistry(OFFSET_REG);
00027     _gain = readRegistry(GAIN_REG);
00028     
00029     //set chip select high
00030     _cs = 1; 
00031     
00032     //run internal calibration
00033     internalFullCal();
00034     internalZeroCal(); 
00035     
00036     //turn off LED3
00037     _LED3 = false; 
00038     
00039 
00040     _continous = false;
00041       
00042 }
00043 
00044 /************************************************************************************************************************/
00045 // default destructor
00046 /************************************************************************************************************************/
00047 AD7730::~AD7730(void){}
00048 
00049 void AD7730::dump(void){
00050     
00051     //get default registry values
00052     _mode = readRegistry(MODE_REG);
00053     _filter = readRegistry(FILTER_REG);
00054     _dac = readRegistry(DAC_REG);
00055     _offset = readRegistry(OFFSET_REG);
00056     _gain = readRegistry(GAIN_REG);
00057     _status = readRegistry(STATUS_REG);
00058         
00059     printf("_mode=0x%04x\n",_mode);
00060     printf("_filter=0x%06x\n",_filter);
00061     printf("_dac=0x%02x\n",_dac);
00062     printf("_offset=0x%06x\n",_offset);
00063     printf("_gain=0x%06x\n",_gain);
00064     printf("_status=0x%02x\n",_status);
00065 }
00066 
00067 
00068 /************************************************************************************************************************/
00069 //function to read the specified registry value
00070 /************************************************************************************************************************/
00071 int AD7730::readRegistry(int registry){
00072 
00073     int readReg = 0;
00074     int bytes = 0;
00075     
00076     switch(registry){
00077     
00078         case STATUS_REG: //status registry
00079         {   
00080             readReg = 0x10;
00081             bytes = 1;
00082             break;
00083         }
00084         case DATA_REG: //data registry
00085         {
00086             _LED3 = _readyDig ? true : false;
00087             readReg = 0x11;
00088             bytes = 3;
00089             break;
00090         }
00091         case MODE_REG: //mode registry
00092         {
00093             readReg = 0x12;
00094             bytes = 2;
00095             break;
00096         }
00097         case FILTER_REG: //filter registry
00098         {
00099             readReg = 0x13;
00100             bytes = 3;
00101             break;
00102         }
00103         case DAC_REG: //dac registry
00104         {
00105             readReg = 0x14;
00106             bytes = 1;
00107             break;
00108         }
00109         case OFFSET_REG: //offset registry
00110         {
00111             readReg = 0x15;
00112             bytes = 3;
00113             break;
00114         }
00115         case GAIN_REG: //gain registry
00116         {
00117             readReg = 0x16;
00118             bytes = 3;
00119             break;
00120         }
00121         case TEST_REG: //test registry
00122         {
00123             readReg = 0x17;
00124             bytes = 3;
00125             break;
00126         }
00127         default: //default to status registry
00128         {
00129             readReg = 0x10;
00130             bytes = 1;
00131             break;
00132         }
00133     } // end of switch statement
00134     
00135     //send command to read the registry
00136     _cs = 0; 
00137     wait_us(5);
00138     _spi.write(readReg);
00139     
00140     int value = 0;
00141     //loop through bytes of returned data
00142     for(int i=0; i<bytes; i++){
00143         value = (value << 8) | _spi.write(EMPTY_SPI); //shift previous return value up by 8 bits to make room for new data
00144     }
00145     wait_us(5);
00146     _cs = 1;
00147     
00148     return value;
00149 }
00150 
00151 /************************************************************************************************************************/
00152 //function to write to the specified registry
00153 /************************************************************************************************************************/
00154 int AD7730::writeRegistry(int registry, int value){
00155 
00156     int writeReg = 0;
00157     int bytes = 0;
00158     
00159     switch(registry){
00160     
00161         case MODE_REG: //mode registry
00162         {
00163             writeReg = 0x02;
00164             bytes = 2;
00165             _mode = value;
00166             //check if continous converstion is being stopped or started
00167             _continous = ((value & 0x2000) > 0)? true : false;
00168             break;
00169         }
00170         case FILTER_REG: //filter registry
00171         {
00172             writeReg = 0x03;
00173             bytes = 3;
00174             _filter = value;
00175             break;
00176         }
00177         case DAC_REG: //dac registry
00178         {
00179             writeReg = 0x04;
00180             bytes = 1;
00181             _dac = value;
00182             break;
00183         }
00184         case OFFSET_REG: //offset registry
00185         {
00186             writeReg = 0x05;
00187             bytes = 3;
00188             _offset = value;
00189             break;
00190         }
00191         case GAIN_REG: //gain registry
00192         {
00193             writeReg = 0x06;
00194             bytes = 3;
00195             _gain = value;
00196             break;
00197         }
00198         default: //default to communications register
00199         {
00200             writeReg = 0x00;
00201             bytes = 0;
00202             break;
00203         }
00204     } // end of switch statement
00205     
00206     //send command to write to a the registry
00207     _cs = 0;
00208     wait_us(5);
00209     _spi.write(writeReg);
00210     
00211     //send data
00212     switch(bytes)
00213     {
00214         case 3:
00215             _spi.write(((value >> 16) & 255));
00216         case 2:
00217             _spi.write(((value >> 8) & 255));
00218         case 1:
00219             _spi.write((value & 255));
00220             break;
00221         default:
00222             break;
00223     }
00224     wait_us(5);
00225     _cs = 1;
00226     
00227     return value;
00228 }
00229 
00230 
00231 /************************************************************************************************************************/
00232 //function to initiate an internal full-scale calibration
00233 /************************************************************************************************************************/
00234 int AD7730::internalFullCal(void){
00235     
00236     //reset execution timer
00237     _exeTmr.reset();
00238 
00239     //1011000100110000 (0xB130) Internal Full-Scale Calibration, unipolar, long data, low reference, 0-80mv, channel 0
00240     writeRegistry(MODE_REG, 0xB130);
00241     wait_us(1); //give time for ready line to go high
00242     
00243     //wait for ready pin to go low indicating calibration complete with timeout of 2000ms
00244     int time = 0;
00245     while(_readyDig && time < 2000){
00246         wait_ms(2);
00247         time += 2;
00248     }
00249     
00250     //update execution time
00251     _exeTime = _exeTmr.read_us();
00252     
00253     //check if timeout occurred
00254     if(time >= 2000){
00255         _exeError = 56;
00256         return 1;
00257     }
00258     else {
00259         _exeError = 0;
00260         return 0;
00261     } 
00262 }
00263 
00264 
00265 /************************************************************************************************************************/
00266 //function to initiate an internal zero-scale calibration
00267 /************************************************************************************************************************/
00268 int AD7730::internalZeroCal(void){
00269     
00270     //reset execution timer
00271     _exeTmr.reset();
00272 
00273     //1001000100110000 (0x9100) Internal Zero-Scale Calibration, unipolar, long data, low reference, 0-10mv, channel 0
00274     writeRegistry(MODE_REG, 0x9100);
00275     wait_us(1); //give time for ready line to go high
00276     
00277     //wait for ready pin to go low indicating calibration complete with timeout of 2000ms
00278     int time = 0;
00279     while(_readyDig && time < 2000){
00280         wait_ms(2);
00281         time += 2;
00282     }
00283     
00284     //update execution time
00285     _exeTime = _exeTmr.read_us();
00286     
00287     //check if timeout occurred
00288     if(time >= 2000){
00289         _exeError = 56;
00290         return 1;
00291     }
00292     else {
00293         _exeError = 0;
00294         return 0;
00295     } 
00296 }
00297 
00298 
00299 
00300 /************************************************************************************************************************/
00301 //function to initialize the chip settings to default values after power up and to run internal calibration
00302 /************************************************************************************************************************/
00303 int AD7730::initialize(void){
00304 
00305     //reset device
00306     reset(true); //initate a full reset
00307     
00308     systemLowCal(_minWeight);
00309     
00310     //set the Offset
00311     writeRegistry(OFFSET_REG, _offset);
00312     
00313     //set the Gain
00314     writeRegistry(GAIN_REG, _gain);
00315     
00316     //set the DAC
00317     writeRegistry(DAC_REG, _dac); 
00318     
00319     return 0;   
00320      
00321 }
00322 
00323 
00324 /************************************************************************************************************************/
00325 //function to initiate a system zero-scale calibration
00326 /************************************************************************************************************************/
00327 int AD7730::systemLowCal(double wgt){
00328     
00329     //set minimum weight for low calibration
00330     _minWeight = wgt;
00331     
00332     
00333     //1101000100000000 (0xD100) System Zero-Scale Calibration, unipolar, long data, low reference, 0-10mv, channel 0
00334     int mode = 0xD100;
00335     
00336     writeRegistry(MODE_REG, mode);
00337     
00338     wait_us(1);  //give time for ready pin to go high
00339     int time = 0;
00340     while(_readyDig && time < 2000){
00341         time += 2;
00342         wait_ms(2);
00343     }//wait for ready pin to go low     
00344     
00345     if(_readyDig){
00346         //printf("External Zero Failed\r\n");
00347     }
00348     
00349     return (time >= 2000) ? 1 : 0;
00350     
00351 }
00352 
00353 
00354 /************************************************************************************************************************/
00355 //function to initiate a system high calibration
00356 /************************************************************************************************************************/
00357 int AD7730::systemHighCal(double max, double fullScale){
00358     
00359     //get the current offset value
00360     int offset = readRegistry(OFFSET_REG);
00361     int fullScaleAdjust = ((double)offset - 8388608) + 16777215;
00362     fullScaleAdjust /= 2;
00363     //double calFactor = fullScale / (fullScaleAdjust / 2); //dual load cells splits the weight in half
00364     
00365     //set maximum weight for high calibration
00366     _maxWeight = max;
00367     //calculate the expected value for the maximum weight based on the full scale of the load cell
00368     double expected = ((fullScaleAdjust * max) / fullScale);
00369     
00370     //take some samples
00371     double avg = 0;
00372     double value = 0;
00373     for(int i=0; i<20; i++){
00374         value = (double)read();
00375         avg += value;  
00376     }
00377     
00378     avg = avg / 20;
00379     
00380     //get current gain setting
00381     double gain = (double)readRegistry(GAIN_REG);
00382     
00383     //calculate new gain value
00384     double adjustedGain = gain * (expected / avg);
00385     
00386     printf("Expected: %.3f\r\nActual: %.3f\r\n", expected, avg);
00387     
00388     int err = 0;
00389     if(adjustedGain > 16777215){
00390         //printf("Exceeded Maximum Gain Value\r\n");
00391         err = 1;
00392     }
00393     
00394     //update gain registry
00395     writeRegistry(GAIN_REG, (int)adjustedGain);
00396     
00397     return err;
00398 }
00399 
00400 
00401 
00402 /************************************************************************************************************************/
00403 //function to initiate the conversion of a sample
00404 /************************************************************************************************************************/
00405 int AD7730::startConversion(bool wait){
00406     
00407     //set the mode to do a single conversion
00408     //5432109876543210
00409     //0100000100000000 (0x4100)  Single Conversion, bipolar, short data, low reference, 0-10mv, channel 0
00410     int mode = 0x4100;
00411 
00412     writeRegistry(MODE_REG, mode);
00413     
00414     if(wait){
00415         //wait for conversion to complete
00416          
00417         wait_us(1); //give time for ready to go high*/
00418     
00419         int time = 0;
00420         while(_readyDig && time < 2000000){
00421             time += 2;
00422             wait_us(2);
00423         }//wait for ready pin to go low.*/
00424         
00425         if(time >= 2000000){
00426             printf("Convert Timeout\r\n");
00427             _exeError = 56;
00428             return 1;
00429         }
00430     }
00431     
00432     return 0;
00433 }
00434 
00435 /************************************************************************************************************************/
00436 //function to do a single read with conversion
00437 /************************************************************************************************************************/
00438 int AD7730::read(){
00439 
00440     if(_continous){
00441         //chip is running in continous conversion mode
00442         return _lastValue;
00443     }
00444     else {
00445         //a new conversion must be started
00446         if(startConversion(true)==1){
00447             return 0;
00448         }
00449         return readRegistry(DATA_REG);
00450     }              
00451 }
00452 
00453 
00454 /************************************************************************************************************************/
00455 //function to set the filter settings
00456 /************************************************************************************************************************/
00457 void AD7730::setFilter(int SF, bool chop, int filter2){
00458     
00459     SF = SF << 12; //slide SF settings up 12 bits
00460     
00461     switch(filter2){
00462         case 2:
00463             SF = SF | 512;  //turn on bit 10 for skip mode
00464             break;
00465         case 1:
00466             SF = SF | 256; //turn on bit 09 for fast mode
00467             break;
00468         default:
00469             break; //leave bits 9 & 10 off so secondary filter is fully enabled
00470     }
00471     
00472     if(chop){
00473         SF = SF | 16; //turn on bit 5 to enable chop mode
00474     }
00475     
00476     writeRegistry(FILTER_REG,SF);
00477     
00478 }
00479 
00480 /************************************************************************************************************************/
00481 //function to reset the chip
00482 /************************************************************************************************************************/
00483 void AD7730::reset(bool fullReset){
00484     
00485     _cs = 0;
00486     wait_us(5);
00487     _spi.write(0xFF);
00488     _spi.write(0xFF);
00489     _spi.write(0xFF);
00490     _spi.write(0xFF);
00491     _spi.write(0xFF);
00492     wait_us(5);
00493     _cs = 1;
00494     
00495     //if not a full reset, then reload registry settings
00496     if(!fullReset){
00497         writeRegistry(MODE_REG, _mode);
00498         writeRegistry(FILTER_REG, _filter);
00499         writeRegistry(DAC_REG, _dac);
00500         writeRegistry(OFFSET_REG, _offset);
00501         writeRegistry(GAIN_REG, _gain);
00502     }
00503     else {
00504         //reinitiate internal calibration
00505         internalFullCal();
00506         wait_ms(100);
00507         internalZeroCal();
00508         wait_ms(100);
00509     }
00510 }
00511 
00512 /************************************************************************************************************************/
00513 //function to adjust the DAC
00514 /************************************************************************************************************************/
00515 int AD7730::adjustDAC(int direction){
00516 
00517     int DAC = readRegistry(DAC_REG);
00518     int sign = DAC & 32; //get the sign bit
00519     DAC &= 31; //remove sign bit 
00520  
00521     
00522     if(direction > 0){
00523         //increment DAC
00524         if((sign > 0) && (DAC == 1)){ //sign bit is set and DAC is already at 1 change to 0;
00525             DAC = 0;
00526             sign = 0;
00527         }
00528         else if((sign == 0) && (DAC >= 0)){  //sign bit is not set increment DAC
00529             DAC++;
00530         }
00531         else if ((sign > 0) && (DAC > 0)){  //sign bit is set decrement DAC because it is negative
00532             DAC--;
00533         }
00534         
00535     }
00536     
00537    else if(direction < 0){
00538         //decrement DAC
00539         if((sign == 0) && (DAC == 0)){ //sign bit is not set and DAC is already at 0
00540             DAC = 1;
00541             sign = 1;
00542         }
00543         else if((sign == 0) && (DAC > 0)){  //sign bit is not set increment DAC
00544             DAC--;
00545         }
00546         else if ((sign > 0) && (DAC >= 0)){  //sign bit is set decrement DAC because it is negative
00547             DAC++;
00548         }
00549         
00550     }    
00551 
00552     else{
00553         //no change in direction
00554         //do nothing
00555         return DAC;
00556     }
00557     
00558     if(DAC > 31){
00559         DAC = 31;  //limit DAC to maximum value of 31 (5 bits)
00560     }
00561     
00562     if(sign > 0){
00563         DAC |= 32; //set the sign bit of DAC
00564     }
00565     
00566     //update DAC
00567     writeRegistry(DAC_REG, DAC);
00568     
00569     return DAC;
00570 }
00571 
00572 /************************************************************************************************************************/
00573 //function to set the filtering SF setting
00574 /************************************************************************************************************************/
00575 void AD7730::setFilterSF(int sf){
00576 
00577     //get current filter setting
00578     int filter = readRegistry(FILTER_REG);
00579     
00580     //clear sf bits 
00581     filter &= 0xFFF;
00582     
00583     //bitshift sf up by 12 bits
00584     sf = sf << 12;
00585     
00586     //or sf bits with filter bits
00587     filter = filter | sf;
00588     
00589     //apply new filter setting
00590     writeRegistry(FILTER_REG, filter);
00591 }
00592 
00593 /************************************************************************************************************************/
00594 //function to set the filtering chop mode
00595 /************************************************************************************************************************/
00596 void AD7730::setFilterChop(int enabled){
00597 
00598     //get current filter setting
00599     int filter = readRegistry(FILTER_REG);
00600     
00601     //clear bit 5 
00602     filter &= ~0x10;
00603     
00604     //apply chop setting
00605     if(enabled)
00606         filter |= 0x10;
00607     
00608     //apply new filter setting
00609     writeRegistry(FILTER_REG, filter);
00610 }
00611 
00612 /************************************************************************************************************************/
00613 //function to set the mode of the second filter
00614 /************************************************************************************************************************/
00615 void AD7730::setFilterMode(int mode){
00616 
00617     //get current filter setting
00618     int filter = readRegistry(FILTER_REG);
00619     
00620     //clear bits 9 & 10 
00621     filter &= ~0x300;
00622     
00623     //apply mode setting
00624     if(mode == 1){
00625         filter |= 0x100; //apply fast mode
00626     }
00627     else if(mode == 2){
00628         filter |= 0x200; //apply skip mode
00629     }
00630     else {
00631         //leave both bits unset
00632     }
00633     
00634     
00635     //apply new filter setting
00636     writeRegistry(FILTER_REG, filter);
00637 }
00638 
00639 /************************************************************************************************************************/
00640 //function to set the chip to continous conversion
00641 /************************************************************************************************************************/
00642 void AD7730::start(void){
00643     
00644     writeRegistry(MODE_REG, 0x2100); //set to continous conversion mode
00645     //_interruptReady = new InterruptIn(_readyPin);
00646     //_interruptReady->fall(this, &AD7730::interruptRead);  
00647     _continous = true; //set flag indicating that chip is running in continous mode
00648 }
00649 
00650 /************************************************************************************************************************/
00651 //function to stop the chip running in continous conversion mode
00652 /************************************************************************************************************************/
00653 void AD7730::stop(void){
00654     
00655     writeRegistry(MODE_REG, 0x1100); //set to idle mode
00656     
00657     _interruptReady = NULL;
00658   
00659 }
00660 
00661 /************************************************************************************************************************/
00662 //function to check if the ready digital line is low
00663 /************************************************************************************************************************/
00664 bool AD7730::isReady(void){
00665      
00666     //if digital line is high, return not ready  
00667     return (_readyDig)? false : true;
00668     
00669 }
00670 
00671 /************************************************************************************************************************/
00672 //function to read data on falling edge of ready pin when running in continous conversion mode
00673 /************************************************************************************************************************/
00674 void AD7730::interruptRead(void){
00675 
00676     
00677     _lastValue = readRegistry(DATA_REG);
00678     
00679 }