简体   繁体   English

Arduino Serial.print()优化

[英]Arduino Serial.print() optimization

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. 我在串行写入之间的时间间隔为每串行写入9-11 ms。 Is there a way to optimize the Serial.print() method to allow writing of multiple values across types of long and String values? 有没有办法优化Serial.print()方法,以允许跨long和String值类型写入多个值?

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. 我知道这不是我正在研究的JavaScript - 只是在寻找写作过程的优化可能性。 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. 我知道MOD可能很昂贵,但只是进行简单的减法并写出currentClockTime的值就让我的间隙时间为6-7 ms。

The arduino has a semi-java like string concatenation. arduino有一个半java类似的字符串连接。 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. 如果你能够在另一Serial.Write建字符串,也许更好的做法是使用Serial.Write并发送原始数据,然后重建接收端的字符串。 This would reduce the amount of data you send each loop from 5-10 bytes to 3-4 bytes. 这会将每个循环发送的数据量从5-10个字节减少到3-4个字节。

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() ? 例如,使用类似snprintf()函数的东西写入预先分配的char[] ,然后在一次调用Serial.print()打印出来?

So for instance: 例如:

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

--Jason --Jason

流媒体库应该做你想要的:

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

I found the easiest way to Serial print a single string composed of integers and your words (message): 我找到了串行打印由整数和单词(消息)组成的单个字符串的最简单方法:

in scketch : 在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!!!!!!!!!!): 在串行监视器上,您将看到(作为单个LINE !!!!!!!!!!):

my number is: 12 - which is to be used in calculation! 我的号码是:12 - 用于计算!

The fastest and preferred way to do string concatenation under Arduino is, 在Arduino下进行字符串连接的最快和首选方法是,

  • Use the String class. 使用String类。
  • 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() . 如果您确实需要速度和/或只是想避免在每次连接操作中创建新的内存中字符串,请使用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 . 然后,通过调用concat()或operator + =附加所需的字符或字符串, 每行代码使用一个concat()或+ =操作 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. 通过预先执行reserve(),String对象将有效地充当行缓冲区。

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, ie: maximum number of characters you need before String does a realloc(), not including the null-terminating character '\\0'. 请注意,应使用最适合行缓冲区容量的值调用reserve(),即:String执行realloc()之前所需的最大字符数,不包括空终止字符'\\ 0'。

Three alternatives follow: 以下三种选择:

1) Here is the sample code, 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) 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. 2)作为在setup()调用reserve()的替代方法,您可以使用具有所需(最大)长度的“模板”或虚拟字符串声明和初始化String。

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. 第一种方法允许您使用带有动态计算的最大长度值的reserve(),而当您有一个“模板”或已知的固定长度时,第二种方法会使您稍后要编写的字符串更加清晰。

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, 3) 如果您只需要将数据输出到输出流(通常是Serial),这是最快且最紧凑的代码,不需要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);

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). 注意:John Y的答案与我的最后一段代码完全相同,除了他“更简单”地阅读代码(假设你对操作符<<感觉很舒服,用作C ++流式语法糖)。 In some cases, however, using the Streaming library will generate slightly larger/slower code. 但是,在某些情况下,使用Streaming库会生成稍大/较慢的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM