详见昨天做的测试代码,代码网址:
BWS2000倾角传感器c++测试代码【2】-CSDN博客文章浏览阅读268次,点赞7次,收藏8次。倾角传感器测试与编写思路https://blog.csdn.net/m0_47489229/article/details/135128748
昨天的代码今天打开之后,再进行测试出现了一个问题,就是当移动倾角传感器之后,可以见到传感器显示的数值变化是比实际慢很多的,可以明显看出来。
由于昨天的代码存在相应的时间延迟,不方便后面进行传感器的时间同步。我的思路是搞个多线程
由于倾角传感器存在时间延迟的问题,但是厂家给出的软件之中并不存在时间延迟的问题。所以为了解决这个问题我的想法是创建一个线程,进行实时处理传输的接口信息,对于通信接口进行连接判断。连接的瞬间就进行数据处理。
写个测试案例:
首先创建一个线程,实时监督接口与进行数据处理:
void sensorThread()
{
std::cout << " " << std::endl;
std::cout << "开始采集 " << std::endl;
int i = 0;
while (1)
{
ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL);
auto startTime = std::chrono::high_resolution_clock::now();
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
bool flag1 = false;
int flag;
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i + 1] == 0x10 && dataReceived[i + 2] == 0x00 && dataReceived[i + 3] == 0xFFFFFF84)
{
flag1 = true;
flag = i;
break;
}
}
std::cout << "" << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(4000));
if (flag1 == true)
{
//x轴
// Given hexadecimal values
int hexValues[] = { dataReceived[flag + 5] & 0xFF, dataReceived[flag + 6] & 0xFF, dataReceived[flag + 7] & 0xFF };
int hexValues1[] = { dataReceived[flag + 9] & 0xFF, dataReceived[flag + 10] & 0xFF, dataReceived[flag + 11] & 0xFF };
int numValues = sizeof(hexValues) / sizeof(hexValues[0]);
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << std::hex << hexValues[0];
for (int i = 1; i < numValues; i++) {
ss << "." << std::setw(2) << std::hex << hexValues[i];
}
std::string resultString = ss.str();
std::string inputString = resultString;
std::string outputString;
size_t firstDotIndex = inputString.find('.');
size_t secondDotIndex = inputString.find('.', firstDotIndex + 1);
if (firstDotIndex != std::string::npos && secondDotIndex != std::string::npos) {
outputString = inputString.substr(0, secondDotIndex) + inputString.substr(secondDotIndex + 1);
}
else {
outputString = inputString;
}
double resultDouble = std::stod(outputString);
if (dataReceived[flag + 4] == 0x00)
{
Sensor_Angle_RX0 = resultDouble;
}
else
{
Sensor_Angle_RX0 = -resultDouble;
}
std::cout << "x轴角度" << Sensor_Angle_RX0 << std::endl;
//Y轴
int numValues1 = sizeof(hexValues1) / sizeof(hexValues1[0]);
std::stringstream ss1;
ss1 << std::setfill('0') << std::setw(2) << std::hex << hexValues1[0];
for (int i = 1; i < numValues1; i++) {
ss1 << "." << std::setw(2) << std::hex << hexValues1[i];
}
std::string resultString1 = ss1.str();
std::string inputString1 = resultString1;
std::string outputString1;
size_t firstDotIndex1 = inputString1.find('.');
size_t secondDotIndex1 = inputString1.find('.', firstDotIndex1 + 1);
if (firstDotIndex1 != std::string::npos && secondDotIndex1 != std::string::npos) {
outputString1 = inputString1.substr(0, secondDotIndex1) + inputString1.substr(secondDotIndex1 + 1);
}
else {
outputString1 = inputString1;
}
double resultDouble1 = std::stod(outputString1);
if (dataReceived[flag + 8] == 0x00)
{
Sensor_Angle_RY0 = resultDouble1;
}
else
{
Sensor_Angle_RY0 = -resultDouble1;
}
std::cout << "y轴: " << Sensor_Angle_RY0 << std::endl;
// 计算执行代码所花费的时间
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(endTime - startTime);
// 计算需要延迟的时间
int delay = interval - duration.count();
//std::cout << delay << std::endl;
if (delay == interval)
{
std::cout << "频率正确" << std::endl;
}
else if (delay > 0) {
// 延迟执行
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
std::cout << "频率正确" << std::endl;
}
else if (delay < 0)
{
std::cout << "时间不够:(ms)***************************************:" << delay << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(200000000));
}
}
}
//std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
在主函数函数之中对于接口进行初步的数据处理:
int main()
{
// 创建传感器数据读取线程
std::thread sensorThreadObj(sensorThread);
//CString str123 = strValue1;
//CString strA("COM10");
//CString strB("\\\\.\\");
//strB += strA;
//const char* portName = strB.GetString();
//strB.ReleaseBuffer();
//strA.ReleaseBuffer();
wchar_t portName[] = L"\\\\.\\COM10"; // Note the 'L' before the string
hSerial = CreateFile("\\\\.\\COM10", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
std::cout << "Serial port not available." << std::endl;
}
return 1;
}
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
std::cout << "Error getting serial port state." << std::endl;
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
std::cout << "Error setting serial port state." << std::endl;
CloseHandle(hSerial);
return 1;
}
timeouts.ReadIntervalTimeout = 500;
timeouts.ReadTotalTimeoutConstant = 500;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.WriteTotalTimeoutConstant = 500;
timeouts.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(hSerial, &timeouts))
{
std::cout << "Error setting timeouts." << std::endl;
CloseHandle(hSerial);
return 1;
}
//默认为9600的时候,进行对话模式
char command_R4[] = { 0x77, 0x05, 0x00, 0x0C, 0x00, 0x11 };
if (!WriteFile(hSerial, command_R4, sizeof(command_R4), &bytesWritten4, NULL)) {
std::cout << "第一次9600的对话模式配置失败" << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "第一次9600的对话模式数据读取失败." << std::endl;
CloseHandle(hSerial);
return 1;
}
std::cout << "第一次初始波特率:" << dcbSerialParams.BaudRate << std::endl;
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
bool exists = false; // 标志位,记录元素是否存在
int falsecount = 0;
// 循环遍历数组
while (!exists) {
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i + 3] == 0xFFFFFF8C) {
exists = true; // 元素存在,设置标志位为true
std::cout << falsecount << std::endl;
std::cout << "应答模式配置成功!" << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(400000));
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
falsecount++;
if (falsecount >= 2)//说明原有配置是115200波特率
{
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
std::cout << "Error setting serial port state." << std::endl;
CloseHandle(hSerial);
return 1;
}
timeouts.ReadIntervalTimeout = 500;
timeouts.ReadTotalTimeoutConstant = 500;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.WriteTotalTimeoutConstant = 500;
timeouts.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(hSerial, &timeouts))
{
std::cout << "Error setting timeouts." << std::endl;
CloseHandle(hSerial);
return 1;
}
}
if (!WriteFile(hSerial, command_R4, sizeof(command_R4), &bytesWritten4, NULL)) {
std::cout << "115200的对话模式配置失败." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "115200的对话模式回复失败." << std::endl;
CloseHandle(hSerial);
return 1;
}
}
}
//设置频率为115200
char command_R1[] = { 0x77, 0x05, 0x00, 0x0B, 0x04, 0x14 };//115200
if (!WriteFile(hSerial, command_R1, sizeof(command_R1), &bytesWritten1, NULL))
{
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL))
{
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
exists = false;
while (!exists)
{
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i + 3] == 0xFFFFFF8B) {//设置成功
exists = true; // 元素存在,设置标志位为true
std::cout << "115200波特率配置成功!" << std::endl;
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
if (!WriteFile(hSerial, command_R1, sizeof(command_R1), &bytesWritten1, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
std::cout << "重复配置115200波特率" << std::endl;
// 可以在这里添加需要执行的语句
std::this_thread::sleep_for(std::chrono::milliseconds(4000));
}
}
//00-11:应答模式 05-50Hz 04-25Hz
//06-100 05-50 04-25
char command_R3[] = { 0x77, 0x05, 0x00, 0x0C, 0x03, 0x14 };//50Hz
if (!WriteFile(hSerial, command_R3, sizeof(command_R3), &bytesWritten3, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
exists = false;
while (!exists) {
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i+3] == 0xFFFFFF8C) {//设置成功
exists = true; // 元素存在,设置标志位为true
std::cout << "50Hz配置成功!" << std::endl;
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
if (!WriteFile(hSerial, command_R3, sizeof(command_R3), &bytesWritten3, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
std::cout << "元素不存在,继续执行某条语句..." << std::endl;
// 可以在这里添加需要执行的语句
}
}
//
sensorThreadObj.join();
return 0;
}
完整代码段:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
HANDLE hSerial;
DCB dcbSerialParams = { 0 };
COMMTIMEOUTS timeouts = { 0 };
DWORD bytesRead, bytesRead1, bytesWritten, bytesWritten1, bytesWritten2, bytesWritten3, bytesWritten4, bytesWritten5, response_R1;
char command_R[] = { 0x77, 0x04, 0x00, 0x04, 0x08 };//读X、Y轴角度 发送命令: 77 04 00 04 08
char response_R[34];
double Sensor_Angle_RX0;
double Sensor_Angle_RY0;
char dataReceived[34];
const int interval = 100;
void sensorThread()
{
std::cout << " " << std::endl;
std::cout << "开始采集 " << std::endl;
int i = 0;
while (1)
{
auto startTime = std::chrono::high_resolution_clock::now();
ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL);
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
bool flag1 = false;
int flag;
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i + 1] == 0x10 && dataReceived[i + 2] == 0x00 && dataReceived[i + 3] == 0xFFFFFF84)
{
flag1 = true;
flag = i;
break;
}
}
std::cout << "" << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(4000));
if (flag1 == true)
{
//x轴
// Given hexadecimal values
int hexValues[] = { dataReceived[flag + 5] & 0xFF, dataReceived[flag + 6] & 0xFF, dataReceived[flag + 7] & 0xFF };
int hexValues1[] = { dataReceived[flag + 9] & 0xFF, dataReceived[flag + 10] & 0xFF, dataReceived[flag + 11] & 0xFF };
int numValues = sizeof(hexValues) / sizeof(hexValues[0]);
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << std::hex << hexValues[0];
for (int i = 1; i < numValues; i++) {
ss << "." << std::setw(2) << std::hex << hexValues[i];
}
std::string resultString = ss.str();
std::string inputString = resultString;
std::string outputString;
size_t firstDotIndex = inputString.find('.');
size_t secondDotIndex = inputString.find('.', firstDotIndex + 1);
if (firstDotIndex != std::string::npos && secondDotIndex != std::string::npos) {
outputString = inputString.substr(0, secondDotIndex) + inputString.substr(secondDotIndex + 1);
}
else {
outputString = inputString;
}
double resultDouble = std::stod(outputString);
if (dataReceived[flag + 4] == 0x00)
{
Sensor_Angle_RX0 = resultDouble;
}
else
{
Sensor_Angle_RX0 = -resultDouble;
}
std::cout << "x轴角度" << Sensor_Angle_RX0 << std::endl;
//Y轴
int numValues1 = sizeof(hexValues1) / sizeof(hexValues1[0]);
std::stringstream ss1;
ss1 << std::setfill('0') << std::setw(2) << std::hex << hexValues1[0];
for (int i = 1; i < numValues1; i++) {
ss1 << "." << std::setw(2) << std::hex << hexValues1[i];
}
std::string resultString1 = ss1.str();
std::string inputString1 = resultString1;
std::string outputString1;
size_t firstDotIndex1 = inputString1.find('.');
size_t secondDotIndex1 = inputString1.find('.', firstDotIndex1 + 1);
if (firstDotIndex1 != std::string::npos && secondDotIndex1 != std::string::npos) {
outputString1 = inputString1.substr(0, secondDotIndex1) + inputString1.substr(secondDotIndex1 + 1);
}
else {
outputString1 = inputString1;
}
double resultDouble1 = std::stod(outputString1);
if (dataReceived[flag + 8] == 0x00)
{
Sensor_Angle_RY0 = resultDouble1;
}
else
{
Sensor_Angle_RY0 = -resultDouble1;
}
std::cout << "y轴: " << Sensor_Angle_RY0 << std::endl;
// 计算执行代码所花费的时间
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(endTime - startTime);
// 计算需要延迟的时间
int delay = interval - duration.count();
//std::cout << delay << std::endl;
if (delay == interval)
{
std::cout << "频率正确" << std::endl;
}
else if (delay > 0) {
// 延迟执行
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
std::cout << "频率正确" << std::endl;
}
else if (delay < 0)
{
std::cout << "时间不够:(ms)***************************************:" << delay << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(200000000));
}
}
}
//std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
int main()
{
// 创建传感器数据读取线程
std::thread sensorThreadObj(sensorThread);
//CString str123 = strValue1;
//CString strA("COM10");
//CString strB("\\\\.\\");
//strB += strA;
//const char* portName = strB.GetString();
//strB.ReleaseBuffer();
//strA.ReleaseBuffer();
wchar_t portName[] = L"\\\\.\\COM10"; // Note the 'L' before the string
hSerial = CreateFile("\\\\.\\COM10", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
std::cout << "Serial port not available." << std::endl;
}
return 1;
}
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
std::cout << "Error getting serial port state." << std::endl;
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
std::cout << "Error setting serial port state." << std::endl;
CloseHandle(hSerial);
return 1;
}
timeouts.ReadIntervalTimeout = 500;
timeouts.ReadTotalTimeoutConstant = 500;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.WriteTotalTimeoutConstant = 500;
timeouts.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(hSerial, &timeouts))
{
std::cout << "Error setting timeouts." << std::endl;
CloseHandle(hSerial);
return 1;
}
//默认为9600的时候,进行对话模式
char command_R4[] = { 0x77, 0x05, 0x00, 0x0C, 0x00, 0x11 };
if (!WriteFile(hSerial, command_R4, sizeof(command_R4), &bytesWritten4, NULL)) {
std::cout << "第一次9600的对话模式配置失败" << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "第一次9600的对话模式数据读取失败." << std::endl;
CloseHandle(hSerial);
return 1;
}
std::cout << "第一次初始波特率:" << dcbSerialParams.BaudRate << std::endl;
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
bool exists = false; // 标志位,记录元素是否存在
int falsecount = 0;
// 循环遍历数组
while (!exists) {
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i + 3] == 0xFFFFFF8C) {
exists = true; // 元素存在,设置标志位为true
std::cout << falsecount << std::endl;
std::cout << "应答模式配置成功!" << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(400000));
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
falsecount++;
if (falsecount >= 2)//说明原有配置是115200波特率
{
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
std::cout << "Error setting serial port state." << std::endl;
CloseHandle(hSerial);
return 1;
}
timeouts.ReadIntervalTimeout = 500;
timeouts.ReadTotalTimeoutConstant = 500;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.WriteTotalTimeoutConstant = 500;
timeouts.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(hSerial, &timeouts))
{
std::cout << "Error setting timeouts." << std::endl;
CloseHandle(hSerial);
return 1;
}
}
if (!WriteFile(hSerial, command_R4, sizeof(command_R4), &bytesWritten4, NULL)) {
std::cout << "115200的对话模式配置失败." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "115200的对话模式回复失败." << std::endl;
CloseHandle(hSerial);
return 1;
}
}
}
//设置频率为115200
char command_R1[] = { 0x77, 0x05, 0x00, 0x0B, 0x04, 0x14 };//115200
if (!WriteFile(hSerial, command_R1, sizeof(command_R1), &bytesWritten1, NULL))
{
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL))
{
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
exists = false;
while (!exists)
{
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i + 3] == 0xFFFFFF8B) {//设置成功
exists = true; // 元素存在,设置标志位为true
std::cout << "115200波特率配置成功!" << std::endl;
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
if (!WriteFile(hSerial, command_R1, sizeof(command_R1), &bytesWritten1, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
std::cout << "重复配置115200波特率" << std::endl;
// 可以在这里添加需要执行的语句
std::this_thread::sleep_for(std::chrono::milliseconds(4000));
}
}
//00-11:应答模式 05-50Hz 04-25Hz
//06-100 05-50 04-25
char command_R3[] = { 0x77, 0x05, 0x00, 0x0C, 0x03, 0x14 };//50Hz
if (!WriteFile(hSerial, command_R3, sizeof(command_R3), &bytesWritten3, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
exists = false;
while (!exists) {
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
for (int i = 0; i < sizeof(dataReceived); i++) {
if (dataReceived[i] == 0x77 && dataReceived[i+3] == 0xFFFFFF8C) {//设置成功
exists = true; // 元素存在,设置标志位为true
std::cout << "50Hz配置成功!" << std::endl;
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
if (!WriteFile(hSerial, command_R3, sizeof(command_R3), &bytesWritten3, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
if (!ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial);
return 1;
}
std::cout << "元素不存在,继续执行某条语句..." << std::endl;
// 可以在这里添加需要执行的语句
}
}
//
sensorThreadObj.join();
return 0;
}
我不知道为啥,程序可以正常运行,但是时间过长的情况下,偶尔会出现下面的这个问题(如果哪个大佬要是知道可以告诉我一下,学习学习):
前面已经完成了对于倾角传感器初步的设定与时间延缓问题的补偿,下一步需要对于倾角传感器的界面进行设计了。不写那么复杂,直接就是连接之后实时显示。
其中,Combo Box的ID我设置为IDC_COMBO1。x轴、y轴控件之间添加变量为m_x11、x_x22。可以见到在.h文件之中生成绑定变量。
在.h之中添加自己想要的变量。
HANDLE hSerial_L;
DCB dcbSerialParams_L = { 0 };
COMMTIMEOUTS timeouts_L = { 0 };
DWORD bytesRead_L, bytesRead_L1, bytesWritten, bytesWritten1, bytesWritten2, bytesWritten3, bytesWritten4, bytesWritten5, response_R1;
char dataReceived[34];
const int interval = 100;
char dataReceived_L[23];
在.cpp的初始化函数OnInit之中添加线程监控与按钮初始化
AfxBeginThread(ReadCom1Thread, this);
CComboBox* pCombo_S_L = (CComboBox*)GetDlgItem(IDC_COMBO1);
pCombo_S_L->AddString(_T("断开连接"));
pCombo_S_L->AddString(_T("COM1"));
pCombo_S_L->AddString(_T("COM2"));
pCombo_S_L->AddString(_T("COM3"));
pCombo_S_L->AddString(_T("COM4"));
pCombo_S_L->AddString(_T("COM5"));
pCombo_S_L->AddString(_T("COM6"));
pCombo_S_L->AddString(_T("COM7"));
pCombo_S_L->AddString(_T("COM8"));
pCombo_S_L->AddString(_T("COM9"));
pCombo_S_L->AddString(_T("COM10"));
pCombo_S_L->AddString(_T("COM11"));
pCombo_S_L->AddString(_T("COM12"));
pCombo_S_L->AddString(_T("COM13"));
pCombo_S_L->AddString(_T("COM14"));
pCombo_S_L->AddString(_T("COM15"));
pCombo_S_L->AddString(_T("COM16"));
pCombo_S_L->AddString(_T("COM17"));
pCombo_S_L->AddString(_T("COM18"));
pCombo_S_L->AddString(_T("COM19"));
pCombo_S_L->AddString(_T("COM20"));
pCombo_S_L->SetCurSel(0);
线程函数如下所示:
volatile bool bThreadRunning1 = false; // 线程1运行标志
//UINT CMFCApplication1Dlg::ReadCom1Thread(LPVOID pParam)
UINT ReadCom1Thread(LPVOID pParam)
{
CMFCApplication1Dlg* pDlg = (CMFCApplication1Dlg*)pParam;
CString strText;
bThreadRunning1 = true;
double LX, LY;
std::cout << " " << std::endl;
std::cout << "开始采集 " << std::endl;
int i = 0;
while (1)
{
auto startTime = std::chrono::high_resolution_clock::now();
ReadFile(pDlg->hSerial_L, pDlg->dataReceived, sizeof(pDlg->dataReceived), &(pDlg->bytesRead_L), NULL);
for (int i = 0; i < sizeof(pDlg->dataReceived); i++) {
printf("%02X ", pDlg->dataReceived[i]);
}
bool flag1 = false;
int flag;
for (int i = 0; i < sizeof(pDlg->dataReceived); i++) {
if (pDlg->dataReceived[i] == 0x77 && pDlg->dataReceived[i + 1] == 0x10 && pDlg->dataReceived[i + 2] == 0x00 && pDlg->dataReceived[i + 3] == 0xFFFFFF84)
{
flag1 = true;
flag = i;
break;
}
}
std::cout << "" << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(4000));
if (flag1 == true)
{
//x轴
// Given hexadecimal values
int hexValues[] = { pDlg->dataReceived[flag + 5] & 0xFF, pDlg->dataReceived[flag + 6] & 0xFF, pDlg->dataReceived[flag + 7] & 0xFF };
int hexValues1[] = { pDlg->dataReceived[flag + 9] & 0xFF, pDlg->dataReceived[flag + 10] & 0xFF, pDlg->dataReceived[flag + 11] & 0xFF };
int numValues = sizeof(hexValues) / sizeof(hexValues[0]);
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << std::hex << hexValues[0];
for (int i = 1; i < numValues; i++) {
ss << "." << std::setw(2) << std::hex << hexValues[i];
}
std::string resultString = ss.str();
std::string inputString = resultString;
std::string outputString;
size_t firstDotIndex = inputString.find('.');
size_t secondDotIndex = inputString.find('.', firstDotIndex + 1);
if (firstDotIndex != std::string::npos && secondDotIndex != std::string::npos) {
outputString = inputString.substr(0, secondDotIndex) + inputString.substr(secondDotIndex + 1);
}
else {
outputString = inputString;
}
double resultDouble = std::stod(outputString);
if (pDlg->dataReceived[flag + 4] == 0x00)
{
LX = resultDouble;
}
else
{
LX = -resultDouble;
}
//Y轴
int numValues1 = sizeof(hexValues1) / sizeof(hexValues1[0]);
std::stringstream ss1;
ss1 << std::setfill('0') << std::setw(2) << std::hex << hexValues1[0];
for (int i = 1; i < numValues1; i++) {
ss1 << "." << std::setw(2) << std::hex << hexValues1[i];
}
std::string resultString1 = ss1.str();
std::string inputString1 = resultString1;
std::string outputString1;
size_t firstDotIndex1 = inputString1.find('.');
size_t secondDotIndex1 = inputString1.find('.', firstDotIndex1 + 1);
if (firstDotIndex1 != std::string::npos && secondDotIndex1 != std::string::npos) {
outputString1 = inputString1.substr(0, secondDotIndex1) + inputString1.substr(secondDotIndex1 + 1);
}
else {
outputString1 = inputString1;
}
double resultDouble1 = std::stod(outputString1);
if (pDlg->dataReceived[flag + 8] == 0x00)
{
LY = resultDouble1;
}
else
{
LY = -resultDouble1;
}
CString strValue;
strValue.Format(_T("%.4f°"), LX); // 将 double 值转换成字符串,保留四位小数
pDlg->m_x11.ResetContent();
pDlg->m_x11.AddString(strValue); // 将字符串添加到 ListBox 中
CString strValue1;
strValue1.Format(_T("%.4f°"), LY); // 将 double 值转换成字符串,保留四位小数
pDlg->m_x22.ResetContent();
pDlg->m_x22.AddString(strValue1); // 将字符串添加到 ListBox 中
// 计算执行代码所花费的时间
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(endTime - startTime);
// 计算需要延迟的时间
int delay = pDlg->interval - duration.count();
//std::cout << delay << std::endl;
if (delay == pDlg->interval)
{
std::cout << "频率正确" << std::endl;
}
else if (delay > 0) {
// 延迟执行
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
std::cout << "频率正确" << std::endl;
}
else if (delay < 0)
{
std::cout << "时间不够:(ms)***************************************:" << delay << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(200000000));
}
}
}
//
// 关闭串口1
CloseHandle(pDlg->hSerial_L);
return 0;
}
双击COM口选择控件,添加如下函数
void CMFCApplication1Dlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
// TODO: 在此添加控件通知处理程序代码
CComboBox* pCombo12 = (CComboBox*)GetDlgItem(IDC_COMBO1);
CString strValue1;
pCombo12->GetLBText(pCombo12->GetCurSel(), strValue1);
CString vl11 = strValue1;
CStringA strA(strValue1);
CStringA strB("\\\\.\\");
strB += strA;
const char* portName = strB.GetString();
// 释放 portName 的资源
strB.ReleaseBuffer();
strA.ReleaseBuffer();
CString duankai("断开连接");
if (vl11 == duankai)
{
MessageBox(L"断开与倾角传感器的连接");
}
else
{
CStringW widePortName(portName);
hSerial_L = CreateFile(widePortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSerial_L == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
std::cout << "Serial port not available." << std::endl;
}
}
dcbSerialParams_L.DCBlength = sizeof(dcbSerialParams_L);
if (!GetCommState(hSerial_L, &dcbSerialParams_L)) {
std::cout << "Error getting serial port state." << std::endl;
CloseHandle(hSerial_L);
}
dcbSerialParams_L.BaudRate = CBR_9600;
dcbSerialParams_L.ByteSize = 8;
dcbSerialParams_L.StopBits = ONESTOPBIT;
dcbSerialParams_L.Parity = NOPARITY;
if (!SetCommState(hSerial_L, &dcbSerialParams_L)) {
std::cout << "Error setting serial port state." << std::endl;
CloseHandle(hSerial_L);
}
timeouts_L.ReadIntervalTimeout = 500;
timeouts_L.ReadTotalTimeoutConstant = 500;
timeouts_L.ReadTotalTimeoutMultiplier = 100;
timeouts_L.WriteTotalTimeoutConstant = 500;
timeouts_L.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(hSerial_L, &timeouts_L))
{
std::cout << "Error setting timeouts." << std::endl;
CloseHandle(hSerial_L);
}
//默认为9600的时候,进行对话模式
char command_R4[] = { 0x77, 0x05, 0x00, 0x0C, 0x00, 0x11 };
if (!WriteFile(hSerial_L, command_R4, sizeof(command_R4), &bytesWritten4, NULL)) {
std::cout << "第一次9600的对话模式配置失败" << std::endl;
CloseHandle(hSerial_L);
}
if (!ReadFile(hSerial_L, dataReceived_L, sizeof(dataReceived_L), &bytesRead_L, NULL)) {
std::cout << "第一次9600的对话模式数据读取失败." << std::endl;
CloseHandle(hSerial_L);
}
std::cout << "第一次初始波特率:" << dcbSerialParams_L.BaudRate << std::endl;
for (int i = 0; i < sizeof(dataReceived_L); i++) {
printf("%02X ", dataReceived_L[i]);
}
bool exists = false; // 标志位,记录元素是否存在
int falsecount = 0;
// 循环遍历数组
while (!exists) {
for (int i = 0; i < sizeof(dataReceived_L); i++) {
printf("%02X ", dataReceived_L[i]);
}
for (int i = 0; i < sizeof(dataReceived_L); i++) {
if (dataReceived_L[i] == 0x77 && dataReceived_L[i + 3] == 0xFFFFFF8C) {
exists = true; // 元素存在,设置标志位为true
std::cout << falsecount << std::endl;
std::cout << "应答模式配置成功!" << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(400000));
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
falsecount++;
if (falsecount >= 2)//说明原有配置是115200波特率
{
dcbSerialParams_L.BaudRate = CBR_115200;
dcbSerialParams_L.ByteSize = 8;
dcbSerialParams_L.StopBits = ONESTOPBIT;
dcbSerialParams_L.Parity = NOPARITY;
if (!SetCommState(hSerial_L, &dcbSerialParams_L)) {
std::cout << "Error setting serial port state." << std::endl;
CloseHandle(hSerial_L);
}
timeouts_L.ReadIntervalTimeout = 500;
timeouts_L.ReadTotalTimeoutConstant = 500;
timeouts_L.ReadTotalTimeoutMultiplier = 100;
timeouts_L.WriteTotalTimeoutConstant = 500;
timeouts_L.WriteTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(hSerial_L, &timeouts_L))
{
std::cout << "Error setting timeouts." << std::endl;
CloseHandle(hSerial_L);
}
}
if (!WriteFile(hSerial_L, command_R4, sizeof(command_R4), &bytesWritten4, NULL)) {
std::cout << "115200的对话模式配置失败." << std::endl;
CloseHandle(hSerial_L);
}
if (!ReadFile(hSerial_L, dataReceived_L, sizeof(dataReceived_L), &bytesRead_L, NULL)) {
std::cout << "115200的对话模式回复失败." << std::endl;
CloseHandle(hSerial_L);
}
}
}
//设置频率为115200
char command_R1[] = { 0x77, 0x05, 0x00, 0x0B, 0x04, 0x14 };//115200
if (!WriteFile(hSerial_L, command_R1, sizeof(command_R1), &bytesWritten1, NULL))
{
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial_L);
}
if (!ReadFile(hSerial_L, dataReceived_L, sizeof(dataReceived_L), &bytesRead_L, NULL))
{
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial_L);
}
exists = false;
while (!exists)
{
for (int i = 0; i < sizeof(dataReceived_L); i++) {
printf("%02X ", dataReceived_L[i]);
}
for (int i = 0; i < sizeof(dataReceived_L); i++) {
if (dataReceived_L[i] == 0x77 && dataReceived_L[i + 3] == 0xFFFFFF8B) {//设置成功
exists = true; // 元素存在,设置标志位为true
std::cout << "115200波特率配置成功!" << std::endl;
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
if (!WriteFile(hSerial_L, command_R1, sizeof(command_R1), &bytesWritten1, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial_L);
}
if (!ReadFile(hSerial_L, dataReceived_L, sizeof(dataReceived_L), &bytesRead_L, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial_L);
}
std::cout << "重复配置115200波特率" << std::endl;
// 可以在这里添加需要执行的语句
}
}
//00-11:应答模式 05-50Hz 04-25Hz
//06-100 05-50 04-25
char command_R3[] = { 0x77, 0x05, 0x00, 0x0C, 0x03, 0x14 };//50Hz
if (!WriteFile(hSerial_L, command_R3, sizeof(command_R3), &bytesWritten3, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial_L);
}
if (!ReadFile(hSerial_L, dataReceived_L, sizeof(dataReceived_L), &bytesRead_L, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial_L);
}
for (int i = 0; i < sizeof(dataReceived_L); i++) {
printf("%02X ", dataReceived_L[i]);
}
exists = false;
while (!exists) {
for (int i = 0; i < sizeof(dataReceived_L); i++) {
printf("%02X ", dataReceived_L[i]);
}
for (int i = 0; i < sizeof(dataReceived_L); i++) {
if (dataReceived_L[i] == 0x77 && dataReceived_L[i + 3] == 0xFFFFFF8C) {//设置成功
exists = true; // 元素存在,设置标志位为true
std::cout << "50Hz配置成功!" << std::endl;
break; // 跳出for循环
}
}
if (exists)
{
break;
}
if (!exists) {
if (!WriteFile(hSerial_L, command_R3, sizeof(command_R3), &bytesWritten3, NULL)) {
std::cout << "Error writing to serial port." << std::endl;
CloseHandle(hSerial_L);
;
}
if (!ReadFile(hSerial_L, dataReceived_L, sizeof(dataReceived_L), &bytesRead_L, NULL)) {
std::cout << "Error reading from serial port." << std::endl;
CloseHandle(hSerial_L);
}
std::cout << "元素不存在,继续执行某条语句..." << std::endl;
// 可以在这里添加需要执行的语句
}
}
}
}
实时读取界面完成。
因为在实际的使用过程之中,需要用到的数据不可能只是一个倾角传感器的数据,如何进行多传感器的时间的同步是一个比较重要的问题。
针对于这个时间帧对齐方式,当存在多个传感器的时候,多个传感器的输出频率是不一致的情况下,最佳的方式是将其频率调节到整数倍的情况下。然后使用插值的方式使得其帧率变为一致的情况。
以相机而言,如下所示,可以调用相机的SDK进行人为设置相机的帧率。
可以见到相应的相机的帧率是稳定不变的,以将相机与倾角传感器时间帧进行对齐为例。首先,选定一个参考物也就是所谓的时间的参考物,我是以相机为参考时间的,将倾角传感器的频率设置为100Hz,由于此处我是将receive的长度设置为34,也就是采集长度的二倍,因此实际输出的频率为原来的1/2,也就是50Hz。(这样做的目的是方式出现丢帧的问题)
我的想法是使用时间戳的方式进行对齐,首先将相机的帧率设置为10FPS,需要进行注意的是相机设置为10FPS的过程,相机是逐渐成为10FPS的,有一个时间延迟,延迟一段时间并且记录下此时的时间戳t1。同理,倾角传感器在进行采集的过程之中也是存在相应的时间延迟,延迟之后记录下此时的时间戳t2。
其含义为相机在t1时刻以后以10Hz的频率进行采集,倾角传感器在t2时刻以后以50Hz的频率进行采集。其中10Hz对应100ms/次,50Hz对应20ms/次。其中如何对齐,后面再想。
问题的出现:
在实际进行采集的时候,采集的一帧数据,应该是17个字节。0x77开头便是一帧数据,但是实际0x77在后面,因此前面是进行了采集了两帧数据,防止0x77以后的数据是断开的,然后再进行处理。
但是这就导致了一个问题,由于设置的char dataReceived[34],也就是说是34个字节,标准数据是17个字节,因此采集的频率是实际的设定的一半。
问题的解决:
这个地方的问题我想了一下,如何设定为与标准的采集频率一致。不如我们就是将char dataReceived[设置为17个字节,然后再复制一份进行拼接为34个字节,将这34个字节再进行处理,这样便可以设置得到的数据频率与设定的频率一致。
注意这个地方进行拼接的时候还不能使用常规的方法:
strcpy(response_R, dataReceived); // 复制第一个数组到目标数组
strcat(response_R, dataReceived); // 追加第二个数组到目标数组
如上所示的代码,如果进行拼接会出现错误,原因在于进行拼接的是16进制的元素,拼接以后会出现完全数据不一致的问题。
可以见到,拼接以后与拼接前进行对比,数据是完全不正确了
这个地方因此使用常规的遍历是最合适的:
ReadFile(hSerial, dataReceived, sizeof(dataReceived), &bytesRead, NULL);
std::cout << "拼接前 " << std::endl;
for (int i = 0; i < sizeof(dataReceived); i++) {
printf("%02X ", dataReceived[i]);
}
std::cout << "拼接后 " << std::endl;
for (int i = 0; i < 17; i++) {
response_R[i] = dataReceived[i];
response_R[i+17] = dataReceived[i];
}
for (int i = 0; i < sizeof(response_R); i++) {
printf("%02X ", response_R[i]);
}
得到的数据结果如下:
问题基本完全解决,见视频:
bws
详细代码见资源下载