hi... until i know there could be tons of options, this is the most easy to use and the less memory greedy i tried, it just traslates echo(dev, datas...) to a sequence of (dev)->print(data); functions
// print up to 9 different variables concatenated in one line, to any Print* derived class pointer
// easy to use, inspired in echo() from php/bash/cmd.exe
// example: echo(&Serial, "rate = ", 27.1, '%');
// macros may look bloated but actually generate more efficient code than printf(), templates, or functions
// because just expand to a sequence of print() calls and don't consume additional ram or cycles
// released under Apache v2 license by atesin may-2025
// homepage: https://gitlab.com/-/snippets/4838085
#define echo(p, ...) ECHO_SEQ(LIST_TO_PAIRS(p,##__VA_ARGS__)(p,'\n')) /* could change '\n' to "\r\n" */
// helper macros
#define ECHO_SEQ(seq) do{XCAT(ECHO_A seq,_END)}while(0)
#define ECHO_A(p,x) (p)->print(x);ECHO_B
#define ECHO_B(p,x) (p)->print(x);ECHO_A
#define ECHO_A_END
#define ECHO_B_END
// auxiliary macros
#define HAS_ARGS(...) EVAL_ARGS(DUMMY,##__VA_ARGS__,1,1,1,1,1,1,1,1,1,0)
#define NUM_ARGS(...) EVAL_ARGS(DUMMY,##__VA_ARGS__,9,8,7,6,5,4,3,2,1,0)
#define EVAL_ARGS(DUMMY,_9,_8,_7,_6,_5,_4,_3,_2,_1,RESULT,...) RESULT
#define XCAT(a,b) CAT(a,b)
#define CAT(a,b) a ## b
// convert list to sequence
#define LIST_TO_PAIRS(p,...) XCAT(PAIRS_,NUM_ARGS(__VA_ARGS__))(p,##__VA_ARGS__)
#define PAIRS_0(p)
#define PAIRS_1(p,x1) (p,x1)
#define PAIRS_2(p,x1,x2) (p,x1)(p,x2)
#define PAIRS_3(p,x1,x2,x3) (p,x1)(p,x2)(p,x3)
#define PAIRS_4(p,x1,x2,x3,x4) (p,x1)(p,x2)(p,x3)(p,x4)
#define PAIRS_5(p,x1,x2,x3,x4,x5) (p,x1)(p,x2)(p,x3)(p,x4)(p,x5)
#define PAIRS_6(p,x1,x2,x3,x4,x5,x6) (p,x1)(p,x2)(p,x3)(p,x4)(p,x5)(p,x6)
#define PAIRS_7(p,x1,x2,x3,x4,x5,x6,x7) (p,x1)(p,x2)(p,x3)(p,x4)(p,x5)(p,x6)(p,x7)
#define PAIRS_8(p,x1,x2,x3,x4,x5,x6,x7,x8) (p,x1)(p,x2)(p,x3)(p,x4)(p,x5)(p,x6)(p,x7)(p,x8)
#define PAIRS_9(p,x1,x2,x3,x4,x5,x6,x7,x8,x9) (p,x1)(p,x2)(p,x3)(p,x4)(p,x5)(p,x6)(p,x7)(p,x8)(p,x9)
void setup() {
Serial.begin(115200);
int foo = 1, bar = 6;
echo(&Serial, foo, bar);
/* //
ECHO_SEQ(LIST_TO_PAIRS(&Serial,foo,bar)(&Serial,'\n'));
ECHO_SEQ(XCAT(PAIRS_,NUM_ARGS(foo,bar))(&Serial,foo,bar)(&Serial,'\n'));
ECHO_SEQ(XCAT(PAIRS_,EVAL_ARGS(DUMMY,foo,bar,9,8,7,6,5,4,3,2,1,0))(&Serial,foo,bar)(&Serial,'\n'));
ECHO_SEQ(XCAT(PAIRS_,2)(&Serial,foo,bar)(&Serial,'\n'));
ECHO_SEQ(CAT(PAIRS_ ## 2)(&Serial,foo,bar)(&Serial,'\n'));
ECHO_SEQ(PAIRS_2(&Serial,foo,bar)(&Serial,'\n'));
ECHO_SEQ((&Serial,foo)(&Serial,bar)(&Serial,'\n'));
do{XCAT(ECHO_A (&Serial,foo)(&Serial,bar)(&Serial,'\n'),_END)}while(0);
do{CAT(ECHO_A (&Serial,foo)(&Serial,bar)(&Serial,'\n') ## _END)}while(0);
do{ECHO_A (&Serial,foo)(&Serial,bar)(&Serial,'\n')_END}while(0);
do{(&Serial)->print(foo);ECHO_B(&Serial,bar)(&Serial,'\n')_END}while(0);
do{(&Serial)->print(foo);(&Serial)->print(bar);ECHO_A(&Serial,'\n')_END}while(0);
do{(&Serial)->print(foo);(&Serial)->print(bar);(&Serial)->print('\n');ECHO_B_END}while(0);
do{(&Serial)->print(foo);(&Serial)->print(bar);(&Serial)->print('\n');}while(0);
// */
}
void loop(){}
... since many time i was scratching my head trying to find a way for Serial class to print different variables like Serial.print("rate = ", 61.8, '%'); ... it doesn't work that way, also there are MANY related posts (enable printf, install a buffered print class, use templates, etc.) but all these are complicated and unefficient
i developed a set of macros for this common use, it was inspired in echo from php, bash, cmd, etc... it accepts a Print* pointer as first parameter and a list of variables/constant to print to (currently up to 9)
here are some examples:
echo(&Serial, "rate = ", 61.8, '%');
if ( client = server.accept() ){
Print* rcon = &client // could also be Stream* since it extends from Print
echo(rcon, F("welcome user "), getUsername(client));
}
the code is here: arduino print concatenated data ($4838085) · Snippets · GitLab
you could make some adjusts if you want, like increase handled parameters, change end lines to "\r\n", fork it, make a library with this, report bugs with kindness, etc... would be also cool if you vote me if you like it
if you use it in some project or modify it would be nice if you mention me, this sketch was released under Apache v2 license
i wanted to do this because since arduino have no easy print/string concatenation or printf() funcion available, is really tedious, boring and error-prone to have to write code like
Serial.print("name = ");
Serial.print(name);
Serial.print(", rate = ");
Serial.print(61.8);
Serial.print('%');
...
Serial.println(".")
also, to enable printf() is a very technical (and also error-prone) task for most users, moreover printf() is somewhat hard to use and a VERY MEMORY HUGRY MONSTER, same as templates that DUPLICATES FUNCTIONS for every datatype found, all unsuitable for platforms with a little chip like popular arduinos
these macros just write code for you (sounds easy but cost me a lot to develop them, i am not a programmer), it just expand your echo(printer, ...) macro to a sequence of (printer)->print(x); functions to be processed in next stage by the compiler... these macros could look a little massive and compile a little slower, but the C code they produce is very efficient
