【发布时间】:2021-12-23 19:50:01
【问题描述】:
(请原谅我的英语) 你好。我是一名编码初学者,开始尝试 Arduino 和 c++(因为 Arduino)。最近我刚刚了解到您可以通过串行监视器写入 Arduino 板,从而通过您的 COM 端口通过您的 PC,所以我试图找到一种通过 Arduino 的串行监视器从 cmd 控制伺服电机旋转的方法。我复制了 Arduino 网站上作为示例给出的代码,并通过 youtube 上的某个人获得了一段代码。
因为您看到此代码的工作原理与它通过 windows(任何 ide)上的 c++ 程序写入串行监视器一样,但是当我发送命令时,它运行正确,然后它再次运行但将输入设置为 0度,从而将伺服头移动到 0 度。如果输入为 0,我通过阻止伺服旋转来暂时“修复”它,但它会运行草图中的所有其他内容。 (我已经包含了下面的代码,但它真的很长,我不完全知道如何包含大段代码(如果我包含错误的内容,请道歉)同时仍然包含最小可重现的示例。如果被告知,我会很乐意更改它到)
主要代码:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <string>
#include "SerialPort.h"
char output[MAX_DATA_LENGTH];
char incomingData[MAX_DATA_LENGTH];
using namespace std;
char temp[] = "\\\\.\\COM4";
char* port = temp;
float Scalar = 0.8888;
int main() {
SerialPort arduino(port);
if (arduino.isConnected()) {
cout << "Connection established" << endl << endl;
}
else {
cout << "Error in port name" << endl << endl;
}
while (arduino.isConnected()) {
while (true) {
cout << "Enter your command (degrees 0 to 180 in integers): " << endl;
string data;
cin >> data;
if (data == "exit")
return 0;
/*if (stoi(data) != 90) {
data = to_string(
round((stof(data) - 90) * Scalar + 90)
);
}*/
//cout << data << endl;
char* charArray = new char[data.size() + 2];
copy(data.begin(), data.end(), charArray);
charArray[data.size()] = '\n';
charArray[data.size() + 1] = '\0';
cout << "char array: " << charArray << endl;
arduino.writeSerialPort(charArray, MAX_DATA_LENGTH);
arduino.readSerialPort(output, MAX_DATA_LENGTH);
cout << ">> " << output << endl;
cout << "----------\n" << endl;
delete[] charArray;
}
}
return 0;
}
.ino 草图文件:
#include <Servo.h>
Servo servo1;
int LED = 13;
int servoPos = 90; //to store servo's position
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(LED, OUTPUT);
servo1.attach(11);
servo1.write(servoPos);
}
void loop() {
// put your main code here, to run repeatedly:
delay(15);
if(Serial.available() > 0) {
String info;
String return_text;
info = Serial.readStringUntil('\n');
return_text = "info variable string is: " + info;
Serial.println(return_text);
if(info.toInt() < servoPos && info.toInt() != 0) {
for( 0; servoPos > info.toInt(); servoPos-=1) {
servo1.write(servoPos);
delay(5);
}
}
else if(info.toInt() > servoPos) {
for( 0; servoPos < info.toInt(); servoPos+=1) {
servo1.write(servoPos);
delay(5);
}
}
digitalWrite(LED, HIGH);
delay(20);
digitalWrite(LED, LOW);
//Serial.println("");
//Serial.print("Servo position: ");
//Serial.println(servoPos);
}
}
标题:
#ifndef SERIALPORT_H
#define SERIALPORT_H
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 255
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class SerialPort
{
private:
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
SerialPort(char* portName);
~SerialPort();
int readSerialPort(char* buffer, unsigned int buf_size);
bool writeSerialPort(char* buffer, unsigned int buf_size);
bool isConnected();
};
#endif // SERIALPORT_H
以及包含函数的cpp文件:
#include "SerialPort.h"
SerialPort::SerialPort(char* portName)
{
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (this->handler == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
printf("ERROR: Handle was not attached. Reason: %s not available\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else {
DCB dcbSerialParameters = { 0 };
if (!GetCommState(this->handler, &dcbSerialParameters)) {
printf("failed to get current serial parameters");
}
else {
dcbSerialParameters.BaudRate = CBR_9600;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = ONESTOPBIT;
dcbSerialParameters.Parity = NOPARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler, &dcbSerialParameters))
{
printf("ALERT: could not set Serial port parameters\n");
}
else {
this->connected = true;
PurgeComm(this->handler, PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort()
{
if (this->connected) {
this->connected = false;
CloseHandle(this->handler);
}
}
int SerialPort::readSerialPort(char* buffer, unsigned int buf_size)
{
DWORD bytesRead;
unsigned int toRead = 0;
ClearCommError(this->handler, &this->errors, &this->status);
if (this->status.cbInQue > 0) {
if (this->status.cbInQue > buf_size) {
toRead = buf_size;
}
else toRead = this->status.cbInQue;
}
if (ReadFile(this->handler, buffer, toRead, &bytesRead, NULL)) return bytesRead;
return 0;
}
bool SerialPort::writeSerialPort(char* buffer, unsigned int buf_size)
{
DWORD bytesSend;
if (!WriteFile(this->handler, (void*)buffer, buf_size, &bytesSend, 0)) {
ClearCommError(this->handler, &this->errors, &this->status);
return false;
}
else return true;
}
bool SerialPort::isConnected()
{
return this->connected;
}
会发生什么:
所以当我运行它时,首先伺服器旋转到 90 度,然后当我给它一个整数输入时,Arduino 将伺服器运行到所需的输入,打开和关闭 LED,当这种情况发生时,cpp 主代码打印我'已经发送到 Arduino(或者至少是没有\n 和\0 等的可见内容)以及串行监视器写的内容并返回要求我发送输入。 问题是 Arduino 代码再次运行并将伺服器移动到 0 度并点亮和关闭 LED,就像以前没有我的请求一样。
如果data == 0,我去阻止伺服器移动,但 .ino 草图的其余部分仍在运行,所以我怀疑它可能与 cpp 文件发送到监视器的字符有关..?但是我脑子太笨了,无法弄清楚,因此寻求任何建议。控制台显示输出,但在 arduino 循环第二次发生时不显示任何内容。
如果我在控制台中写了一些东西,而第二次(不希望的)迭代发生了,那么 arduino 不会响应我的输入,并且它还会在下一次运行期间通过不显示文本或完全弄乱串行监视器中的output增加文本和/或显示奇怪的胡言乱语,例如“³ô¦ò»]½R↨ùýº§»⌂2{²à_Ú◄/4ý¾ı”等等。
(如果由于不当行为、礼仪或其他原因需要添加、删除或更改任何内容,那么正如我所说,我会非常乐意) 提前致谢。
【问题讨论】: