3
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.

1
  • Did you look at the output on an oscilloscope to see when the gap occurs? That could help narrow down the problem. Commented Apr 4, 2011 at 5:02

5 Answers 5

5

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I agree with your comment that the buffer would be a cleaner solution. But the time it takes to allocate that buffer and fill it with information actually takes longer (1-2ms) than your solution. While your is not the perfect solution for my needs it is a start. Thanks for the assistance.
The benefit of a buffer is that you'd only need to allocate it once, as well as not needing to allocate it at the time you're using it. I haven't tested it out specifically, but that's something you could try out.
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()?

So for instance:

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

--Jason

1 Comment

The drawback of using any variant of printf() is that your code size will increase ~1-2KB.
4

The Streaming library should do what you want:

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

Comments

1

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.

1 Comment

The drawback of using the String library of Arduino is that your code size will increase ~1-2KB. By directly applying print()/println() to Serial, you can avoid this increase in code size.
0

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!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.