A collection of Analog Devices drivers for the mbed platform
For additional information check out the mbed page of the Analog Devices wiki: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
Revision 4:5c1b28aff7e1, committed 2016-04-19
- Comitter:
- Adrian Suciu
- Date:
- Tue Apr 19 17:55:14 2016 +0300
- Parent:
- 3:1a8c14043a4e
- Child:
- 5:9221918730aa
- Commit message:
- Driver and application redesign
Changed in this revision
--- a/examples/cn0357_example/main.cpp Fri Apr 01 10:53:41 2016 +0300
+++ b/examples/cn0357_example/main.cpp Tue Apr 19 17:55:14 2016 +0300
@@ -44,7 +44,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************/
-
#include "mbed.h"
#include "cn0357.h"
@@ -88,9 +87,9 @@
@param fdata2 - Gas Concentration reading to be displayed
**/
-void display_data(uint16_t ui16Data, float fData1, float fdata2)
+void display_data(uint8_t ui8Status_Reg, uint16_t ui16Data, float fData1, float fdata2)
{
-
+ pc.printf("\r\nStatus Register value: 0x%x", ui8Status_Reg);
pc.printf("\r\nADC Data Register Value = %#08x", ui16Data); /** Send valid ADC data register value*/
pc.printf("\r\nADC Input Voltage input = %f V", fData1); /** Send valid voltage input value */
pc.printf("\r\nGas Concentration = %f PPM", fdata2); /** Send valid gas concentration value */
@@ -98,35 +97,46 @@
pc.printf("\r\n");
}
-
/**
* Project entry-point - initializes the CN0357 shield, reads the data when the ADC is ready and outputs the sensor
* value in PPM
*/
+
+#define SINGLE_CONVERSION
+//#define CONTINOUS_CONVERSION
+
int main()
{
/* Main variables */
-
+ CN0357 cn0357;
+ uint8_t ui8Status_Reg = 0;
+#ifdef SINGLE_CONVERSION
+ cn0357.init(SENSOR_RANGE, SENSOR_SENSITIVITY);
+#elif defined CONTINOUS_CONVERSION
+ cn0357.init(SENSOR_RANGE, SENSOR_SENSITIVITY, CN0357::INTERNAL_AD7790, 0x00, 0x07);
+#else
+#error define SINGLE_CONVERSION or CONTINOUS_CONVERSION, but not both
+#endif
- CN0357 cn0357;
- cn0357.init(SENSOR_RANGE, SENSOR_SENSITIVITY);
/* Infinite loop */
while (1) {
+ wait_ms(1000);
+#ifdef CONTINOUS_CONVERSION
+ ui8Status_Reg = cn0357.read_adc_status(); // Read ADC Status Register //
- uint8_t ui8Status_Reg = cn0357.read_adc_status(); // Read ADC Status Register
-
- if (ui8Status_Reg == 0x08) { // Checks if ADC data is available
+ if (ui8Status_Reg != 0x08) { // Checks if ADC data is available
+ pc.printf("\r\nStatus Register value: 0x%x", ui8Status_Reg);
+ } else
+#endif
+ {
uint16_t ui16Adcdata = cn0357.read_sensor();
float fAdcVoltage = cn0357.data_to_voltage(ui16Adcdata); // Convert ADC data to voltage
float fConcentration = cn0357.calc_ppm(fAdcVoltage); // Convert voltage to Gas concentration
- display_data(ui16Adcdata, fAdcVoltage, fConcentration); // Display data thru UART
-
- // printf("OneshotRead: %f PPM \r\n", cn0357.readPPM());
+ display_data(ui8Status_Reg, ui16Adcdata, fAdcVoltage, fConcentration); // Display data thru UART
}
+ }
- wait_ms(1000);
- }
/* Infinite loop, never returns. */
}
--- a/libraries/ad5270/AD5270.cpp Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad5270/AD5270.cpp Tue Apr 19 17:55:14 2016 +0300
@@ -60,8 +60,8 @@
AD5270::AD5270(PinName CS, float max_resistance, PinName MOSI, PinName MISO, PinName SCK):
ad5270(MOSI, MISO, SCK), cs(CS), _max_resistance(max_resistance)
{
- ad5270.format(8, 3);
cs = true;
+ ad5270.format(8, _SPI_MODE);
}
/**
@@ -75,12 +75,37 @@
}
/**
+ * @brief sets a new value for the RDAC
+ * @param resistance new value for the resistance
+ * @return actual value of the resistance in the RDAC
+ */
+float AD5270::write_RDAC(float resistance)
+{
+ // Compute for the RDAC code nearest to the required feedback resistance
+ uint16_t RDAC_val = calc_RDAC(resistance);
+ float RDAC_Value = ((static_cast<float> (RDAC_val) * _max_resistance) / 1024.0); // inverse operation to get actual resistance in the RDAC
+ write_wiper_reg(RDAC_val);
+ return RDAC_Value;
+}
+
+/**
+ * Reads the RDAC register
+ * @return RDAC resistor value
+ */
+float AD5270::read_RDAC()
+{
+ uint16_t RDAC_val = read_wiper_reg();
+ return ((static_cast<float> (RDAC_val) * _max_resistance) / 1024.0);
+}
+
+/**
* @brief Puts the AD5270 SDO line in to Hi-Z mode
* @return none
*/
void AD5270::set_SDO_HiZ(void)
{
write_reg(HI_Z_Cmd);
+ wait_us(2);
write_reg(NO_OP_cmd);
}
@@ -108,6 +133,33 @@
}
/**
+ * Enables the 50TP memory programming
+ */
+void AD5270::enable_50TP_programming()
+{
+ uint8_t regVal = read_ctrl_reg();
+ write_cmd(WRITE_CTRL_REG, regVal | PROGRAM_50TP_ENABLE); // RDAC register write protect - allow update of wiper position through digital interface
+}
+
+/**
+ * Stores current RDAC content to the 50TP memory
+ */
+void AD5270::store_50TP()
+{
+ write_cmd(STORE_50TP);
+ wait_ms(_WRITE_OPERATION_50TP_TIMEOUT);
+}
+
+/**
+ * Disables the 50TP memory programming
+ */
+void AD5270::disable_50TP_programming()
+{
+ uint8_t regVal = read_ctrl_reg();
+ write_cmd(WRITE_CTRL_REG, regVal & (~PROGRAM_50TP_ENABLE));
+}
+
+/**
* @brief Writes 16bit data to the AD5270 SPI interface
* @param data to be written
* @return data returned by the AD5270
@@ -117,6 +169,7 @@
uint16_t result;
uint8_t upper_byte = (data >> 8) & 0xFF;
uint8_t lower_byte = data & 0xFF;
+ ad5270.format(8, _SPI_MODE);
cs = false;
result = ((ad5270.write(upper_byte)) << 8);
result |= ad5270.write(lower_byte);
@@ -132,3 +185,99 @@
{
return _max_resistance;
}
+
+/**
+ * Writes the wiper register. This includes reading the control register,
+ * setting write protect off, writing the wiper, and reverting the settings
+ * to the control reg.
+ * @param data to be written
+ */
+void AD5270::write_wiper_reg(uint16_t data)
+{
+ uint8_t reg_val = read_ctrl_reg();
+ write_cmd(WRITE_CTRL_REG, reg_val | RDAC_WRITE_PROTECT); // RDAC register write protect - allow update of wiper position through digital interface
+ write_cmd(WRITE_RDAC, data); // write data to the RDAC register
+ write_cmd(WRITE_CTRL_REG, reg_val); // RDAC register write protect - allow update of wiper position through digital interface
+}
+
+/**
+ * Reads the wiper register value
+ * @return value of the wiper register
+ */
+uint16_t AD5270::read_wiper_reg(void)
+{
+ uint16_t RDAC_val;
+ write_cmd(READ_RDAC);
+ wait_us(_REG_OPERATION_TIMEOUT);
+ RDAC_val = write_cmd(NO_OP);
+ return RDAC_val;
+}
+
+/**
+ * Reads the last programmed value of the 50TP memory
+ * @return last programmed value
+ */
+uint8_t AD5270::read_50TP_last_address(void)
+{
+ uint8_t ret_val;
+ write_cmd(READ_50TP_ADDRESS);
+ wait_us(_MEMORY_OPERATION_TIMEOUT);
+ ret_val = write_cmd(NO_OP);
+ return ret_val;
+}
+
+/**
+ * Reads the content of a 50TP memory address
+ * @param address memory to be read
+ * @return value stored in the 50TP address
+ */
+uint16_t AD5270::read_50TP_memory(uint8_t address)
+{
+ uint16_t ret_val;
+ write_cmd(READ_50TP_CONTENTS, address);
+ wait_us(_MEMORY_OPERATION_TIMEOUT);
+ ret_val = write_cmd(NO_OP);
+ return ret_val;
+}
+
+/**
+ * Writes the control register
+ * @param data to be written
+ */
+void AD5270::write_ctrl_reg(uint8_t data)
+{
+ write_cmd(WRITE_CTRL_REG, data);
+}
+
+/**
+ * Reads the control register
+ * @return value of the control register
+ */
+uint8_t AD5270::read_ctrl_reg(void)
+{
+ uint8_t ret_val;
+ write_cmd(READ_CTRL_REG);
+ wait_us(_REG_OPERATION_TIMEOUT);
+ ret_val = write_cmd(NO_OP);
+ return ret_val;
+}
+
+/**
+ * Resets the wiper register value to the data last written in the 50TP
+ */
+void AD5270::reset_RDAC(void)
+{
+ write_cmd(SW_RST);
+}
+
+/**
+ * Changes the device mode, enabled or shutdown
+ * @param mode - new mode of the device
+ */
+void AD5270::change_mode(AD5270Modes_t mode)
+{
+ write_cmd(SW_SHUTDOWN, static_cast<uint8_t>(mode));
+}
+
+
+
--- a/libraries/ad5270/AD5270.h Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad5270/AD5270.h Tue Apr 19 17:55:14 2016 +0300
@@ -59,36 +59,77 @@
/// AD5270 commands
typedef enum {
- NO_OP = 0x00, ///< No data
- NO_OP_cmd = 0x0000, ///< 16 bit no data
- WRITE_RDAC = 0x04, ///< Write to the RDAC Register
- READ_RDAC = 0x08, ///< Read from the RDAC Register
- STORE_50TP = 0x0C, ///< Write to the RDAC to memory
- SW_RST = 0x10, ///< Software reset to last memory location
- READ_50TP_CONTENTS = 0x14, ///< Read the last memory contents
- READ_50TP_ADDRESS = 0x18, ///< Read the last memory address
- WRITE_CTRL_REG = 0x1C, ///< Write to the control Register
- READ_CTRL_REG = 0x20, ///< Read from the control Register
- SW_SHUTDOWN = 0x24, ///< Software shutdown (0) - Normal, (1) - Shutdown
- HI_Zupper = 0x80, ///< Get the SDO line ready for High Z
- HI_Zlower = 0x01, ///< Puts AD5270 into High Z mode
+ NO_OP = 0x00, ///< No data
+ NO_OP_cmd = 0x0000, ///< 16 bit no data
+ WRITE_RDAC = 0x04, ///< Write to the RDAC Register
+ READ_RDAC = 0x08, ///< Read from the RDAC Register
+ STORE_50TP = 0x0C, ///< Write from RDAC to memory
+ SW_RST = 0x10, ///< Software reset to last memory location
+ READ_50TP_CONTENTS = 0x14, ///< Read the last memory contents
+ READ_50TP_ADDRESS = 0x18, ///< Read the last memory address
+ WRITE_CTRL_REG = 0x1C, ///< Write to the control Register
+ READ_CTRL_REG = 0x20, ///< Read from the control Register
+ SW_SHUTDOWN = 0x24, ///< Software shutdown (0) - Normal, (1) - Shutdown
+ HI_Zupper = 0x80, ///< Get the SDO line ready for High Z
+ HI_Zlower = 0x01, ///< Puts AD5270 into High Z mode
HI_Z_Cmd = 0x8001 ///< Puts AD5270 into High Z mode*/
} AD5270Commands_t;
+ typedef enum {
+ NORMAL_MODE = 0,
+ SHUTDOWN_MODE = 1
+ } AD5270Modes_t;
+
+ typedef enum {
+ PROGRAM_50TP_ENABLE = 1,
+ RDAC_WRITE_PROTECT = 2,
+ R_PERFORMANCE_ENABLE = 4,
+ MEMORY_PROGRAM_SUCCESFUL = 8
+ } AD5270ControlRegisterBits_t;
+
+ // SPI configuration & constructor
AD5270(PinName CS = SPI_CS, float max_resistance = 20000.0, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
+ void frequency(int hz);
+
+ /* RDAC commands */
+ void write_ctrl_reg(uint8_t data);
+ uint8_t read_ctrl_reg(void);
+ void change_mode(AD5270Modes_t mode);
void set_SDO_HiZ(void);
- void frequency(int hz);
- uint16_t calc_RDAC(float resistance);
+
+ /* Wiper R/W methods*/
+ void reset_RDAC(void);
+ void write_wiper_reg(uint16_t data);
+ uint16_t read_wiper_reg(void);
+
+
+ /* Low level methods */
uint16_t write_cmd(uint8_t command, uint16_t data = 0x00);
uint16_t write_reg(uint16_t data);
+
+ /* Methods that deal with resistance in float format*/
+ uint16_t calc_RDAC(float resistance);
+ float write_RDAC(float resistance);
+ float read_RDAC(void);
float get_max_resistance(void);
+ /* 50 TP methods */
+ void enable_50TP_programming(void);
+ void store_50TP(void);
+ void disable_50TP_programming(void);
+ uint8_t read_50TP_last_address(void);
+ uint16_t read_50TP_memory(uint8_t address);
+
SPI ad5270; ///< SPI instance of the AD5270
- DigitalOut cs; ///< DigitalOut instance for the chipselect of the AD5270
+ DigitalOut cs; ///< DigitalOut instance for the chip select of the AD5270
private:
const static int _RESET = 0xff;
+ const static int _REG_OPERATION_TIMEOUT = 2;
+ const static int _MEMORY_OPERATION_TIMEOUT = 6;
+ const static int _WRITE_OPERATION_50TP_TIMEOUT = 350;
const static int _DUMMY_BYTE = 0xAA;
+ const static uint8_t _SPI_MODE = 1;
float _max_resistance;
};
--- a/libraries/ad7790/AD7790.cpp Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad7790/AD7790.cpp Tue Apr 19 17:55:14 2016 +0300
@@ -49,7 +49,6 @@
#include "mbed.h"
#include "ad7790.h"
-
/**
* @brief AD7790 constructor, sets CS pin and SPI format
* @param CS - (optional)chip select of the AD7790
@@ -57,14 +56,17 @@
* @param MISO - (optional)pin of the SPI interface
* @param SCK - (optional)pin of the SPI interface
*/
-AD7790::AD7790(PinName CS,
+AD7790::AD7790(float reference_voltage,
+ PinName CS,
PinName MOSI,
PinName MISO,
PinName SCK) :
- ad7790(MOSI, MISO, SCK), cs(CS)
+ ad7790(MOSI, MISO, SCK), cs(CS), miso(MISO), _vref(reference_voltage), _PGA_gain(1)
{
- ad7790.format(8, 3);
cs = true; // cs is active low
+ ad7790.format(8, _SPI_MODE);
+ _continous_conversion = true;
+ _channel = DIFFERENTIAL;
}
/**
@@ -83,74 +85,314 @@
*/
void AD7790::reset()
{
+ ad7790.format(8, _SPI_MODE);
cs = false;
+ wait_us(_DELAY_TIMING);
ad7790.write(_RESET);
ad7790.write(_RESET);
ad7790.write(_RESET);
ad7790.write(_RESET);
+ wait_us(_DELAY_TIMING);
cs = true;
+ _continous_conversion = true;
+}
+
+/**
+ * Sets the mode register. Also sets continous mode and range based on the value
+ * written in reg_val
+ * @param reg_val
+ */
+void AD7790::write_mode_reg(uint8_t reg_val)
+{
+ write_reg(MODE_REG, reg_val);
+ uint8_t continous_mode = (reg_val & 0xC0);
+ if(continous_mode == 0x00) {
+ _continous_conversion = true;
+ } else {
+ _continous_conversion = false;
+ }
+ uint8_t range = (reg_val & 0x30);
+ _PGA_gain = 1 << (range >> 4);
+}
+
+/**
+ * Reads the mode register and returns its value
+ * @return value of the mode register
+ */
+uint8_t AD7790::read_mode_reg()
+{
+ return read_reg(MODE_REG);
+}
+
+/**
+ * Writes the filter register
+ * @param regValue value to be written.
+ */
+void AD7790::write_filter_reg(uint8_t reg_val)
+{
+ write_reg(FILTER_REG, reg_val);
+}
+
+/**
+ * Reads the filter register and returns its value
+ * @return the value of the filter register
+ */
+uint8_t AD7790::read_filter_reg()
+{
+ return read_reg(FILTER_REG);
+}
+
+/**
+ * Reads the data register and returns its value
+ * @return value of the data register
+ */
+uint16_t AD7790::read_data_reg()
+{
+ uint16_t data_result;
+ ad7790.format(8, _SPI_MODE);
+ cs = false;
+ ad7790.write(_DATA_READ | (static_cast<uint8_t>(_channel)));
+ data_result = ((ad7790.write(_DUMMY_BYTE)) << 8);
+ data_result |= (ad7790.write(_DUMMY_BYTE));
+ cs = true;
+ return data_result;
}
/**
- * @brief Reads the data register of the AD7790
- * @return value of the register
+ * Reads the status register of the ADC and returns its value
+ * @return value of the status reg
*/
-uint16_t AD7790::read_data(void)
+uint8_t AD7790::read_status_reg()
{
- uint16_t dataResult = 0;
+ return read_reg(STATUS_REG);
+}
+
+
+/**
+ * @brief Enables/disables continous_conversion mode
+ * In Single Conversion mode, read_u16 method will read the MODE register of the ADC,
+ * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low,
+ * When the pin is driven low, data register is read back from the ADC.
+ *
+ * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low,
+ * the data register is read back from the ADC.
+ *
+ * @param mode
+ * true - continous conversion mode enabled
+ * false - single conversion mode enabled
+ */
+void AD7790::set_conversion_mode(AD7790Mode_t mode)
+{
+ uint8_t mode_reg_val;
+ mode_reg_val = read_mode_reg() & 0x3F;
+ mode_reg_val = mode_reg_val | (static_cast<uint8_t>(mode));
+ write_mode_reg(mode);
+}
+/**
+ * - From mbed AnalogIn API -
+ * @brief Read the input voltage, represented as an unsigned short in the range [0x0, 0xFFFF]
+ * Depending on the conversion mode, this method will have different behavior. Conversion mode is set using
+ * set_continous_conversion_mode(bool).
+ *
+ * In Single Conversion mode, read_u16 method will read the MODE register of the ADC,
+ * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low,
+ * When the pin is driven low, data register is read back from the ADC.
+ *
+ * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low,
+ * the data register is read back from the ADC.
+ *
+ * @return 16-bit unsigned short representing the current input voltage, normalised to a 16-bit value
+ * returns -1 (0xFFFF) along with a debug message if conversion failed.
+ */
+uint16_t AD7790::read_u16(void)
+{
+ uint16_t data_result = 0;
+ ad7790.format(8, _SPI_MODE);
cs = false;
- ad7790.write(_DATA_READ);
- dataResult = ((ad7790.write(_DUMMY_BYTE)) << 8);
- dataResult |= (ad7790.write(_DUMMY_BYTE));
+ uint16_t timeout_cnt = 0;
+ if(_continous_conversion == false) {
+
+ uint8_t mode_reg = read_mode_reg();
+ wait_us(_DELAY_TIMING);
+
+ cs = false;
+ mode_reg = (mode_reg & 0x3F) | MD1; // mask single conversion bits
+ ad7790.write((MODE_REG << 4) | (static_cast<uint8_t>(_channel))); // start single conversion
+ ad7790.write(mode_reg);
+ timeout_cnt = _SINGLE_CONVERSION_TIMEOUT; // starts timeout
+ } else {
+ timeout_cnt = _CONTINOUS_CONVERSION_TIMEOUT; // starts timeout
+ }
+
+ while(miso) { // wait for the MISO pin to go low.
+ if(timeout_cnt) {
+ timeout_cnt--;
+ } else {
+ cs = true;
+#ifdef AD7790_DEBUG_MODE
+ printf("timeout occurred reading the AD7790. "); // error, MISO line didn't toggle
+#endif
+ return -1; // ERROR
+ }
+ wait_us(10);
+ }
+
+ ad7790.write(_DATA_READ | (static_cast<uint8_t>(_channel)));
+ data_result = ((ad7790.write(_DUMMY_BYTE)) << 8);
+ data_result |= (ad7790.write(_DUMMY_BYTE));
cs = true;
-
- return dataResult;
+ return data_result;
}
/**
* @brief Reads a register of the AD7790
- * @param regAddress - address of the register
+ * @param address - address of the register
* @return value of the register
*/
-uint16_t AD7790::read_reg(AD7790Registers_t regAddress)
+uint16_t AD7790::read_reg(AD7790Register_t address)
{
- uint16_t data = regAddress << 12;
+ uint16_t data = address << 12;
data |= _DUMMY_BYTE;
data |= _READ_FLAG;
+ data |= (static_cast<uint8_t>(_channel) << 8);
return write_spi(data);
}
/**
* @brief Writes a register of the AD7790
- * @param regAddress - address of the register
- * @param regValue - value to be written
+ * @param address - address of the register
+ * @param reg_val - value to be written
* @return none
*
*/
-void AD7790::write_reg(AD7790Registers_t regAddress, uint8_t regValue)
+void AD7790::write_reg(AD7790Register_t address, uint8_t reg_val)
{
- uint16_t data = regAddress << 12;
- data |= regValue;
- write_spi(data);
+ uint16_t spi_data = address << 12;
+ spi_data |= reg_val;
+ spi_data |= (static_cast<uint8_t>(_channel) << 8);
+ write_spi(spi_data);
}
/**
* @brief Writes 16bit data to the AD7790 SPI interface
- * @param data to be written
+ * @param reg_val to be written
* @return data returned by the AD7790
*/
-uint16_t AD7790::write_spi(uint16_t data)
+uint16_t AD7790::write_spi(uint16_t reg_val)
{
- uint16_t result;
- uint8_t upper_byte = (data >> 8) & 0xFF;
- uint8_t lower_byte = data & 0xFF;
+ uint16_t data_result;
+ uint8_t upper_byte = (reg_val >> 8) & 0xFF;
+ uint8_t lower_byte = reg_val & 0xFF;
+ ad7790.format(8, _SPI_MODE);
cs = false;
- result = (ad7790.write(upper_byte) << 8);
- result |= ad7790.write(lower_byte);
+ data_result = (ad7790.write(upper_byte) << 8);
+ data_result |= ad7790.write(lower_byte);
cs = true;
- return result;
+ return data_result;
}
+/**
+ * Sets the AnalogInputRange to be used by the AD7790
+ * @param range AnalogInputRange_t to be used in voltage computations
+ */
+void AD7790::set_range(AnalogInputRange_t range)
+{
+ uint8_t mode_reg_val;
+ mode_reg_val = read_mode_reg() & 0xCF;
+ mode_reg_val = mode_reg_val | (range << 4);
+ write_mode_reg(mode_reg_val);
+}
+
+/**
+ * Sets the reference voltage of the AD7790
+ * @param ref reference voltage to be set
+ */
+void AD7790::set_reference_voltage(float ref)
+{
+ _vref = ref;
+}
+
+/**
+ * Gets the reference voltage of the AD7790
+ * @return reference voltage
+ */
+float AD7790::get_reference_voltage(void)
+{
+ return _vref;
+}
+
+/**
+ * Reads the data register of the ADC and converts the result to volts
+ * Gain needs to be correctly set using set_gain in order to get accurate results
+ * @return voltage of the ADC input
+ */
+float AD7790::read_voltage(void)
+{
+ return data_to_voltage(read_u16());
+}
+
+/**
+ * Converts an uint16_t to voltage.
+ * Gain needs to be correctly set using set_gain in order to get accurate results
+ * @param data in uint16_t format
+ * @return float value of voltage (in V)
+ */
+float AD7790::data_to_voltage(uint16_t data)
+{
+ return ((data / static_cast<float>(_RESOLUTION / 2)) - 1) * (_vref / _PGA_gain);
+}
+
+/**
+ * Converts voltage to an uint16_t.
+ * Gain needs to be correctly set using set_gain in order to get accurate results
+ * @param voltage to be converted
+ * @return data in uint16_t format
+ */
+uint16_t AD7790::voltage_to_data(float voltage)
+{
+ return (((voltage * _PGA_gain / _vref) + 1) * static_cast<float>(_RESOLUTION / 2));
+}
+
+/**
+ * Sets the conversion channel.
+ * @param channel
+ */
+void AD7790::set_channel(AD7790Channel_t channel)
+{
+ _channel = channel;
+}
+
+/**
+ * - From mbed AnalogIn API -
+ * Read the input voltage, represented as a float in the range [0.0, 1.0] - uses the read_u16 method
+ * @returns A floating-point value representing the current input voltage, measured as a percentage
+ * returns 1.0 along with a debug message if the conversion failed
+ */
+float AD7790::read(void)
+{
+ float percent;
+ uint16_t data;
+ data = read_u16();
+ percent = (data / static_cast<float>(_RESOLUTION) ); // translate bipolar conversion to [0.0, 1.0] domain
+ return percent;
+}
+
+#ifdef MBED_OPERATORS
+
+/**
+ * - From mbed AnalogIn API -
+ * An operator shorthand for read()
+ * The float() operator can be used as a shorthand for read() to simplify common code sequences
+ */
+AD7790::operator float()
+{
+ return read();
+}
+
+#endif
+
+
+
--- a/libraries/ad7790/AD7790.h Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad7790/AD7790.h Tue Apr 19 17:55:14 2016 +0300
@@ -53,6 +53,13 @@
/**
* @brief Analog Devices AD7790 SPI 16-bit Buffered Sigma-Delta ADC
*/
+
+/**
+ * Comment this line if you want to turn off the debug mode.
+ * The debug mode will send a message if an exception occurs within AD7790 driver
+ */
+#define AD7790_DEBUG_MODE
+
class AD7790
{
public:
@@ -63,33 +70,105 @@
MODE_REG, ///< Mode register
FILTER_REG, ///< Filter Register
DATA_REG ///< Data register
- } AD7790Registers_t;
+ } AD7790Register_t;
/// AD7790 channel configuration
typedef enum {
- DIFFERENTIAL, ///< AIN(+)-AIN(-)
+ DIFFERENTIAL = 0, ///< AIN(+)-AIN(-)
RESERVED, ///< reserved
SHORT, ///< AIN(-)-AIN(-)
VDDMONITOR ///< Monitor VDD
} AD7790Channel_t;
- AD7790(PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
+ typedef enum {
+ CONTINOUS_CONVERSION_MODE = 0,
+ SINGLE_CONVERSION_MODE = 0x80,
+ SHUTDOWN_MODE = 0xC0
+ } AD7790Mode_t;
+
+ typedef enum {
+ MD1 = 0x80, ///< Mode Select Bit 1
+ MD0 = 0x40, ///< Mode Select Bit 0
+ G1 = 0x20, ///< Range bit 1
+ G0 = 0x10, ///< Range bit 0
+ BO = 0x08, ///< Burnout Current Enable bit
+ BUF = 0x02, ///< Buffered mode bit
+ } ModeRegisterBits_t;
+
+ typedef enum {
+ CLKDIV1 = 0x40, ///< Clock divider bit 1
+ CLKDIV0 = 0x20, ///< Clock divider bit 0
+ FS2 = 0x04, ///< Update rate bit 2
+ FS1 = 0x02, ///< Update rate bit 1
+ FS0 = 0x01, ///< Update rate bit 0
+ } FilterRegisterBits_t;
+
+ typedef enum {
+ RANGE_VREF = 0,
+ RANGE_VREF_DIV_2,
+ RANGE_VREF_DIV_4,
+ RANGE_VREF_DIV_8,
+ } AnalogInputRange_t;
+
+ /** SPI configuration & constructor */
+ AD7790( float reference_voltage, PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
void frequency(int hz);
+
+ /** Low level SPI bus comm methods */
void reset(void);
- void write_reg(AD7790Registers_t regAddress, uint8_t regValue);
- uint16_t write_spi(uint16_t data);
- uint16_t read_reg (AD7790Registers_t regAddress);
- uint16_t read_data(void);
+
+ /** Register access methods*/
+ void set_channel(AD7790Channel_t channel);
+ void set_conversion_mode(AD7790Mode_t mode);
+ uint16_t read_data_reg();
+ uint8_t read_status_reg(void);
+ void write_filter_reg(uint8_t regVal);
+ uint8_t read_filter_reg(void);
+ void write_mode_reg(uint8_t regVal);
+ uint8_t read_mode_reg(void);
+ void set_range(AnalogInputRange_t range);
+ AnalogInputRange_t get_range(void);
+
+ /** Reference voltage methods */
+ void set_reference_voltage(float ref);
+ float get_reference_voltage(void);
+
+ /** Voltage read methods */
+ float read_voltage(void);
+ float data_to_voltage(uint16_t data);
+ uint16_t voltage_to_data(float voltage);
+
+ /** AnalogIn API */
+ float read(void);
+ uint16_t read_u16(void);
+
+#ifdef MBED_OPERATORS
+ operator float();
+#endif
SPI ad7790; ///< SPI instance of the AD7790
DigitalOut cs; ///< DigitalOut instance for the chipselect of the AD7790
private:
+ DigitalIn miso;
+ float _vref;
+ uint8_t _PGA_gain;
+ bool _continous_conversion;
+ AD7790Channel_t _channel;
- const static int _RESET = 0xFF;
- const static int _DUMMY_BYTE = 0xAA;
- const static int _READ_FLAG = 0x0800;
- const static int _DATA_READ = 0x38; // Read from the Data Register
+ void write_reg(AD7790Register_t regAddress, uint8_t regValue);
+ uint16_t write_spi(uint16_t data);
+ uint16_t read_reg (AD7790Register_t regAddress);
+
+ const static uint16_t _SINGLE_CONVERSION_TIMEOUT = 0xFFFF; // in 10us = 100ms
+ const static uint16_t _CONTINOUS_CONVERSION_TIMEOUT = 0xFFFF;
+ const static uint16_t _RESOLUTION = 0xFFFF;
+ const static uint8_t _RESET = 0xFF;
+ const static uint8_t _DUMMY_BYTE = 0xFF;
+ const static uint16_t _READ_FLAG = 0x0800;
+ const static uint8_t _DATA_READ = 0x38; // Read from the Data Register
+ const static uint8_t _DELAY_TIMING = 0x02;
+ const static uint8_t _SPI_MODE = 3;
};
#endif
--- a/libraries/cn0357/cn0357.cpp Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/cn0357/cn0357.cpp Tue Apr 19 17:55:14 2016 +0300
@@ -60,8 +60,9 @@
*/
CN0357::CN0357(PinName CSAD7790, PinName CSAD5270, PinName MOSI, PinName MISO,
PinName SCK) :
- ad7790(CSAD7790, MOSI, MISO, SCK), ad5270(CSAD5270, 20000.0, MOSI, MISO, SCK) ,
- _sensor_sensitivity(0), _sensor_range(0), _RDACvalue(0)
+ _vref(1.2), _sensor_sensitivity(0), _sensor_range(0), _RDACvalue(0),
+ ad7790(_vref, CSAD7790, MOSI, MISO, SCK), ad5270(CSAD5270, 20000.0, MOSI, MISO, SCK)
+
{
}
@@ -79,11 +80,11 @@
ad7790.frequency(500000);
float resistance = set_sensor_parameters(range, sensitivity);
- _rdac_init(resistance);
+
if(jp == INTERNAL_AD7790) {
_AD7790_init(mode_val, filter_val);
}
-
+ _rdac_init(resistance);
}
/**
@@ -108,10 +109,13 @@
void CN0357::_AD7790_init(uint8_t mode_val, uint8_t filter_val)
{
ad7790.reset();
- // wait_ms(1000);
- ad7790.write_reg(AD7790::MODE_REG, mode_val);
- ad7790.write_reg(AD7790::FILTER_REG, filter_val);
+ wait_ms(50);
+ ad7790.write_mode_reg(mode_val);
+ wait_us(2);
+
+ ad7790.write_filter_reg(filter_val);
+ wait_ms(50);
}
/**
@@ -120,7 +124,7 @@
*/
uint8_t CN0357::read_adc_status(void)
{
- return ad7790.read_reg(AD7790::STATUS_REG);
+ return ad7790.read_status_reg();
}
/**
@@ -129,7 +133,7 @@
*/
float CN0357::read_sensor_voltage(void)
{
- return data_to_voltage(read_sensor());
+ return ad7790.read_voltage();
}
/**
@@ -138,7 +142,7 @@
*/
uint16_t CN0357::read_sensor(void)
{
- return ad7790.read_data();
+ return ad7790.read_u16();
}
/**
@@ -147,7 +151,7 @@
*/
float CN0357::read_ppm()
{
- return calc_ppm(read_sensor_voltage()); /* Convert voltage to Gas concentration*/
+ return calc_ppm(ad7790.read_voltage()); /* Convert voltage to Gas concentration*/
}
/**
@@ -169,7 +173,7 @@
*/
float CN0357::data_to_voltage(uint16_t data)
{
- return ((static_cast<float>(data) / pow(2, 15)) - 1) * 1.2; /* Bipolar voltage computation from ADC code */
+ return ad7790.data_to_voltage(data);
}
/**
@@ -179,12 +183,7 @@
*/
void CN0357::set_RDAC_value(float resistance)
{
- // Compute for the RDAC code nearest to the required feedback resistance
- uint16_t RDAC_val = (resistance / 20000.0) * 1024.0;
- // Compute for the constants used in voltage and PPM conversion computation
- _RDACvalue = ((static_cast<float> (RDAC_val) * 20000.0) / 1024.0);
- ad5270.write_cmd(AD5270::WRITE_CTRL_REG, 0x02); // RDAC register write protect - allow update of wiper position through digital interface
- ad5270.write_cmd(AD5270::WRITE_RDAC, RDAC_val); // write data to the RDAC register
+ _RDACvalue = ad5270.write_RDAC(resistance);
}
/**
@@ -208,7 +207,7 @@
{
_sensor_sensitivity = static_cast<float>(sensitivity);
_sensor_range = range;
- return (1.2 / (static_cast<float>(_sensor_range * _sensor_sensitivity)));
+ return (_vref / (static_cast<float>(_sensor_range * _sensor_sensitivity)));
}
/**
--- a/libraries/cn0357/cn0357.h Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/cn0357/cn0357.h Tue Apr 19 17:55:14 2016 +0300
@@ -59,6 +59,15 @@
{
public:
+private:
+ float _vref;
+ float _sensor_sensitivity;
+ float _sensor_range;
+ float _RDACvalue;
+public:
+ AD7790 ad7790; ///< AD7790 instance - can be used for manual overriding
+ AD5270 ad5270; ///< AD5270 instance - can be used for manual overriding
+
/// CN0357 shield jumper configuration
typedef enum {
INTERNAL_AD7790 = 0, ///< The shield's AD7790 is used
@@ -75,27 +84,22 @@
float calc_ppm(float adcVoltage);
float read_ppm(void);
+ void set_vref(float vref);
+ float get_vref(void);
+
void set_RDAC_value(float resistor_val);
float get_RDAC_value(void);
float set_sensor_parameters(float range, float sensitivity);
float get_sensor_range(void);
float get_sensor_sensitivity(void);
-
- AD7790 ad7790; ///< AD7790 instance - can be used for manual overriding
- AD5270 ad5270; ///< AD5270 instance - can be used for manual overriding
-
private:
const static int _RESET = 0xff;
- const static int _DEFAULT_MODE_VAL = 0x00;
- const static int _DEFAULT_FILTER_VAL = 0x07;
- float _sensor_sensitivity;
- float _sensor_range;
- float _RDACvalue;
+ const static int _DEFAULT_MODE_VAL = AD7790::MD1 | AD7790::MD0; // POWERDOWN MODE
+ const static int _DEFAULT_FILTER_VAL = AD7790::FS0 | AD7790::FS1 | AD7790::FS2;
void _rdac_init(float resistanceValue);
void _AD7790_init(uint8_t mode_val, uint8_t filter_val);
-
};
#endif // CN0357_H
CN0357 - Toxic gas measurement
CN0216 - Weight Scale