如何在C++中读取程序输出并发送至Arduino驱动魔方求解器?
如何将C++魔方求解器的输出发送到Arduino控制步进电机?
我正在搭建一款魔方求解器设备,需要读取C程序的输出并传入设备的步进电机。我的C程序会输出求解魔方所需的转动步骤(颜色字符串,比如Yellow、White等),示例输出如下:
________________________| RUBIK'S CUBE SOLVER |________________________ Input : enter code here White Side : Red Side : Orange Side : Blue Side : Green Side : Yellow Side : ------------------------------------------------- Turn these sides of the Cube in Clockwise Direction by 90 degrees in this exact order... Yellow Yellow White Orange
当前的C++代码片段(处理白色面转动的部分)如下:
if (choice=='w') { cout<<"White"<<endl; swap(white[7],white[3]); swap(white[6],white[4]); swap(white[0],white[2]); swap(white[7],white[5]); swap(white[0],white[4]); // 其他魔方状态更新代码... }
我希望添加功能,读取cout输出的颜色字符串,直接发送至Arduino以执行相应转动操作。
解决方案思路
核心是让C++程序通过串口把颜色指令发送给Arduino,Arduino接收后解析指令并驱动步进电机。下面分步骤实现:
1. 修改C++程序,添加串口通信功能
我们需要把原本输出到控制台的颜色指令,同时发送到Arduino所在的串口。这里以Windows平台为例(跨平台可以用libserialport库):
首先实现串口打开和发送函数,然后在输出颜色的地方调用发送逻辑:
#include <iostream> #include <Windows.h> #include <string> // 打开指定串口 HANDLE openSerialPort(const char* portName) { HANDLE hSerial = CreateFileA(portName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { std::cerr << "Failed to open serial port!" << std::endl; return INVALID_HANDLE_VALUE; } // 配置串口参数:9600波特率,8N1(8位数据、无校验、1位停止位) DCB dcbParams = {0}; dcbParams.DCBlength = sizeof(dcbParams); if (!GetCommState(hSerial, &dcbParams)) { std::cerr << "Failed to get serial port state!" << std::endl; CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } dcbParams.BaudRate = CBR_9600; dcbParams.ByteSize = 8; dcbParams.StopBits = ONESTOPBIT; dcbParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbParams)) { std::cerr << "Failed to set serial port parameters!" << std::endl; CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } return hSerial; } // 发送指令到串口,附加换行符作为结束标记 void sendToArduino(HANDLE hSerial, const std::string& cmd) { DWORD bytesWritten; // 发送指令内容 WriteFile(hSerial, cmd.c_str(), cmd.size(), &bytesWritten, NULL); // 发送换行符,方便Arduino识别单条指令 WriteFile(hSerial, "\n", 1, &bytesWritten, NULL); } int main() { // 替换为你的Arduino串口(比如COM3,可在Arduino IDE中查看) HANDLE hSerial = openSerialPort("COM3"); if (hSerial == INVALID_HANDLE_VALUE) { return 1; } // 模拟你的求解逻辑,输出颜色指令并发送到Arduino // 这里可以替换成你实际的求解输出代码 std::string steps[] = {"Yellow", "Yellow", "White", "Orange"}; for (const auto& step : steps) { std::cout << step << std::endl; // 保留原控制台输出 sendToArduino(hSerial, step); // 发送到Arduino Sleep(500); // 给Arduino留处理时间,避免指令堆积 } CloseHandle(hSerial); return 0; }
在你现有的代码中,比如处理choice=='w'的分支,只需添加发送逻辑:
if (choice=='w') { std::string color = "White"; cout << color << endl; sendToArduino(hSerial, color); // 新增:发送到Arduino // 原有的魔方状态更新代码 swap(white[7],white[3]); swap(white[6],white[4]); swap(white[0],white[2]); swap(white[7],white[5]); swap(white[0],white[4]); // ...其他代码 }
2. Arduino端:接收指令并控制步进电机
Arduino需要监听串口,接收到颜色指令后执行对应的步进电机转动逻辑。示例代码如下(根据你的硬件连接调整引脚):
// 步进电机引脚定义(根据你的实际接线修改) #define STEP_PIN 2 #define DIR_PIN 3 // 转动黄色面90度顺时针的函数 void turnYellow() { digitalWrite(DIR_PIN, HIGH); // 设置方向为顺时针 // 假设步进电机需要200步转90度(根据你的电机参数调整) for (int i = 0; i < 200; i++) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(500); digitalWrite(STEP_PIN, LOW); delayMicroseconds(500); } } // 转动白色面90度顺时针的函数 void turnWhite() { digitalWrite(DIR_PIN, HIGH); for (int i = 0; i < 200; i++) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(500); digitalWrite(STEP_PIN, LOW); delayMicroseconds(500); } } // 转动橙色面90度顺时针的函数 void turnOrange() { digitalWrite(DIR_PIN, HIGH); for (int i = 0; i < 200; i++) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(500); digitalWrite(STEP_PIN, LOW); delayMicroseconds(500); } } void setup() { Serial.begin(9600); // 和C++程序的波特率保持一致 pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT); } void loop() { if (Serial.available() > 0) { String cmd = Serial.readStringUntil('\n'); cmd.trim(); // 去除换行符和多余空格 // 调试输出,可在Arduino IDE串口监视器查看 Serial.println("Received command: " + cmd); // 根据指令执行对应转动 if (cmd == "Yellow") { turnYellow(); } else if (cmd == "White") { turnWhite(); } else if (cmd == "Orange") { turnOrange(); } // 在这里添加其他颜色的判断逻辑 } }
3. 关键注意事项
- 串口参数匹配:确保C++程序和Arduino的波特率、数据位、停止位、校验位完全一致(示例中用的是9600, 8N1)。
- 指令结束标记:发送指令时添加换行符
\n,让Arduino能准确区分每条指令,避免粘包。 - 延迟处理:C++程序发送每条指令后短暂延迟(比如500ms),给Arduino足够的时间完成转动,避免指令堆积。
- 过滤无关输出:如果你的C++程序还有其他控制台输出(比如标题、提示语),需要在发送前过滤掉,只保留颜色指令字符串。可以通过判断输出内容是否是预设的颜色列表(比如Yellow、White等)来实现。
内容的提问来源于stack exchange,提问作者crispo12
相关产品推荐
相关产品推荐

