Skip to content
Permalink
6c3787288e
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
184 lines (159 sloc) 6.63 KB
#include "AHRSInputIOProcessor.hpp"
/*
* Return Values:
* 0 : No Errors.
* 1 : Serial port does not exist.
* 2 : Some other error occurred.
* 3 : Error getting state.
* 4 : Error setting serial port state
* 5 : Error occured while setting timoemouts.
* 6 : Error occured while trying to send GoToConfig message.
* 7 : Error occured while trying to send SetOutputConfiguration message.
* 8 : Error occured while trying to send GoToMeasurment message.
*/
int AHRSInputIOProcessor::configAHRS()
{
hSerial = CreateFile("COM8", // The COM port to connect to, may have to be changed
GENERIC_READ | GENERIC_WRITE, // depending on what COM port gets selected.
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hSerial == INVALID_HANDLE_VALUE)
{
if(GetLastError() == ERROR_FILE_NOT_FOUND)
{
std::cerr << "Serial port does not exist." << std::endl;
return 1;
}
std::cerr << "Some other error occurred." << std::endl;
return 2;
}
DCB dcb = { 0 };
dcb.DCBlength = sizeof(dcb);
if (!GetCommState(hSerial, &dcb))
{
std::cerr << "Error getting state." << std::endl;
return 3;
}
dcb.BaudRate = CBR_115200; // defualt baud rate of MT
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcb))
{
std::cerr << "Error setting serial port state." << std::endl;
return 4;
}
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hSerial, &timeouts))
{
std::cerr << "Error occured while setting timoemouts." << std::endl;
return 5;
}
std::cout << "Connection established!" << std::endl;
std::cout << "Setting up Config..." << std::endl;
// This is the GoToConfig message, MID 48
// Switch the active state of the device from Measurment State to Config State.
unsigned char wBuff1[] = {0xFA,0xFF,0x30,0x00,0xD1};
DWORD dwBytesWritten = 0; // Number of bytes actually written
if (!WriteFile(hSerial, wBuff1, 6, &dwBytesWritten, NULL))
{
std::cerr << "Error occured while trying to send GoToConfig message." << std::endl;
return 6;
}
// This is the SetOutputConfiguration message, MID 192
// Set the output configuration of the device.
unsigned char wBuff2[] = {0xFA,0xFF,0xC0,0x04,0x20,0x33,0x00,0x00,0xEA};
dwBytesWritten = 0;
if (!WriteFile(hSerial, wBuff2, 10, &dwBytesWritten, NULL))
{
std::cerr << "Error occured while trying to send SetOutputConfiguration message." << std::endl;
return 7;
}
// This is the GoToMeasurment message, MID 16
// Switch the active state of the device from Config State to Measurment State.
unsigned char wBuff3[] = {0xFA,0xFF,0x10,0x00,0xF1};
dwBytesWritten = 0;
if (!WriteFile(hSerial, wBuff3, 6, &dwBytesWritten, NULL))
{
std::cerr << "Error occured while trying to send GoToMeasurment message." << std::endl;
return 8;
}
configured = true;
return 0;
}
bool AHRSInputIOProcessor::loopCondition()
{
return true;
}
void AHRSInputIOProcessor::loop()
{
if (!configured)
configAHRS();
unsigned char szBuff[64 + 1] = {0}; // Buffer size
DWORD dwBytesRead = 0; // Number of bytes actually read
if (!ReadFile(hSerial, szBuff, 64, &dwBytesRead, NULL))
{
std::cerr << "Error occured while trying to read bytes." << std::endl;
}
/* This gets the index of the bytes for the Euler angles in the captured
* buffer (szBuff). First, it finds the first byte of the message (i). Then,
* it finds the 14th index of the message (dataStart). This is where the last
* byte of the roll angle is. This allows me loop backward through each group
* of bytes, since the order needs to be reversed because the AHRS is in Big
* Endian.
* i is where the message starts in the buffer.
* dataStart = i + 14, which is where the data we want starts (for Roll).
* To find Pitch and Yaw, we add 8 and 16 respectivly.
*
* MESSAGE STRUCTURE:
* Roll Angle Bytes = RX, Pitch Angle Bytes = PX, Yaw Angle Bytes = YX
* +-------------------------+-------------------------+-------------------------+
* | Roll | Pitch | Yaw |
* +-------------------------+-------------------------+-------------------------+
* | R1 R2 R3 R4 R5 R6 R7 R8 | P1 P2 P3 P4 P5 P6 P7 P8 | Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 |
* +-------------------------+-------------------------+-------------------------+
* ... | 7 8 9 10 11 12 13 14 | 15 16 17 18 19 20 21 22 | 23 24 25 26 27 28 29 30 | ...
* | ^ | ^ | ^ |
* | dataStart| dataStart + 8| dataStart + 16|
* +-------------------------+-------------------------+-------------------------+
*/
int dataStart = -1;
for (int i=0; i < 32; i++)
{
if (szBuff[i] == 0xFA && szBuff[i+1] == 0xFF && szBuff[i+2] == 0x36)
{
dataStart = i + 14;
break;
}
}
unsigned char rollArray[8];
unsigned char pitchArray[8];
unsigned char yawArray[8];
// Puts the bytes for each angle in their own array backwards, since they are sent in big endian
if (dataStart != -1)
{
for (int i = 0; i < 8; i++)
{
rollArray[i] = szBuff[dataStart - i];
pitchArray[i] = szBuff[dataStart - i + 8];
yawArray[i] = szBuff[dataStart - i + 16];
}
}
double doubleRoll = *reinterpret_cast<double* const>(rollArray);
double doublePitch = *reinterpret_cast<double* const>(pitchArray);
double doubleYaw = *reinterpret_cast<double * const>(yawArray);
Attribute attRoll("XSIMUROL", 8, &doubleRoll);
getComms()->sendAttribute(attRoll);
Attribute attPitch("XSIMUPIT", 8, &doublePitch);
getComms()->sendAttribute(attPitch);
Attribute attYaw("XSIMUYAW", 8, &doubleYaw);
getComms()->sendAttribute(attYaw);
}