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.
Dependencies: MX12 ServoRingBuffer mbed-src
Fork of SpindleBot by
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 }
Generated on Thu Jul 14 2022 07:15:40 by
1.7.2
