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