Arduino Serial.print() 优化

发布于 2024-10-29 00:46:00 字数 1052 浏览 2 评论 0原文

unsigned long current_millis_value = 0;
unsigned long previous_millis_value = 0;
unsigned long m = 0;
unsigned int seconds = 0;
unsigned int minutes = 0;
unsigned int hours = 0;

unsigned long clockTimeStart = 1800000; //30 Minutes
unsigned long currentClockTime;

void loop() {
    current_millis_value = millis();
    currentClockTime -= current_millis_value - previous_millis_value;
    previous_millis_value = current_millis_value;

    minutes = (currentClockTime / 1000 / 60);
    seconds = (currentClockTime / 1000) % 60;
    m = (currentClockTime % 100);

    Serial.print(minutes);
    Serial.print(":");
    Serial.print(seconds);
    Serial.print(":");
    Serial.println(m);
}

我发现串行写入之间的时间间隔为每写入串行行 9-11 毫秒。有没有办法优化 Serial.print() 方法以允许跨 long 和 String 值类型写入多个值?

示例(这是无效的,但符合我的想法):

Serial.print(minutes + ":" + seconds + ":" + m);

我知道这不是我正在使用的 JavaScript - 只是寻找编写过程的优化可能性。我知道 MOD 可能很昂贵,但只需进行简单的减法并写出 currentClockTime 的值,就会留下 6-7 毫秒的间隙时间。

unsigned long current_millis_value = 0;
unsigned long previous_millis_value = 0;
unsigned long m = 0;
unsigned int seconds = 0;
unsigned int minutes = 0;
unsigned int hours = 0;

unsigned long clockTimeStart = 1800000; //30 Minutes
unsigned long currentClockTime;

void loop() {
    current_millis_value = millis();
    currentClockTime -= current_millis_value - previous_millis_value;
    previous_millis_value = current_millis_value;

    minutes = (currentClockTime / 1000 / 60);
    seconds = (currentClockTime / 1000) % 60;
    m = (currentClockTime % 100);

    Serial.print(minutes);
    Serial.print(":");
    Serial.print(seconds);
    Serial.print(":");
    Serial.println(m);
}

I'm getting a gap in times between serial writes of anywhere from 9-11 ms per serial line written. Is there a way to optimize the Serial.print() method to allow writing of multiple values across types of long and String values?

Example (this is not valid but along the lines of what I'm thinking):

Serial.print(minutes + ":" + seconds + ":" + m);

I know this isn't JavaScript I'm working in - just looking for optimization possibilities for the writing process. I know that MOD can be expensive but just doing the simple subtraction and writing out the value of currentClockTime leaves me with a gap time of 6-7 ms.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

謸气贵蔟 2024-11-05 00:46:00

arduino 有一个类似 java 的字符串连接。我不知道这是否会让你加快速度,但它会在发送之前将所有内容连接成一个字符串。

String package = "" + minutes;
package += ":"+seconds;
package += ":"+m;
Serial.print(package);

如果您能够在另一端重建字符串,也许更好的做法是使用 Serial.Write 并发送原始数据,然后在接收端重建字符串。这会将每个循环发送的数据量从 5-10 字节减少到 3-4 字节。

The arduino has a semi-java like string concatenation. I have no idea if this will get you any speed up, but it will concatenate everything into one string before sending it.

String package = "" + minutes;
package += ":"+seconds;
package += ":"+m;
Serial.print(package);

If you're able to reconstruct the string on the other side, perhaps a better course of action is to use Serial.Write and send the raw data, then reconstruct the String on the receiving side. This would reduce the amount of data you send each loop from 5-10 bytes to 3-4 bytes.

他不在意 2024-11-05 00:46:00

有什么方法可以将所有内容预先转换为字符串值,以便可以一次写出整个字符串?例如,使用 snprintf() 函数写入预先分配的 char[],然后在一次调用 Serial.print 中将其打印出来()?

例如:

char buffer[32];
snprintf(buffer, 32, "%u : %u : %lu", minutes, seconds, m);
Serial.print(buffer);

--Jason

Any way to pre-convert everything to a string value so you can write out the entire string at once? For instance, use something like a snprintf() function to write into a pre-allocated char[] that you then print out in one call to Serial.print()?

So for instance:

char buffer[32];
snprintf(buffer, 32, "%u : %u : %lu", minutes, seconds, m);
Serial.print(buffer);

--Jason

懒猫 2024-11-05 00:46:00

Streaming 库应该可以满足您的需求:

Serial << minutes << ":" << seconds << ":" << m;

The Streaming library should do what you want:

Serial << minutes << ":" << seconds << ":" << m;
Bonjour°[大白 2024-11-05 00:46:00

在 Arduino 下进行字符串连接的最快且首选的方法是

  • 使用 String 类。
  • 如果您确实需要速度和/或只是想避免在每次连接操作中创建新的内存中字符串,请使用reserve()提前保留所需的内存
  • 首先,将对象设置为空字符串“”。
  • 然后,通过调用 concat() 或运算符 += 附加所需的字符或字符串,每行代码仅使用一个 concat() 或 += 操作。这是为了避免创建临时 Strings 对象。
  • 通过提前执行reserve(),String对象将有效地充当行缓冲区。

通过应用上述准则,串联操作将就地完成

请注意,应该使用行缓冲区容量的最合适值调用reserve(),即:String执行realloc()之前所需的最大字符数,不包括空终止字符'\0'。

以下是三种替代方案:

1) 这是示例代码,

// Declaration, outside setup() and loop()
String line;

// Inside setup()
// Use the appropriate value for reserve(), depending on on your actual usage.
line.reserve(10);

// Inside loop()
line = "";
line += minutes;
line += ":";
line += seconds;
line += ":";
line += m;
Serial.println(line);

2) 作为在 setup() 中调用 Reserve() 的替代方案,您可以使用具有所需(最大)长度的“模板”或虚拟字符串来声明和初始化字符串。

