BWS2000倾角传感器c++测试代码_时间延迟与时间同步问题【3】

详见昨天做的测试代码,代码网址:
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<std::chrono::milliseconds>(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 <Windows.h>

#include <iostream>
#include <iomanip>
#include <iostream>
#include <chrono>
#include <thread>
#include <iostream>
#include <iomanip> 
#include <iostream>
#include <sstream> 
#include <iomanip>

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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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/次。其中如何对齐,后面再想。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/263400.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动能方案|NFC智能家电解决方案 基于13.56MHz的近场无线通信技术

众所周知&#xff0c;物联网&#xff08;IoT&#xff09;是一个连接日常物品和互联网的系统&#xff0c;它正在迅速改变我们执行日常任务的方式&#xff0c;物联网的影响如今几乎在每一个领域都有体现。IOT应用在智能家居领域的发展&#xff0c;相信大家都不陌生&#xff0c;日…

Searching for MobileNetV3(2019)

文章目录 Abstract主要内容实验结果 IntroductionRelated WorkEfficient Mobile Building BlocksNetwork SearchPlatform-Aware NAS for Block-wise SearchNetAdapt for Layer-wise Search Network ImprovementsRedesigning Expensive LayersNonlinearitiesLarge squeeze-and-e…

Jupyter Notebook修改默认工作目录

1、参考修改Jupyter Notebook的默认工作目录_jupyter文件路径-CSDN博客修改配置文件 2.在上述博客内容的基础上&#xff0c;这里不是删除【%USERPROFILE%】而是把这个地方替换为所要设置的工作目录路径&#xff0c; 3.【起始位置】也可以更改为所要设置的工作目录路径&#x…

3分钟部署自己独享的Gemini

3分钟部署自己独享的Gemini 在前面的几篇文章中&#xff0c;分别介绍了Gemini Pro的发布和Gemini Pro API的详细申请步骤&#xff0c;那么今天给大家分享的是如何快速搭建一个属于自己的Gemini 。 1️⃣ 准备工作 科学网络环境Github账号和Vercel账号Gemini Pro API Key&…

深度学习建模从零开始步骤流程

深度学习建模从零开始步骤流程 步骤如下&#xff1a; 环境准备三方库安装建模开发 环境准备 Anaconda安装&#xff1a; Anaconda下载网址&#xff0c;下载win10下的64位版本。 清华镜像站 下载完毕后点击安装&#xff0c;一直点确定或下一步 到上图点击 Just me&#xff…

Appium如何实现移动端UI自动化测试呢?

Appium是一个开源跨平台移动应用自动化测试框架。 既然只是想学习下Appium如何入门&#xff0c;那么我们就直奔主题。文章结构如下&#xff1a; 为什么要使用Appium&#xff1f;如何搭建Appium工具环境?(超详细&#xff09;通过demo演示Appium的使用Appium如何实现移动端UI自…

Appium安装及配置

一、前置说明 Appium 是一个用于自动化移动应用程序的开源测试框架&#xff0c;它支持 Android 和 iOS&#xff0c;同时支持使用多种编程语言&#xff08;如 Java、Python、JavaScript 等&#xff09;进行测试脚本的编写。 二、操作步骤 1. 安装Node.js Appium Server 由 n…

【玩转TableAgent数据智能分析】借助全球高校数据多维度分析案例,体验TableAgent如何助力用户轻松洞察数据,赋能企业高效数智化转型

目录 前言 一、TableAgent介绍及其优势&#xff1f; 1、会话式数据分析&#xff0c;所需即所得 2、私有化部署&#xff0c;数据安全 3、支持企业级数据分析,大规模&#xff0c;高性能 4、支持领域微调&#xff0c;专业化 5、透明化过程&#xff0c;审计部署 二、使用Ta…

【设计模式-2.5】创建型——建造者模式

说明&#xff1a;本文介绍设计模式中&#xff0c;创建型设计模式中的最后一个&#xff0c;建造者模式&#xff1b; 入学报道 创建型模式&#xff0c;关注于对象的创建&#xff0c;建造者模式也不例外。假设现在有一个场景&#xff0c;高校开学&#xff0c;学生、教师、职工都…

在Windows上使用 Python

本文档旨在概述在 Microsoft Windows 上使用 Python 时应了解的特定于 Windows 的行为。 与大多数UNIX系统和服务不同&#xff0c;Windows系统没有预安装Python。多年来CPython 团队已经编译了每一个 发行版 的Windows安装程序&#xff08;MSI 包&#xff09;&#xff0c;已便…

世微 AP5101C高压线性LED恒流驱动芯片 6-100V 2A LED灯电源驱动

产品描述 AP5101C 是一款高压线性 LED 恒流 芯片 &#xff0c; 简单 、 内置功率管 &#xff0c; 适用于 6- 100V 输入的高精度降压 LED 恒流驱动 芯片。电流2.0A。 AP5101C 可实现内置MOS 做 2.0A, 外置MOS 可做 3.0A 的。 AP5101C 内置温度保护功能 &#xff0c;温度保 护点…

CSS 网页制作-学成在线

1、 准备工作 1.1 项目目录 网站根目录是指存放网站的第一层文件夹&#xff0c;内部包含当前网站的所有素材&#xff0c;包含HTML、CSS、图片、JavaScript等等。 1.2 版心效果 可以发现都是呈现版心居中的效果&#xff0c;但是每次都写一次太麻烦了&#xff0c;可以把版心居中…

java设计模式学习之【责任链模式】

文章目录 引言责任链模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用日志示例代码地址 引言 在现实生活中&#xff0c;常常会遇到这样的场景&#xff1a;一个请求或命令需要经过多个层级的处理。例如&#xff0c;一个行政审批流程可能需要通过多个部门的审…

【视觉实践】使用Mediapipe进行目标检测:杯子检测和椅子检测实践

目录 1 Mediapipe 2 Solutions 3 安装mediapipe 4 实践 1 Mediapipe Mediapipe是google的一个开源项目,可以提供开源的、跨平台的常用机器学习(machine learning,ML)方案。MediaPipe是一个用于构建机器学习管道</

成为一名FPGA工程师:面试题与经验分享

在现代科技领域&#xff0c;随着数字电子技术的迅猛发展&#xff0c;FPGA&#xff08;可编程逻辑器件&#xff09;工程师成为了备受瞩目的职业之一。FPGA工程师不仅需要掌握硬件设计的基本原理&#xff0c;还需要具备良好的编程能力和解决问题的实践经验。面对如此竞争激烈的行…

DRF从入门到精通二(Request源码分析、DRF之序列化、反序列化、反序列化校验、序列化器常用字段及参数、source、定制字段、保存数据)

文章目录 一、Request对象源码分析区分原生request和新生request新的request还能像原来的reqeust一样使用吗源码片段分析总结&#xff1a; 二、DRF之序列化组件序列化介绍序列化步骤序列化组件的基本使用反序列化基本使用反序列化的新增反序列化的新增删除单条 反序列化的校验序…

老师的责任和义务

作为一名老师&#xff0c;我们的责任和义务是重大的。在教育领域&#xff0c;我们扮演着至关重要的角色&#xff0c;肩负着培养下一代人才的重任。下面&#xff0c;我将以知乎的口吻&#xff0c;从几个方面谈谈老师的责任和义务。 确保学生获得高质量的教育。这包括制定合理的教…

【XR806开发板试用】通过http请求从心知天气网获取天气预报信息

1. 开发环境搭建 本次评测开发环境搭建在windows11的WSL2的Ubuntu20.04中&#xff0c;关于windows安装WSL2可以参考文章: Windows下安装Linux(Ubuntu20.04)子系统&#xff08;WSL&#xff09; (1) 在WSL的Ubuntu20.04下安装必要的工具的. 安装git: sudo apt-get install git …

在线客服系统推荐:优质选择助您提升客户服务体验

大部分企业依靠在线客服系统和客户达成联系&#xff0c;他为客户和企业之间建立了有效的沟通桥梁。市场上这么多的在线客服系统哪个好呢&#xff1f; 1、明确自己的需求。 这一点是最重要的&#xff0c;要先明确公司使用客服系统是想做售前咨询还是售后服务。不同的需求相对应…

[笔记]ByteBuffer垃圾回收

参考&#xff1a;https://blog.csdn.net/lom9357bye/article/details/133702169 public static void main(String[] args) throws Throwable {List<Object> list new ArrayList<>();Thread thread new Thread(() -> {ByteBuffer byteBuffer ByteBuffer.alloc…