Arduino Serial.print()优化

时间:2011-04-04 03:27:35

标签: c serial-port arduino

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 ms。有没有办法优化Serial.print()方法,以允许跨long和String值类型写入多个值?

示例(这是无效的,但与我的想法一致):

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

我知道这不是我正在研究的JavaScript - 只是寻找写作过程的优化可能性。我知道MOD可能很昂贵,但只是做了简单的减法并且写出 currentClockTime 的值让我的间隙时间为6-7毫秒。

5 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:3)

Streaming库应该做你想做的事情:

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

答案 2 :(得分:2)

任何方法都可以将所有内容预转换为字符串值,以便您可以立即写出整个字符串?例如,使用snprintf()函数之类的内容写入预先分配的char[],然后通过一次调用Serial.print()打印出来?

例如:

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

- 詹森

答案 3 :(得分:0)

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

在scketch:

int w = 12;

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

Serial.Print (w);

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

结果:

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

我的号码是:12 - 用于计算!

答案 4 :(得分:0)

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

  • 使用String类。
  • 如果您确实需要速度和/或只是想避免在每次连接操作中创建新的内存中字符串,使用reserve()提前保留所需的内存。
  • 首先,将对象设置为空字符串“”。
  • 然后,通过调用concat()或operator + =,追加所需的字符或字符串,每行使用一行concat()或+ =操作。这是为了避免创建临时字符串对象。
  • 通过事先执行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()的替代方法,您可以使用“模板”或具有所需(最大)长度的虚拟字符串声明和初始化String。

以下是此备选方案的示例代码

// 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的答案与我的最后一段代码完全相同,除了他阅读代码的“更简单”(假设您对操作符感到满意&lt;&lt;,用作C ++流式语法糖) 。但是,在某些情况下,使用Streaming库会生成稍大/较慢的代码。

相关问题