我正在尝试使用带有DMX Shield的Qt和Arduino创建一个软件照明桌。我已经能够在这两者之间建立通信,并且可以将命令发送到Arduino Mega(此时通信只进行一种方式)。我定期(每200毫秒)将11个推子的值作为字符串发送给Mega。
例如:A123 B234 C050 ... J222 M255
上面字符串中的值是基于滑块位置的变量,应该用于调整保存在Mega侧的每个推子上的光强度值。每个部分中的字母标识相应的推子。 A = fader1,B = fader2,......为了清楚起见:我可以以特定的强度调出一个光/秒 - >然后将这些强度分配给推子,当推子移动时,我希望调整这些值并将其发送到实际的灯/调光器。计算工作正常但我的Mega最终会变得没有反应。
我认为我的问题是解析传入的字符串。我试过strtok()方法和readStringUntil()无济于事。在串行监视器中监视传入的字符串也很困难,因为它用于与Qt进行通信。
很高兴能得到任何帮助。如果有任何不清楚的地方,请提问。
编辑:
这是我尝试解决方案之一
const char delim[2] = " ";
char *token;
if(Serial.available())
{
//incomingMessage = Serial.readString();
incomingMessage = Serial.readStringUntil("\n"); // read the whole string until newline
//Serial.println(incomingMessage);
const char* str = incomingMessage.c_str(); // convert it to a C String terminated by a null character "\0"
//Serial.println(str);
token = strtok(str, delim); // first part is a first section until delimiter occurs "-space- "
//Serial.println(token);
LX_Rated.commandLineResolve(token); // resolve it
while( token != NULL ) { // continue splitting and resolving the incoming message until it reaches the end
token = strtok(NULL, delim);
LX_Rated.commandLineResolve(token);
}
}
EDIT2:
我已经确认我收到了Qt发送的整个字符串。当我尝试使用strtok()函数对其进行标记并打印出第一个标记时,我返回整个字符串,其他标记为空。我的代码中没有看到任何错误。我甚至试图减慢从Qt到每5秒发送一个字符串的速度。有谁知道发生了什么事?我不明白为什么这个标准功能没有按预期工作。请参阅下面的修改代码。
if(Serial.available()) {
incomingMessage = Serial.readStringUntil("\n");
Serial.println("ok");
Serial.flush();
char* nullTerminatedIncomingMessage = incomingMessage.c_str();
const char delimiter = " ";
char* token;
char* token1;
char* token2;
//char* secondToken;
token = strtok(nullTerminatedIncomingMessage, delimiter);
token1 = strtok(NULL, delimiter);
token2 = strtok(NULL, delimiter);
Serial.println(token); // print the first section
//Serial.println(incomingMessage);
Serial.flush();
Serial.println(token1);
Serial.flush();
Serial.println(token2);
Serial.flush();
//while(token != NULL)
// secondToken = strtok(NULL, delimiter);
//Serial.println(secondToken);
//Serial.flush();
incomingMessage = "";
}
答案 0 :(得分:0)
至于监控通信的困难,您可以(在Qt中)将您读取的所有内容转储到控制台中,并对写入串口的所有内容执行相同的操作。它将显示在QtCreator的控制台选项卡中
#include <QDebug>
...
qDebug() << "whatever" << endl;
Aso用于解析您从串口读取的数据,看看这个,看看如何轻松split将滑块信息转换为单个字符串(QRegExp) How Can I Split a String According To Delimiters in Qt?
我不可能猜到为什么没有代码你的arduino会没有反应。
编辑: 当您在Qt中生成字符串时,是否可以通过 space 之外的其他内容分隔标记?也许tab(&#34; \ t&#34;)或其他什么? strtok在分隔符字符串中接受多个分隔符,可能需要尝试。 如果不是这种情况,则strtok(...)函数出现问题的可能性很小(顺便说一句,它修改了原始字符串,这本身就是一个问题)。此外,strtok可能会返回一个NULL指针,你似乎无法处理这种情况(一些错误的输入 - 打印一条消息)。您可以尝试将其作为普通strtok的替代方法:
/**
* @brief custom strtok replacement with the same interface
* It does not modify the original string
* Token length is limited to 63 characters
* @param ptr pointer to the string or NULL
* @param delim delimiting character(only the first character will be used)
*/
const char * my_strtok(const char * ptr, const char * delim) {
// Persistent variables, it will remember pointer to the processed string
static const char * src;
static char buffer[64]; // Token is limited to 63 characters
if(ptr) { // Remember the pointer, if a new one was supplied
src = ptr;
}
if(src == NULL || *src == '\0')// Invalid / empty string / no next token - return NULL
return NULL;
char i = 0;
for(i = 0; i < 63 && *src != delim[0]; i++) {// Copy token until delimiter or end of buffer
buffer[i] = *(src++);
}
if(*src == delim[0]) // Skip over the delimiter to the begining of the next token
++src;
buffer[i] = '\0'; // Any returned string must be terminated
return buffer;
}
#include <cstdlib>
#include <cstring>
#include <cassert>
void test() {
const char * str1 = "123 456 asdf jkl;";
assert(strcmp("123", my_strtok(str1, " ")) == 0);
assert(strcmp("456", my_strtok(NULL, " ")) == 0);
assert(strcmp("asdf", my_strtok(NULL, " ")) == 0);
assert(strcmp("jkl;", my_strtok(NULL, " ")) == 0);
assert(NULL == my_strtok(NULL, " "));
assert(NULL == my_strtok(NULL, " "));
assert(strcmp("123", my_strtok(str1, " ")) == 0);
}
答案 1 :(得分:0)
你的错误 - 至少 - 是假设所有输入在你预期时都可用。您需要推迟处理,直到整个生产线组装完毕。 Serial.readStringUntil
阻止,直到整行可用,并且这不是您所期望的。您基本上需要将Serial.available()
替换为Serial.lineAvailable()
,但后者未实现。
This answer包含完整的问题解决方案 - 包括Qt和Arduino代码 - 以及Arudino仿真层。这可能是一个很好的起点,尤其是您可以在一个应用程序中轻松地共同调试Qt和Arduino项目并使用一个调试器!