以下是此替代方案的示例代码,

// Declaration, outside setup() and loop()
String line = "XXXX:YY:ZZ";

// No need to use reserve() inside setup()

// Inside loop()
line = "";
line += minutes;
line += ":";
line += seconds;
line += ":";
line += m;
Serial.println(line);

第一种方法允许您使用带有动态计算的最大长度值的reserve(),而当您有“模板”或已知的固定长度时,第二种方法会导致更清晰的代码读取您稍后将要编写的字符串。

3) 如果您只需要将数据输出到输出流(通常是串行),这是最快、最紧凑的代码,不需要 String 或外部库,

// No need to declare a String outside setup() and loop()
// No need to use reserve() inside setup()

// Inside loop()
Serial.print(minutes);
Serial.print(":");
Serial.print(seconds);
Serial.print(":");
Serial.println(m);

注意:答案为John Y 的做法与我的上一段代码完全相同,只是他的代码读取起来“更简单”(假设您对运算符 << 感到满意,用作 C++ 流语法糖)。然而,在某些情况下,使用 Streaming 库会生成稍大/稍慢的代码。

The fastest and preferred way to do string concatenation under Arduino is,

  • Use the String class.
  • If you really need the speed and/or simply want to avoid creating new in-memory strings with every concatenation operation, reserve the needed memory ahead of time with reserve().
  • First, set the object to an empty string "".
  • Then, append the needed characters or strings by invoking concat() or the operator +=, using exactly one concat() or += operation per line of code. This is to avoid the creation of temporary Strings objects.
  • By executing reserve() in advance, the String object will be effectively acting as a line buffer.

By applying the above guidelines, the concatenation operations will be done in place.

Note that reserve() should be called with the most appropriate value for the line buffer capacity, i.e.: maximum number of characters you need before String does a realloc(), not including the null-terminating character '\0'.

Three alternatives follow:

1) Here is the sample code,

// Declaration, outside setup() and loop()
String line;

// Inside setup()
// Use the appropriate value for reserve(), depending on on your actual usage.
line.reserve(10);

// Inside loop()
line = "";
line += minutes;
line += ":";
line += seconds;
line += ":";
line += m;
Serial.println(line);

2) As an alternative to calling reserve() at setup(), you could declare and initialize the String with a "template" or dummy string which has the desired (maximum) length.

Here is the sample code for this alternative,

// Declaration, outside setup() and loop()
String line = "XXXX:YY:ZZ";

// No need to use reserve() inside setup()

// Inside loop()
line = "";
line += minutes;
line += ":";
line += seconds;
line += ":";
line += m;
Serial.println(line);

The first approach allows you to use reserve() with a dynamically calculated maximum length value, while the second approach results in somewhat cleaner to read code when you have a "template" or known fixed length for the string you will be later composing.

3) If you only need to output the data to the output stream (usually Serial), this is the fastest and the most compact code, with no need of String or external libraries,

// No need to declare a String outside setup() and loop()
// No need to use reserve() inside setup()

// Inside loop()
Serial.print(minutes);
Serial.print(":");
Serial.print(seconds);
Serial.print(":");
Serial.println(m);

Note: the answer by John Y does exactly the same as my last piece of code, except for his "simpler" to read code (assuming you feel comfortable with the operator <<, used as C++ streaming syntactic sugar). In some cases, however, using the Streaming library will generate slightly larger/slower code.

把人绕傻吧 2024-11-05 00:46:00

我找到了串行打印由整数和单词(消息)组成的单个字符串的最简单方法:

在 scketch 中:

int w = 12;

Serial.Print ("my number is: ");

Serial.Print (w);

Serial.Println (" - which is to be used in calculation!"

结果:

在串行监视器上,您将看到(作为单行!!!!!!!!!!!!):

我的数字是:12 - 用于计算!

I found the easiest way to Serial print a single string composed of integers and your words (message):

in scketch :

int w = 12;

Serial.Print ("my number is: ");

Serial.Print (w);

Serial.Println (" - which is to be used in calculation!"

RESULT:

On serial monitor you will see (as a single LINE!!!!!!!!!!):

my number is: 12 - which is to be used in calculation!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文