1 ////////////////////////////////////////////////////////////////////////////////////// 2 // The MIT License (MIT) 3 // 4 // Submit Date: 03/09/2015 5 // Author: Juan Jose Chong <juanjchong (at) gmail.com> 6 // Copyright (c) 2015 Juan Jose Chong 7 // 8 ////////////////////////////////////////////////////////////////////////////////////// 9 // adis16448.cxx 10 ////////////////////////////////////////////////////////////////////////////////////// 11 // 12 // This library runs on an Intel Edison and uses mraa to acquire data 13 // from an ADIS16448. This data is then scaled and printed onto the terminal. 14 // 15 // This software has been tested to connect to an ADIS16448 through a level shifter 16 // such as the TI TXB0104. The SPI lines (DIN, DOUT, SCLK, /CS) are all wired through 17 // the level shifter and the ADIS16448 is also being powered by the Intel Edison. 18 // 19 // Permission is hereby granted, free of charge, to any person obtaining 20 // a copy of this software and associated documentation files (the 21 // "Software"), to deal in the Software without restriction, including 22 // without limitation the rights to use, copy, modify, merge, publish, 23 // distribute, sublicense, and/or sell copies of the Software, and to 24 // permit persons to whom the Software is furnished to do so, subject to 25 // the following conditions: 26 // 27 // The above copyright notice and this permission notice shall be 28 // included in all copies or substantial portions of the Software. 29 // 30 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 34 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 35 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 // 38 ////////////////////////////////////////////////////////////////////////////////////// 39 #include <iostream> 40 #include <string> 41 #include <stdexcept> 42 #include <unistd.h> 43 #include <stdlib.h> 44 #include <functional> 45 #include <string.h> 46 47 #include "adis16448.h" 48 49 using namespace upm; 50 51 //////////////////////////////////////////////////////////////////////////// 52 // Constructor with configurable CS, DR, and RST 53 //////////////////////////////////////////////////////////////////////////// 54 // RST - Hardware reset pin 55 //////////////////////////////////////////////////////////////////////////// 56 ADIS16448::ADIS16448(int bus, int rst) 57 { 58 // Configure I/O 59 //Initialize RST pin 60 if ( !(_rst = mraa_gpio_init(rst)) ) 61 { 62 throw std::invalid_argument(std::string(__FUNCTION__) + 63 ": mraa_gpio_init() failed, invalid pin?"); 64 return; 65 } 66 mraa_gpio_dir(_rst, MRAA_GPIO_IN); //Set direction as INPUT 67 68 // Configure SPI 69 if ( !(_spi = mraa_spi_init(bus)) ) 70 { 71 throw std::invalid_argument(std::string(__FUNCTION__) + 72 ": mraa_spi_init() failed"); 73 return; 74 } 75 configSPI(); 76 } 77 78 //////////////////////////////////////////////////////////////////////////// 79 // Destructor - Stops SPI and Closes all GPIO used. Reports an error if 80 // unable to close either properly. 81 //////////////////////////////////////////////////////////////////////////// 82 ADIS16448::~ADIS16448() 83 { 84 // Close SPI bus 85 mraa_result_t error; 86 error = mraa_spi_stop(_spi); 87 if(error != MRAA_SUCCESS) 88 { 89 mraa_result_print(error); 90 } 91 // Close GPIO 92 error = mraa_gpio_close(_rst); 93 if(error != MRAA_SUCCESS) 94 { 95 mraa_result_print(error); 96 } 97 } 98 99 //////////////////////////////////////////////////////////////////////////// 100 // Performs hardware reset by setting _RST pin low for 2 seconds. 101 //////////////////////////////////////////////////////////////////////////// 102 void ADIS16448::resetDUT() 103 { 104 mraa_gpio_write(_rst, 0); 105 usleep(100000); //Sleep for 100ms 106 mraa_gpio_write(_rst, 1); 107 usleep(1000000); //Sleep for 1s 108 } 109 110 //////////////////////////////////////////////////////////////////////////// 111 // Sets SPI bit order, clock divider, and data mode. This function is useful 112 // when there are multiple SPI devices using different settings. 113 //////////////////////////////////////////////////////////////////////////// 114 void ADIS16448::configSPI() { 115 mraa_spi_frequency(_spi, 1000000); //Set SPI frequency to 1MHz 116 117 if ( mraa_spi_mode(_spi, MRAA_SPI_MODE3) != MRAA_SUCCESS ) 118 { 119 throw std::invalid_argument(std::string(__FUNCTION__) + 120 ": mraa_spi_mode() failed"); 121 return; 122 } 123 //Set # of bits per word 124 125 if ( mraa_spi_bit_per_word(_spi, 16) != MRAA_SUCCESS ) 126 { 127 throw std::invalid_argument(std::string(__FUNCTION__) + 128 ": mraa_spi_bit_per_word() failed"); 129 return; 130 } 131 } 132 133 //////////////////////////////////////////////////////////////////////////////////////////// 134 // Reads two bytes (one word) in two sequential registers over SPI 135 //////////////////////////////////////////////////////////////////////////////////////////// 136 // regAddr - register address from the lookup table in ADIS16448.h 137 // return - (int) signed 16 bit 2's complement number 138 //////////////////////////////////////////////////////////////////////////////////////////// 139 int16_t ADIS16448::regRead(uint8_t regAddr) 140 { 141 configSPI(); //Set up SPI (useful when multiple SPI devices present on bus) 142 // Write register address to be read 143 uint8_t buf[2]; //Allocate write buffer 144 memset(buf, 0, sizeof(uint8_t)*2); //Initialize buffer and write 0s 145 buf[1] = regAddr; //Write the user-requested register address to the buffer 146 mraa_spi_write_buf(_spi, buf, 2); //Write the buffer onto the SPI port 147 148 usleep(20); //Delay to not violate read rate (210us) 149 150 // Read data from register requested 151 buf[1] = 0; //Clear contents of write buffer 152 uint8_t* x = mraa_spi_write_buf(_spi, buf, 2); //Write 0x0000 to SPI and read data requested above 153 int16_t _dataOut = (x[1] << 8) | (x[0] & 0xFF);; //Concatenate upper and lower bytes 154 155 usleep(20); //delay to not violate read rate (210us) 156 return(_dataOut); 157 } 158 //////////////////////////////////////////////////////////////////////////// 159 // Writes one byte of data to the specified register over SPI 160 //////////////////////////////////////////////////////////////////////////// 161 // regAddr - register address from the lookup table 162 // regData - data to be written to the register 163 //////////////////////////////////////////////////////////////////////////// 164 void ADIS16448::regWrite(uint8_t regAddr,uint16_t regData) 165 { 166 configSPI(); 167 // Separate the 16 bit command word into two bytes 168 uint16_t addr = (((regAddr & 0x7F) | 0x80) << 8); //Check that the address is 7 bits, flip the sign bit 169 uint16_t lowWord = (addr | (regData & 0xFF)); 170 uint16_t highWord = ((addr | 0x100) | ((regData >> 8) & 0xFF)); 171 // Write the low byte to the SPI bus 172 uint8_t lbuf[2]; //Allocate write buffer 173 memset(lbuf, 0, sizeof(uint8_t)*2); //Fill low buffer with 0's 174 lbuf[0] = (lowWord >> 8); 175 lbuf[1] = (lowWord); 176 mraa_spi_write_buf(_spi, lbuf, 2); //Write the buffer to the SPI port 177 178 usleep(20); 179 180 // Write the high byte to the SPI bus 181 uint8_t hbuf[2]; //Allocate write buffer 182 memset(hbuf, 0, sizeof(uint8_t)*2); //Fill high buffer with 0's 183 hbuf[0] = (highWord >> 8); 184 hbuf[1] = (highWord); 185 mraa_spi_write_buf(_spi, hbuf, 2); //Write the buffer to the SPI port 186 187 usleep(20); 188 189 } 190 ///////////////////////////////////////////////////////////////////////////////////////// 191 // Converts accelerometer data output from the sensorRead() function and returns 192 // acceleration in g's 193 ///////////////////////////////////////////////////////////////////////////////////////// 194 // sensorData - data output from sensorRead() 195 // return - (float) signed/scaled accelerometer in G's 196 ///////////////////////////////////////////////////////////////////////////////////////// 197 float ADIS16448::accelScale(int16_t sensorData) 198 { 199 float finalData = sensorData * 0.000833; // multiply by accel sensitivity (250uG/LSB) 200 return finalData; 201 } 202 ///////////////////////////////////////////////////////////////////////////////////////////// 203 // Converts gyro data output from the sensorRead() function and returns gyro rate in deg/sec 204 ///////////////////////////////////////////////////////////////////////////////////////////// 205 // sensorData - data output from sensorRead() 206 // return - (float) signed/scaled gyro in degrees/sec 207 ///////////////////////////////////////////////////////////////////////////////////////// 208 float ADIS16448::gyroScale(int16_t sensorData) 209 { 210 float finalData = sensorData * 0.04; //multiply by gyro sensitivity (0.005 LSB/dps) 211 return finalData; 212 } 213 ///////////////////////////////////////////////////////////////////////////////////////////// 214 // Converts temperature data output from the sensorRead() function and returns temperature 215 // in degrees Celcius 216 ///////////////////////////////////////////////////////////////////////////////////////////// 217 // sensorData - data output from sensorRead() 218 // return - (float) signed/scaled temperature in degrees Celcius 219 ///////////////////////////////////////////////////////////////////////////////////////// 220 float ADIS16448::tempScale(int16_t sensorData) 221 { 222 float finalData = (sensorData * 0.07386) + 31; //multiply by temperature scale and add 31 to equal 0x0000 223 return finalData; 224 } 225 ///////////////////////////////////////////////////////////////////////////////////////////// 226 // Converts barometer data output from sensorRead() function and returns pressure in bar 227 ///////////////////////////////////////////////////////////////////////////////////////////// 228 // sensorData - data output from sensorRead() 229 // return - (float) signed/scaled temperature in degrees Celcius 230 ///////////////////////////////////////////////////////////////////////////////////////// 231 float ADIS16448::pressureScale(int16_t sensorData) 232 { 233 float finalData = (sensorData * 0.02); //multiply by gyro sensitivity (0.005 LSB/dps) 234 return finalData; 235 } 236 ///////////////////////////////////////////////////////////////////////////////////////////// 237 // Converts magnetometer output from sensorRead() function and returns magnetic field 238 // reading in Gauss 239 ///////////////////////////////////////////////////////////////////////////////////////////// 240 // sensorData - data output from sensorRead() 241 // return - (float) signed/scaled temperature in degrees Celcius 242 ///////////////////////////////////////////////////////////////////////////////////////// 243 float ADIS16448::magnetometerScale(int16_t sensorData) 244 { 245 float finalData = (sensorData * 0.0001429); //multiply by sensor resolution (142.9uGa LSB/dps) 246 return finalData; 247 } 248