A code for the spindling of bots.
Dependencies: MX12 ServoRingBuffer mbed-src
Fork of SpindleBot by
AD7730/AD7730.cpp
- Committer:
- labmrd
- Date:
- 2015-05-11
- Revision:
- 8:cef07a8bdc42
- Parent:
- 4:e44ac08027bd
- Child:
- 9:f26a91863e3a
File content as of revision 8:cef07a8bdc42:
#include "AD7730.h" /************************************************************************************************************************/ //default constructor requires pin names for spi and ready pin /************************************************************************************************************************/ AD7730::AD7730(PinName mosi, PinName miso, PinName sclk, PinName ready, PinName cs) : _spi(mosi, miso, sclk), _cs(cs), _readyDig(ready), _LED3(LED3){ _readyPin = ready; //setup default parameters for spi //_spi.format(8, 1); //8bits with polarity 0 (clock idle low), phase 1 (write on falling edge, read on rising edge) //_spi.frequency(2000000); //2Mhz //set default setup _minWeight = 1; _maxWeight = 5; _fullScaleWeight = 11.023; //5kgs //reset the device //reset(true); //get default registry values _mode = readRegistry(MODE_REG); _filter = readRegistry(FILTER_REG); _dac = readRegistry(DAC_REG); _offset = readRegistry(OFFSET_REG); _gain = readRegistry(GAIN_REG); //set chip select high _cs = 1; //run internal calibration //internalFullCal(); //internalZeroCal(); //turn off LED3 _LED3 = false; _continous = false; } /************************************************************************************************************************/ // default destructor /************************************************************************************************************************/ AD7730::~AD7730(void){} void AD7730::dump(void){ //get default registry values _mode = readRegistry(MODE_REG); _filter = readRegistry(FILTER_REG); _dac = readRegistry(DAC_REG); _offset = readRegistry(OFFSET_REG); _gain = readRegistry(GAIN_REG); _status = readRegistry(STATUS_REG); printf("_mode=0x%04x\n",_mode); printf("_filter=0x%06x\n",_filter); printf("_dac=0x%02x\n",_dac); printf("_offset=0x%06x\n",_offset); printf("_gain=0x%06x\n",_gain); printf("_status=0x%02x\n",_status); } /************************************************************************************************************************/ //function to read the specified registry value /************************************************************************************************************************/ int AD7730::readRegistry(int registry){ int readReg = 0; int bytes = 0; switch(registry){ case STATUS_REG: //status registry { readReg = 0x10; bytes = 1; break; } case DATA_REG: //data registry { _LED3 = _readyDig ? true : false; readReg = 0x11; bytes = 3; break; } case MODE_REG: //mode registry { readReg = 0x12; bytes = 2; break; } case FILTER_REG: //filter registry { readReg = 0x13; bytes = 3; break; } case DAC_REG: //dac registry { readReg = 0x14; bytes = 1; break; } case OFFSET_REG: //offset registry { readReg = 0x15; bytes = 3; break; } case GAIN_REG: //gain registry { readReg = 0x16; bytes = 3; break; } case TEST_REG: //test registry { readReg = 0x17; bytes = 3; break; } default: //default to status registry { readReg = 0x10; bytes = 1; break; } } // end of switch statement //send command to read the registry _cs = 0; wait_us(5); _spi.write(readReg); int value = 0; //loop through bytes of returned data for(int i=0; i<bytes; i++){ value = (value << 8) | _spi.write(EMPTY_SPI); //shift previous return value up by 8 bits to make room for new data } wait_us(5); _cs = 1; return value; } /************************************************************************************************************************/ //function to write to the specified registry /************************************************************************************************************************/ int AD7730::writeRegistry(int registry, int value){ int writeReg = 0; int bytes = 0; switch(registry){ case MODE_REG: //mode registry { writeReg = 0x02; bytes = 2; _mode = value; //check if continous converstion is being stopped or started _continous = ((value & 0x2000) > 0)? true : false; break; } case FILTER_REG: //filter registry { writeReg = 0x03; bytes = 3; _filter = value; break; } case DAC_REG: //dac registry { writeReg = 0x04; bytes = 1; _dac = value; break; } case OFFSET_REG: //offset registry { writeReg = 0x05; bytes = 3; _offset = value; break; } case GAIN_REG: //gain registry { writeReg = 0x06; bytes = 3; _gain = value; break; } default: //default to communications register { writeReg = 0x00; bytes = 0; break; } } // end of switch statement //send command to write to a the registry _cs = 0; wait_us(5); _spi.write(writeReg); //send data switch(bytes) { case 3: _spi.write(((value >> 16) & 255)); case 2: _spi.write(((value >> 8) & 255)); case 1: _spi.write((value & 255)); break; default: break; } wait_us(5); _cs = 1; return value; } /************************************************************************************************************************/ //function to initiate an internal full-scale calibration /************************************************************************************************************************/ int AD7730::internalFullCal(void){ //reset execution timer _exeTmr.reset(); //1011000100110000 (0xB130) Internal Full-Scale Calibration, unipolar, long data, low reference, 0-80mv, channel 0 writeRegistry(MODE_REG, 0xB130); wait_us(1); //give time for ready line to go high //wait for ready pin to go low indicating calibration complete with timeout of 2000ms int time = 0; while(_readyDig && time < 2000){ wait_ms(2); time += 2; } //update execution time _exeTime = _exeTmr.read_us(); //check if timeout occurred if(time >= 2000){ _exeError = 56; return 1; } else { _exeError = 0; return 0; } } /************************************************************************************************************************/ //function to initiate an internal zero-scale calibration /************************************************************************************************************************/ int AD7730::internalZeroCal(void){ //reset execution timer _exeTmr.reset(); //1001000100110000 (0x9100) Internal Zero-Scale Calibration, unipolar, long data, low reference, 0-10mv, channel 0 writeRegistry(MODE_REG, 0x9100); wait_us(1); //give time for ready line to go high //wait for ready pin to go low indicating calibration complete with timeout of 2000ms int time = 0; while(_readyDig && time < 2000){ wait_ms(2); time += 2; } //update execution time _exeTime = _exeTmr.read_us(); //check if timeout occurred if(time >= 2000){ _exeError = 56; return 1; } else { _exeError = 0; return 0; } } /************************************************************************************************************************/ //function to initialize the chip settings to default values after power up and to run internal calibration /************************************************************************************************************************/ int AD7730::initialize(void){ //reset device reset(true); //initate a full reset systemLowCal(_minWeight); //set the Offset writeRegistry(OFFSET_REG, _offset); //set the Gain writeRegistry(GAIN_REG, _gain); //set the DAC writeRegistry(DAC_REG, _dac); return 0; } /************************************************************************************************************************/ //function to initiate a system zero-scale calibration /************************************************************************************************************************/ int AD7730::systemLowCal(double wgt){ //set minimum weight for low calibration _minWeight = wgt; //1101000100000000 (0xD100) System Zero-Scale Calibration, unipolar, long data, low reference, 0-10mv, channel 0 int mode = 0xD100; writeRegistry(MODE_REG, mode); wait_us(1); //give time for ready pin to go high int time = 0; while(_readyDig && time < 2000){ time += 2; wait_ms(2); }//wait for ready pin to go low if(_readyDig){ //printf("External Zero Failed\r\n"); } return (time >= 2000) ? 1 : 0; } /************************************************************************************************************************/ //function to initiate a system high calibration /************************************************************************************************************************/ int AD7730::systemHighCal(double max, double fullScale){ //get the current offset value int offset = readRegistry(OFFSET_REG); int fullScaleAdjust = ((double)offset - 8388608) + 16777215; fullScaleAdjust /= 2; //double calFactor = fullScale / (fullScaleAdjust / 2); //dual load cells splits the weight in half //set maximum weight for high calibration _maxWeight = max; //calculate the expected value for the maximum weight based on the full scale of the load cell double expected = ((fullScaleAdjust * max) / fullScale); //take some samples double avg = 0; double value = 0; for(int i=0; i<20; i++){ value = (double)read(); avg += value; } avg = avg / 20; //get current gain setting double gain = (double)readRegistry(GAIN_REG); //calculate new gain value double adjustedGain = gain * (expected / avg); printf("Expected: %.3f\r\nActual: %.3f\r\n", expected, avg); int err = 0; if(adjustedGain > 16777215){ //printf("Exceeded Maximum Gain Value\r\n"); err = 1; } //update gain registry writeRegistry(GAIN_REG, (int)adjustedGain); return err; } /************************************************************************************************************************/ //function to initiate the conversion of a sample /************************************************************************************************************************/ int AD7730::startConversion(bool wait){ //set the mode to do a single conversion //5432109876543210 //0100000100000000 (0x4100) Single Conversion, bipolar, short data, low reference, 0-10mv, channel 0 int mode = 0x4100; writeRegistry(MODE_REG, mode); if(wait){ //wait for conversion to complete wait_us(1); //give time for ready to go high*/ int time = 0; while(_readyDig && time < 2000000){ time += 2; wait_us(2); }//wait for ready pin to go low.*/ if(time >= 2000000){ printf("Convert Timeout\r\n"); _exeError = 56; return 1; } } return 0; } /************************************************************************************************************************/ //function to do a single read with conversion /************************************************************************************************************************/ int AD7730::read(){ if(_continous){ //chip is running in continous conversion mode return _lastValue; } else { //a new conversion must be started if(startConversion(true)==1){ return 0; } return readRegistry(DATA_REG); } } /************************************************************************************************************************/ //function to set the filter settings /************************************************************************************************************************/ void AD7730::setFilter(int SF, bool chop, int filter2){ SF = SF << 12; //slide SF settings up 12 bits switch(filter2){ case 2: SF = SF | 512; //turn on bit 10 for skip mode break; case 1: SF = SF | 256; //turn on bit 09 for fast mode break; default: break; //leave bits 9 & 10 off so secondary filter is fully enabled } if(chop){ SF = SF | 16; //turn on bit 5 to enable chop mode } writeRegistry(FILTER_REG,SF); } /************************************************************************************************************************/ //function to reset the chip /************************************************************************************************************************/ void AD7730::reset(bool fullReset){ _cs = 0; wait_us(5); _spi.write(0xFF); _spi.write(0xFF); _spi.write(0xFF); _spi.write(0xFF); _spi.write(0xFF); wait_us(5); _cs = 1; //if not a full reset, then reload registry settings if(!fullReset){ writeRegistry(MODE_REG, _mode); writeRegistry(FILTER_REG, _filter); writeRegistry(DAC_REG, _dac); writeRegistry(OFFSET_REG, _offset); writeRegistry(GAIN_REG, _gain); } else { //reinitiate internal calibration internalFullCal(); wait_ms(100); internalZeroCal(); wait_ms(100); } } /************************************************************************************************************************/ //function to adjust the DAC /************************************************************************************************************************/ int AD7730::adjustDAC(int direction){ int DAC = readRegistry(DAC_REG); int sign = DAC & 32; //get the sign bit DAC &= 31; //remove sign bit if(direction > 0){ //increment DAC if((sign > 0) && (DAC == 1)){ //sign bit is set and DAC is already at 1 change to 0; DAC = 0; sign = 0; } else if((sign == 0) && (DAC >= 0)){ //sign bit is not set increment DAC DAC++; } else if ((sign > 0) && (DAC > 0)){ //sign bit is set decrement DAC because it is negative DAC--; } } else if(direction < 0){ //decrement DAC if((sign == 0) && (DAC == 0)){ //sign bit is not set and DAC is already at 0 DAC = 1; sign = 1; } else if((sign == 0) && (DAC > 0)){ //sign bit is not set increment DAC DAC--; } else if ((sign > 0) && (DAC >= 0)){ //sign bit is set decrement DAC because it is negative DAC++; } } else{ //no change in direction //do nothing return DAC; } if(DAC > 31){ DAC = 31; //limit DAC to maximum value of 31 (5 bits) } if(sign > 0){ DAC |= 32; //set the sign bit of DAC } //update DAC writeRegistry(DAC_REG, DAC); return DAC; } /************************************************************************************************************************/ //function to set the filtering SF setting /************************************************************************************************************************/ void AD7730::setFilterSF(int sf){ //get current filter setting int filter = readRegistry(FILTER_REG); //clear sf bits filter &= 0xFFF; //bitshift sf up by 12 bits sf = sf << 12; //or sf bits with filter bits filter = filter | sf; //apply new filter setting writeRegistry(FILTER_REG, filter); } /************************************************************************************************************************/ //function to set the filtering chop mode /************************************************************************************************************************/ void AD7730::setFilterChop(int enabled){ //get current filter setting int filter = readRegistry(FILTER_REG); //clear bit 5 filter &= ~0x10; //apply chop setting if(enabled) filter |= 0x10; //apply new filter setting writeRegistry(FILTER_REG, filter); } /************************************************************************************************************************/ //function to set the mode of the second filter /************************************************************************************************************************/ void AD7730::setFilterMode(int mode){ //get current filter setting int filter = readRegistry(FILTER_REG); //clear bits 9 & 10 filter &= ~0x300; //apply mode setting if(mode == 1){ filter |= 0x100; //apply fast mode } else if(mode == 2){ filter |= 0x200; //apply skip mode } else { //leave both bits unset } //apply new filter setting writeRegistry(FILTER_REG, filter); } /************************************************************************************************************************/ //function to set the chip to continous conversion /************************************************************************************************************************/ void AD7730::start(void){ writeRegistry(MODE_REG, 0x2100); //set to continous conversion mode //_interruptReady = new InterruptIn(_readyPin); //_interruptReady->fall(this, &AD7730::interruptRead); _continous = true; //set flag indicating that chip is running in continous mode } /************************************************************************************************************************/ //function to stop the chip running in continous conversion mode /************************************************************************************************************************/ void AD7730::stop(void){ writeRegistry(MODE_REG, 0x1100); //set to idle mode _interruptReady = NULL; } /************************************************************************************************************************/ //function to check if the ready digital line is low /************************************************************************************************************************/ bool AD7730::isReady(void){ //if digital line is high, return not ready return (_readyDig)? false : true; } /************************************************************************************************************************/ //function to read data on falling edge of ready pin when running in continous conversion mode /************************************************************************************************************************/ void AD7730::interruptRead(void){ _lastValue = readRegistry(DATA_REG); }