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.
Revision 0:c584a588c24f, committed 2011-12-16
- Comitter:
- cfscontrols2
- Date:
- Fri Dec 16 20:31:01 2011 +0000
- Commit message:
Changed in this revision
| AD7730.cpp | Show annotated file Show diff for this revision Revisions of this file |
| AD7730.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/AD7730.cpp Fri Dec 16 20:31:01 2011 +0000
@@ -0,0 +1,684 @@
+#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(1000000); //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;
+ _bufferCount = 0;
+ memset(_readBuffer, 0, 100);
+
+}
+
+/************************************************************************************************************************/
+// default destructor
+/************************************************************************************************************************/
+AD7730::~AD7730(void){}
+
+
+
+
+/************************************************************************************************************************/
+//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
+ //0101000100000000 (0x5000) Single Conversion, unipolar, short data, low reference, 0-10mv, channel 0
+ int mode = 0x5100;
+
+ 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
+ startConversion(true);
+ 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, 0x3100); //set to continous conversion mode
+ _interruptReady = new InterruptIn(_readyPin);
+ _tmr.start();
+ _frequency = 0;
+ _interruptReady->fall(this, &AD7730::interruptRead);
+}
+
+/************************************************************************************************************************/
+//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){
+
+ _continous = true; //set flag indicating that chip is running in continous mode
+
+ _lastValue = readRegistry(DATA_REG);
+
+ //store data in circular buffer
+ _readBuffer[_bufferCount] = _lastValue;
+ if(_bufferCount < 99){
+ _bufferCount++;
+ }
+ else {
+ _bufferCount = 0;
+ }
+
+ //update conversion speed frequency
+ _frequency = _tmr.read_us();
+ _tmr.reset();
+}
+
+/************************************************************************************************************************/
+//function to return the hertz of the data conversion
+/************************************************************************************************************************/
+double AD7730::getHz(void){
+
+ return (1000000 / (double)_frequency);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/AD7730.h Fri Dec 16 20:31:01 2011 +0000
@@ -0,0 +1,85 @@
+#ifndef AD7730_H
+#define AD7730_H
+
+#include "mbed.h"
+
+class AD7730{
+
+ public:
+ AD7730(PinName mosi, PinName miso, PinName sclk, PinName ready, PinName cs);
+ ~AD7730(void);
+
+ int readRegistry(int registry);
+ int writeRegistry(int registry, int value);
+ int initialize(void);
+ int systemLowCal(double wgt);
+ int systemHighCal(double wgt, double fullScale);
+ int read();
+ int startConversion(bool wait);
+ void setFilter(int SF, bool chop, int filter2);
+ void setFilterSF(int SF);
+ void setFilterMode(int mode);
+ void setFilterChop(int enabled);
+ void reset(bool fullReset);
+ int adjustDAC(int direction);
+ void start(void);
+ void stop(void);
+ bool isReady(void);
+ double getHz(void);
+
+
+ private:
+
+ SPI _spi;
+ DigitalOut _cs;
+ DigitalIn _readyDig;
+ DigitalOut _LED3;
+ InterruptIn *_interruptReady;
+ PinName _readyPin;
+ double _fullScaleWeight;
+ double _minWeight;
+ double _maxWeight;
+ int _readBuffer[100];
+ int _bufferCount;
+ int _lastValue;
+ bool _continous;
+ int _frequency;
+ Timer _tmr;
+
+ //Registry value constants
+ static const int STATUS_REG = 0;
+ static const int DATA_REG = 1;
+ static const int MODE_REG = 2;
+ static const int FILTER_REG = 3;
+ static const int DAC_REG = 4;
+ static const int OFFSET_REG = 5;
+ static const int GAIN_REG = 6;
+ static const int TEST_REG = 7;
+
+ //define empty spi command
+ static const int EMPTY_SPI = 0xFF;
+
+ //internal registries
+ int _mode;
+ int _filter;
+ int _dac;
+ int _offset;
+ int _gain;
+
+
+ //timing variables
+ Timer _exeTmr;
+ int _exeTime;
+
+ //error variables
+ int _exeError;
+
+ //private functions
+ int internalZeroCal(void);
+ int internalFullCal(void);
+ void interruptRead(void);
+
+
+};
+
+#endif