├── README.md ├── Test Setup.jpg └── x_IMU_Arduino_Example ├── Quaternion.cpp ├── Quaternion.h ├── XimuReceiver.cpp ├── XimuReceiver.h └── x_IMU_Arduino_Example.ino /README.md: -------------------------------------------------------------------------------- 1 | x-IMU-Arduino-Example 2 | ===================== 3 | 4 | Generic C++ library for receiving data from the [x-IMU](http://www.x-io.co.uk/x-imu/), implemented and tested with Arduino. x-IMU auxiliary port must be configured for UART mode, see x_IMU_Arduino_Example.ino for details. 5 | 6 | ========= 7 | 8 | 9 | -------------------------------------------------------------------------------- /Test Setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xioTechnologies/x-IMU-Arduino-Example/0e524efdc00b717eb4eef4ba4bd5a1995da34e14/Test Setup.jpg -------------------------------------------------------------------------------- /x_IMU_Arduino_Example/Quaternion.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Quaternion.cpp 3 | Author: Seb Madgwick 4 | 5 | C++ library for basic usage of quaternions. 6 | See: http://www.x-io.co.uk/quaternions/ 7 | */ 8 | 9 | //------------------------------------------------------------------------------ 10 | // Includes 11 | 12 | #include "Quaternion.h" 13 | #include 14 | 15 | //------------------------------------------------------------------------------ 16 | // Variables 17 | 18 | float q[4]; 19 | 20 | //------------------------------------------------------------------------------ 21 | // Methods 22 | 23 | Quaternion::Quaternion(void) { 24 | q[0] = 1.0f; 25 | q[1] = 0.0f; 26 | q[2] = 0.0f; 27 | q[3] = 0.0f; 28 | } 29 | 30 | Quaternion::Quaternion(const float w, const float x, const float y, const float z) { 31 | q[0] = w; 32 | q[1] = x; 33 | q[2] = y; 34 | q[3] = z; 35 | } 36 | 37 | Quaternion Quaternion::getConjugate(void) const { 38 | Quaternion conjugate; 39 | conjugate.q[0] = q[0]; 40 | conjugate.q[1] = -q[1]; 41 | conjugate.q[2] = -q[2]; 42 | conjugate.q[3] = -q[3]; 43 | return conjugate; 44 | } 45 | 46 | EulerAnglesStruct Quaternion::getEulerAngles(void) const { 47 | EulerAnglesStruct eulerAnglesStruct; 48 | eulerAnglesStruct.roll = radiansToDegrees(atan2(2.0f * (q[2] * q[3] - q[0] * q[1]), 2.0f * q[0] * q[0] - 1.0f + 2.0f * q[3] * q[3])); 49 | eulerAnglesStruct.pitch = radiansToDegrees(-atan((2.0f * (q[1] * q[3] + q[0] * q[2])) / sqrt(1.0f - pow((2.0f * q[1] * q[3] + 2.0f * q[0] * q[2]), 2.0f)))); 50 | eulerAnglesStruct.yaw = radiansToDegrees(atan2(2.0f * (q[1] * q[2] - q[0] * q[3]), 2.0f * q[0] * q[0] - 1.0f + 2.0f * q[1] * q[1])); 51 | return eulerAnglesStruct; 52 | } 53 | 54 | float Quaternion::radiansToDegrees (float radians) const { 55 | return 57.2957795130823f * radians; 56 | } 57 | 58 | //------------------------------------------------------------------------------ 59 | // End of file 60 | -------------------------------------------------------------------------------- /x_IMU_Arduino_Example/Quaternion.h: -------------------------------------------------------------------------------- 1 | /* 2 | Quaternion.h 3 | Author: Seb Madgwick 4 | 5 | C++ library for basic usage of quaternions. 6 | See: http://www.x-io.co.uk/quaternions/ 7 | */ 8 | 9 | #ifndef Quaternion_h 10 | #define Quaternion_h 11 | 12 | //------------------------------------------------------------------------------ 13 | // Definitions 14 | 15 | typedef struct { 16 | float roll; /* rotation around x axis in degrees */ 17 | float pitch; /* rotation around y axis in degrees */ 18 | float yaw; /* rotation around z axis in degrees */ 19 | } EulerAnglesStruct; 20 | 21 | //------------------------------------------------------------------------------ 22 | // Class declaration 23 | 24 | class Quaternion { 25 | public: 26 | Quaternion(void); 27 | Quaternion(const float w, const float x, const float y, const float z); 28 | Quaternion getConjugate(void) const; 29 | EulerAnglesStruct getEulerAngles(void) const; 30 | 31 | private: 32 | float q[4]; 33 | float radiansToDegrees (float radians) const; 34 | }; 35 | 36 | #endif 37 | 38 | //------------------------------------------------------------------------------ 39 | // End of file 40 | -------------------------------------------------------------------------------- /x_IMU_Arduino_Example/XimuReceiver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | XimuReceiver.cpp 3 | Author: Seb Madgwick 4 | 5 | C++ library for receiving data from the x-IMU. Current implementation 6 | supports only a few packet types. 7 | 8 | See x_IMU_Arduino_Example.ino for example usage. 9 | */ 10 | 11 | //------------------------------------------------------------------------------ 12 | // Includes 13 | 14 | #include "XimuReceiver.h" 15 | 16 | //------------------------------------------------------------------------------ 17 | // Definitions 18 | 19 | enum PacketHeaders { 20 | PKT_ERROR, 21 | PKT_COMMAND, 22 | PKT_READ_REGISTER, 23 | PKT_WRITE_REGISTER, 24 | PKT_READ_DATE_TIME, 25 | PKT_WRITE_DATE_TIME, 26 | PKT_RAW_BATTERY_AND_THERMOMETER_DATA, 27 | PKT_CAL_BATTERY_AND_THERMOMETER_DATA, 28 | PKT_RAW_INERTIAL_AND_MAGNETIC_DATA, 29 | PKT_CAL_INERTIAL_AND_MAGNETIC_DATA, 30 | PKT_QUATERNION_DATA, 31 | PKT_DIGITAL_IO_DATA, 32 | PKT_RAW_ANALOGUE_INPUT_DATA, 33 | PKT_CAL_ANALOGUE_INPUT_DATA, 34 | PKT_PWM_OUTPUT_DATA, 35 | PKT_RAW_DXL345_BUS_DATA, 36 | PKT_CAL_DXL345_BUS_DATA, 37 | }; 38 | 39 | enum PacketLengths { 40 | LEN_ERROR = 4, 41 | LEN_COMMAND = 6, 42 | LEN_READ_REGISTER = 4, 43 | LEN_WRITE_REGISTER = 8, 44 | LEN_READ_DATE_TIME = 2, 45 | LEN_WRITE_DATE_TIME = 8, 46 | LEN_RAW_BATTERY_AND_THERMOMETER_DATA = 6, 47 | LEN_CAL_BATTERY_AND_THERMOMETER_DATA = 6, 48 | LEN_RAW_INERTIAL_AND_MAGNETIC_DATA = 20, 49 | LEN_CAL_INERTIAL_AND_MAGNETIC_DATA = 20, 50 | LEN_QUATERNION_DATA = 10, 51 | LEN_DIGITAL_IO_DATA = 4, 52 | LEN_RAW_ANALOGUE_INPUT_DATA = 18, 53 | LEN_CAL_ANALOGUE_INPUT_DATA = 18, 54 | LEN_PWM_OUTPUT_DATA = 10, 55 | LEN_RAW_DXL345_BUS_DATA = 26, 56 | LEN_CAL_DXL345_BUS_DATA = 26, 57 | }; 58 | 59 | 60 | typedef enum { 61 | Q_CALIBRATED_BATTERY = 12, 62 | Q_CALIBRATED_THERMOEMTER = 8, 63 | Q_CALIBRATED_GYROSCOPE = 4, 64 | Q_CALIBRATED_ACCELEROEMETER = 11, 65 | Q_CALIBRATED_MAGNETOMETER = 11, 66 | Q_QUATERNION = 15, 67 | Q_BATTERY_SENSITIVITY = 5, 68 | Q_BATTERY_BIAS = 8, 69 | Q_THERMOMETER_SENSITIVITY = 6, 70 | Q_THERMOMETER_BIAS = 0, 71 | Q_GYROSCOPE_SENSITIVITY = 7, 72 | Q_GYROSCOPE_SAMPLED_200DPS = 0, 73 | Q_GYROSCOPE_BIAS_AT_25DEGC = 3, 74 | Q_GYROSCOPE_BIAS_TEMP_SENSITIVITY = 11, 75 | Q_GYROSCOPE_SAMPLED_BIAS = 3, 76 | Q_ACCELEROMETER_SENSITIVITY = 4, 77 | Q_ACCELEROMETER_BIAS = 8, 78 | Q_ACCELEROMETER_Sampled1g = 4, 79 | Q_MAGNETOMETER_SENSITIVITY = 4, 80 | Q_MAGNETOMETER_BIAS = 8, 81 | Q_MAGNETOMETER_HARD_IRON_BIAS = 11, 82 | Q_ALGORITHM_KP = 11, 83 | Q_ALGORITHM_KI = 15, 84 | Q_ALGORITHM_INIT_KP = 11, 85 | Q_ALGORITHM_INIT_PERIOD = 11, 86 | Q_CALIBRATED_ANALOGUE_INPUT = 12, 87 | Q_ANALOGUE_INPUT_SENSITIVITY = 4, 88 | Q_ANALOGUE_INPUT_BIAS = 8, 89 | Q_CALIRBATED_ADXL345 = 10, 90 | Q_ADXL345_BUS_SENSITIVITY = 6, 91 | Q_ADXL345_BUS_BIAS = 8, 92 | } FixedQ; 93 | 94 | //------------------------------------------------------------------------------ 95 | // Variables 96 | 97 | // Serial stream decoding 98 | unsigned char buf[256]; 99 | unsigned char bufIndex = 0; 100 | 101 | // Decoded data 102 | BattAndThermStruct battAndThermStruct = { 0.0f, 0.0f }; 103 | InertialAndMagStruct inertialAndMagStruct = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; 104 | QuaternionStruct quaternionStruct = { 1.0f, 0.0f, 0.0f, 0.0f }; 105 | 106 | // Data ready flags 107 | bool battAndThermGetReady = false; 108 | bool inertialAndMagGetReady = false; 109 | bool quaternionGetReady = false; 110 | 111 | //------------------------------------------------------------------------------ 112 | // Methods 113 | 114 | XimuReceiver::XimuReceiver() { 115 | } 116 | 117 | ErrorCode XimuReceiver::processNewChar(unsigned char c) { 118 | 119 | // Add new byte to buffer 120 | buf[bufIndex++] = c; 121 | 122 | // Process receive buffer if framing char received 123 | if(c & 0x80) { 124 | 125 | // Calculate packet size 126 | int packetSize = bufIndex - 1 - ((bufIndex - 1) >> 3); 127 | bufIndex = 0; //reset index 128 | 129 | // Extract packet (truncate to discard all msb) 130 | unsigned char packet[256]; 131 | packet[0] = (buf[0 ] << 1) | (buf[1 ] >> 6); 132 | packet[1] = (buf[1 ] << 2) | (buf[2 ] >> 5); 133 | packet[2] = (buf[2 ] << 3) | (buf[3 ] >> 4); 134 | packet[3] = (buf[3 ] << 4) | (buf[4 ] >> 3); 135 | packet[4] = (buf[4 ] << 5) | (buf[5 ] >> 2); 136 | packet[5] = (buf[5 ] << 6) | (buf[6 ] >> 1); 137 | packet[6] = (buf[6 ] << 7) | (buf[7 ] >> 0); 138 | packet[7] = (buf[8 ] << 1) | (buf[9 ] >> 6); 139 | packet[8] = (buf[9 ] << 2) | (buf[10] >> 5); 140 | packet[9] = (buf[10] << 3) | (buf[11] >> 4); 141 | packet[10] = (buf[11] << 4) | (buf[12] >> 3); 142 | packet[11] = (buf[12] << 5) | (buf[13] >> 2); 143 | packet[12] = (buf[13] << 6) | (buf[14] >> 1); 144 | packet[13] = (buf[14] << 7) | (buf[15] >> 0); 145 | packet[14] = (buf[16] << 1) | (buf[17] >> 6); 146 | packet[15] = (buf[17] << 2) | (buf[18] >> 5); 147 | packet[16] = (buf[18] << 3) | (buf[19] >> 4); 148 | packet[17] = (buf[19] << 4) | (buf[20] >> 3); 149 | packet[18] = (buf[20] << 5) | (buf[21] >> 2); 150 | packet[19] = (buf[21] << 6) | (buf[22] >> 1); 151 | packet[20] = (buf[22] << 7) | (buf[23] >> 0); 152 | packet[21] = (buf[24] << 1) | (buf[25] >> 6); 153 | packet[22] = (buf[25] << 2) | (buf[26] >> 5); 154 | packet[23] = (buf[26] << 3) | (buf[27] >> 4); 155 | packet[24] = (buf[27] << 4) | (buf[28] >> 3); 156 | packet[25] = (buf[28] << 5) | (buf[29] >> 2); 157 | packet[26] = (buf[29] << 6) | (buf[30] >> 1); 158 | packet[27] = (buf[30] << 7) | (buf[31] >> 0); 159 | 160 | /* 161 | TODO: Verify checksum here, if fail then return ERR_INVALID_CHECKSUM; 162 | */ 163 | 164 | // Interpret packet according to header 165 | switch(packet[0]) { 166 | 167 | case PKT_CAL_BATTERY_AND_THERMOMETER_DATA: 168 | if(packetSize != LEN_CAL_BATTERY_AND_THERMOMETER_DATA) { 169 | return ERR_INVALID_NUM_BYTES_FOR_PACKET_HEADER; 170 | } 171 | battAndThermStruct.battery = fixedToFloat(concat(packet[1], packet[2]), Q_CALIBRATED_BATTERY); 172 | battAndThermStruct.thermometer = fixedToFloat(concat(packet[3], packet[4]), Q_CALIBRATED_THERMOEMTER); 173 | battAndThermGetReady = true; 174 | break; 175 | 176 | case(PKT_CAL_INERTIAL_AND_MAGNETIC_DATA): 177 | if(packetSize != LEN_CAL_INERTIAL_AND_MAGNETIC_DATA) { 178 | return ERR_INVALID_NUM_BYTES_FOR_PACKET_HEADER; 179 | } 180 | inertialAndMagStruct.gyrX = fixedToFloat(concat(packet[1], packet[2]), Q_CALIBRATED_GYROSCOPE); 181 | inertialAndMagStruct.gyrY = fixedToFloat(concat(packet[3], packet[4]), Q_CALIBRATED_GYROSCOPE); 182 | inertialAndMagStruct.gyrZ = fixedToFloat(concat(packet[5], packet[6]), Q_CALIBRATED_GYROSCOPE); 183 | inertialAndMagStruct.accX = fixedToFloat(concat(packet[7], packet[8]), Q_CALIBRATED_ACCELEROEMETER); 184 | inertialAndMagStruct.accY = fixedToFloat(concat(packet[9], packet[10]), Q_CALIBRATED_ACCELEROEMETER); 185 | inertialAndMagStruct.accZ = fixedToFloat(concat(packet[11], packet[12]), Q_CALIBRATED_ACCELEROEMETER); 186 | inertialAndMagStruct.magX = fixedToFloat(concat(packet[13], packet[14]), Q_CALIBRATED_MAGNETOMETER); 187 | inertialAndMagStruct.magY = fixedToFloat(concat(packet[15], packet[16]), Q_CALIBRATED_MAGNETOMETER); 188 | inertialAndMagStruct.magZ = fixedToFloat(concat(packet[17], packet[18]), Q_CALIBRATED_MAGNETOMETER); 189 | inertialAndMagGetReady = true; 190 | break; 191 | 192 | case(PKT_QUATERNION_DATA): 193 | if(packetSize != LEN_QUATERNION_DATA) { 194 | return ERR_INVALID_NUM_BYTES_FOR_PACKET_HEADER; 195 | } 196 | quaternionStruct.w = fixedToFloat(concat(packet[1], packet[2]), Q_QUATERNION); 197 | quaternionStruct.x = fixedToFloat(concat(packet[3], packet[4]), Q_QUATERNION); 198 | quaternionStruct.y = fixedToFloat(concat(packet[5], packet[6]), Q_QUATERNION); 199 | quaternionStruct.z = fixedToFloat(concat(packet[7], packet[8]), Q_QUATERNION); 200 | quaternionGetReady = true; 201 | break; 202 | 203 | default: 204 | break; 205 | } 206 | } 207 | return ERR_NO_ERROR; 208 | } 209 | 210 | float XimuReceiver::fixedToFloat(const short fixed, const unsigned char q) const { 211 | return (float)fixed / (float)(1 << q); 212 | } 213 | 214 | unsigned short XimuReceiver::concat(const unsigned char msb, const unsigned char lsb) const { 215 | return ((unsigned short)msb << 8) | (unsigned short)lsb; 216 | } 217 | 218 | bool XimuReceiver::isBattAndThermGetReady(void) const { 219 | return battAndThermGetReady; 220 | } 221 | 222 | bool XimuReceiver::isInertialAndMagGetReady(void) const { 223 | return inertialAndMagGetReady; 224 | } 225 | 226 | bool XimuReceiver::isQuaternionGetReady(void) const { 227 | return quaternionGetReady; 228 | } 229 | 230 | BattAndThermStruct XimuReceiver::getBattAndTherm(void) { 231 | battAndThermGetReady = false; 232 | return battAndThermStruct; 233 | } 234 | 235 | InertialAndMagStruct XimuReceiver::getInertialAndMag(void) { 236 | inertialAndMagGetReady = false; 237 | return inertialAndMagStruct; 238 | } 239 | 240 | QuaternionStruct XimuReceiver::getQuaternion(void) { 241 | quaternionGetReady = false; 242 | return quaternionStruct; 243 | } 244 | 245 | //------------------------------------------------------------------------------ 246 | // End of file -------------------------------------------------------------------------------- /x_IMU_Arduino_Example/XimuReceiver.h: -------------------------------------------------------------------------------- 1 | /* 2 | XimuReceiver.h 3 | Author: Seb Madgwick 4 | 5 | C++ library for receiving data from the x-IMU. Current implementation 6 | supports only a few packet types. 7 | 8 | See x_IMU_Arduino_Example.ino for example usage. 9 | */ 10 | 11 | #ifndef XimuReceiver_h 12 | #define XimuReceiver_h 13 | 14 | //------------------------------------------------------------------------------ 15 | // Definitions 16 | 17 | typedef enum { 18 | ERR_NO_ERROR, 19 | ERR_FACTORY_RESET_FAILED, 20 | ERR_LOW_BATTERY, 21 | ERR_USB_RECEIVE_BUFFER_OVERRUN, 22 | ERR_USB_TRANSMIT_BUFFER_OVERRUN, 23 | ERR_BLUETOOTH_RECEIVE_BUFFER_OVERRUN, 24 | ERR_BLUETOOTH_TRANSMIT_BUFFER_OVERRUN, 25 | ERR_SD_CARD_WRITE_BUFFER_OVERRUN, 26 | ERR_TOO_FEW_BYTES_IN_PACKET, 27 | ERR_TOO_MANY_BYTES_IN_PACKET, 28 | ERR_INVALID_CHECKSUM, 29 | ERR_UNKNOWN_HEADER, 30 | ERR_INVALID_NUM_BYTES_FOR_PACKET_HEADER, 31 | ERR_INVALID_REGISTER_ADDRESS, 32 | ERR_REGISTER_READ_ONLY, 33 | ERR_INVALID_REGSITER_VALUE, 34 | ERR_INVALID_COMMAND, 35 | ERR_GYROSCOPE_AXIS_NOT_AT_200DPS, 36 | ERR_GYROSCOPE_NOT_STATIONARY, 37 | ERR_ACCELEROMETER_AXIS_NOT_AT_1G, 38 | ERR_MMAGNETOMETER_SATURATION, 39 | ERR_INCORRECT_AUXILIARY_PORT_MODE, 40 | ERR_UART_RECEIVE_BUFFER_OVERRUN, 41 | ERR_UART_TRANSMIT_BUFFER_OVERRUN, 42 | } ErrorCode; 43 | 44 | typedef struct { 45 | float battery; /* battery voltage in V */ 46 | float thermometer; /* thermometer in degC */ 47 | } BattAndThermStruct; 48 | 49 | typedef struct { 50 | float gyrX; /* gyroscope x axis in dps */ 51 | float gyrY; /* gyroscope y axis in dps */ 52 | float gyrZ; /* gyroscope z axis in dps */ 53 | float accX; /* accelerometer x axis in g */ 54 | float accY; /* accelerometer y axis in g */ 55 | float accZ; /* accelerometer z axis in g */ 56 | float magX; /* magnetometer x axis in Ga */ 57 | float magY; /* magnetometer y axis in Ga */ 58 | float magZ; /* magnetometer z axis in Ga */ 59 | } InertialAndMagStruct; 60 | 61 | typedef struct { 62 | float w; 63 | float x; 64 | float y; 65 | float z; 66 | } QuaternionStruct; 67 | 68 | //------------------------------------------------------------------------------ 69 | // Class declaration 70 | 71 | class XimuReceiver { 72 | public: 73 | XimuReceiver(void); 74 | ErrorCode processNewChar(unsigned char c); 75 | bool isBattAndThermGetReady(void) const; 76 | bool isInertialAndMagGetReady(void) const; 77 | bool isQuaternionGetReady(void) const; 78 | BattAndThermStruct getBattAndTherm(void); 79 | InertialAndMagStruct getInertialAndMag(void); 80 | QuaternionStruct getQuaternion(void); 81 | 82 | private: 83 | unsigned char buf[256]; 84 | unsigned char bufIndex; 85 | BattAndThermStruct battAndThermStruct; 86 | InertialAndMagStruct inertialAndMagStruct; 87 | QuaternionStruct quaternionStruct; 88 | bool battAndThermGetReady; 89 | bool inertialAndMagGetReady; 90 | bool quaternionGetReady; 91 | float fixedToFloat(const short fixed, const unsigned char q) const; 92 | unsigned short concat(const unsigned char msb, const unsigned char lsb) const; 93 | }; 94 | 95 | #endif 96 | 97 | //------------------------------------------------------------------------------ 98 | // End of file 99 | -------------------------------------------------------------------------------- /x_IMU_Arduino_Example/x_IMU_Arduino_Example.ino: -------------------------------------------------------------------------------- 1 | /* 2 | x_IMU_Arduino_Example.ino 3 | Author: Seb Madgwick 4 | 5 | Example usage of x-IMU C++ library. Also uses the quaternion library to 6 | convert the received quaternion to Euler angles. 7 | 8 | Requires two hardware serial modules: one to receive from the x-IMU and one 9 | to transmit the decoded data to be displayed on computer. 10 | 11 | x-IMU settings: 12 | Auxiliary Port > Auxiliary Port Mode: "UART" 13 | Auxiliary Port > UART > Baud Rate: 115200 14 | Auxiliary Port > UART > Hardware Flow Control: Off 15 | 16 | Hardware connections: 17 | x-IMU GND -> Arduino MEGA GND 18 | x-IMU EXT -> Arduino MEGA 5V 19 | x-IMU AX2 -> Arduino MEGA RX1 20 | 21 | Tested with "arduino-1.0.3" and "Arduino MEGA". 22 | */ 23 | 24 | //------------------------------------------------------------------------------ 25 | // Includes 26 | 27 | #include "Quaternion.h" 28 | #include "XimuReceiver.h" 29 | 30 | //------------------------------------------------------------------------------ 31 | // Variables 32 | 33 | XimuReceiver ximuReceiver; 34 | 35 | //------------------------------------------------------------------------------ 36 | // Functions 37 | 38 | void setup() { 39 | Serial.begin(115200); // for sending data to computer 40 | Serial1.begin(115200); // for receiving data from x-IMU 41 | } 42 | 43 | void loop() { 44 | ErrorCode e = ERR_NO_ERROR; 45 | 46 | // Process recieved data 47 | while(Serial1.available() > 0) { 48 | e = ximuReceiver.processNewChar(Serial1.read()); 49 | } 50 | 51 | // Print error code (receive error) 52 | if(e != ERR_NO_ERROR) { 53 | Serial.print("ERROR: "); 54 | Serial.print(e); 55 | Serial.print("\r"); 56 | } 57 | 58 | // Print battery and thermometer data 59 | if(ximuReceiver.isBattAndThermGetReady()) { 60 | BattAndThermStruct battAndThermStruct = ximuReceiver.getBattAndTherm(); 61 | Serial.print("battery = "); 62 | Serial.print(battAndThermStruct.battery); 63 | Serial.print(", thermometer = "); 64 | Serial.print(battAndThermStruct.thermometer); 65 | Serial.print("\r"); 66 | } 67 | 68 | // Print sensor data 69 | if(ximuReceiver.isInertialAndMagGetReady()) { 70 | InertialAndMagStruct inertialAndMagStruct = ximuReceiver.getInertialAndMag(); 71 | Serial.print("gyrX = "); 72 | Serial.print(inertialAndMagStruct.gyrX); 73 | Serial.print(", gyrY = "); 74 | Serial.print(inertialAndMagStruct.gyrY); 75 | Serial.print(", gyrZ = "); 76 | Serial.print(inertialAndMagStruct.gyrZ); 77 | Serial.print(", accX = "); 78 | Serial.print(inertialAndMagStruct.accX); 79 | Serial.print(", accY = "); 80 | Serial.print(inertialAndMagStruct.accY); 81 | Serial.print(", accZ = "); 82 | Serial.print(inertialAndMagStruct.accZ); 83 | Serial.print(", magX = "); 84 | Serial.print(inertialAndMagStruct.magX); 85 | Serial.print(", magY = "); 86 | Serial.print(inertialAndMagStruct.magY); 87 | Serial.print(", magZ = "); 88 | Serial.print(inertialAndMagStruct.magZ); 89 | Serial.print("\r"); 90 | } 91 | 92 | // Print quaternion data as Euler angles 93 | if(ximuReceiver.isQuaternionGetReady()) { 94 | QuaternionStruct quaternionStruct = ximuReceiver.getQuaternion(); 95 | Quaternion quaternion = Quaternion(quaternionStruct.w, quaternionStruct.x, quaternionStruct.y, quaternionStruct.z); 96 | EulerAnglesStruct eulerAnglesStruct = quaternion.getEulerAngles(); 97 | Serial.print("roll = "); 98 | Serial.print(eulerAnglesStruct.roll); 99 | Serial.print(", pitch = "); 100 | Serial.print(eulerAnglesStruct.pitch); 101 | Serial.print(", yaw = "); 102 | Serial.print(eulerAnglesStruct.yaw); 103 | Serial.print("\r"); 104 | } 105 | } 106 | 107 | //------------------------------------------------------------------------------ 108 | // End of file 109 | --------------------------------------------------------------------------------