Новичкам, задолбавшимся печатать бесконечные Serial.print() да Serial.println() c каждой переменной, которую они хочут вывести, могу посоветовать открыть файл Print.h и в описание класса в конец вставить вот это Код (C++): size_t printf(const char *format, ...) { const uint8_t MAX_STRING_SIZE = 64; char buf[MAX_STRING_SIZE]; va_list args; va_start(args, format); vsnprintf(buf, MAX_STRING_SIZE, format, args); va_end(args); return print(buf); } и тогда все свои переменные можно писать в одну строчку со всеми плюшками стандартной функции printf() Описание форматов можно почитать у DIHALT: http://we.easyelectronics.ru/Soft/formatnyy-vyvod-na-si-dlya-mikrokontrollerov.html Теперь лехко можно писать Код (C++): const uint8_t ARRAY_SIZE = 100; int Array[ARRAY_SIZE]; for (uint8_t i = 0; i < ARRAY_SIZE; i++) Array[i] = 10*i; const char *Prompt = "Line"; for (uint8_t i = 0; i < ARRAY_SIZE; i++) { Serial.printf("%s%-3d: Array[%d] = \t%d\n", Prompt, i + 1, i, Array[i]); } Если у каво вдруг возникнут трудности с прикручиванием, пишите, я покажу куда.
Добавлю свои 5 копеек. Этот же принцип можно использовать и в других классах, например, для вывода текста на дисплей... Единственное, что нужно помнить, так это то, что "вдруг" увеличился размер прошивки...
тут выбирать надо, удобно, или размер прошивки. Хотя, я это в define заворачиваю, ибо сериал пользую только для отладки. В готовой поделке никакова вывода printf-ом нет.
для этого в заголовке темы и стоит фраза "и не только". Все, што унаследуешь от Print, подхватит это прям "искаропки"
Статью полностью осилить так и не смог? (Понимаю, что Дед выпилися из форума, поэтому вопрос скорее риторический) Что касается представленного "велосипеда" -- тут нужно оговориться, что тот, кто будет пользоваться данным советом, должен в голове держать мысль: "длина результирующей строки не должна превышать 63 символа". Потому как автор использует буфер размером MAX_STRING_SIZE = 64. Конечно же ни кто не мешает этот буфер увеличить. Но только всё равно задача определения размера буфера ложится на плечи программиста. При чём задача эта не такая уж и простая, как может показаться на первый взгляд. Вот к примеру, простой формат "%s - %d". Какого размера должен быть буфер? Ответ будет только тогда, когда программист определится какие строки и какие числа будут выводиться при помощи форматированного вывода. Эта была критика, а теперь к делу. В контексте задачи вывода форматированного текста в последовательный порт, более красивым решением будет переопределение стандартного вывода. В статье DiHALT'а про это подробно написано, повторяться не буду. Но на чём стоит заострить внимание -- код приведённый в статье будет работать только при использовании исходников на языке C с соответствующим компилятором, с языком C++ при компилировании получите ошибку: "sorry, unimplemented: non-trivial designated initializers not supported". Суть в том, что C++ не умеет обрабатывать декларации структур типа: Код (C++): FILE mystdout = { .put = p, .get = g, .flags = f, .udata = 0, } Внутри блока инициализации должны быть перечислены все поля структуры в правильном порядке. А в данной декларации перечислены только нужные поля. Казалось бы "да что тут такого?". Проблема в том, что многие пользуются Arduino IDE, а в этой среде C++ используется по умолчанию (правда, он там немного доработан и некоторые его называют языком Wiring). И что же делать? Можно применить не большой костыль. Костыль этот относится к разряду "говнокода", но всё же не такого вонючего как предложил автор темы. Суть в следующем -- сначала определяем структуру типа FILE, а потом назначаем нужные поля и переопределяем стандартный поток ввода/вывода: Код (C++): // Определяем структуру, которая будет использоваться для замены стандартного потока вывода FILE mystdout; // Функция вывода символа, будет использоваться для вывода символа в наш поток вывода static int my_putchar(char c, FILE *stream) { Serial.write(c); return 0; } //The setup function is called once at startup of the sketch void setup() { Serial.begin(115200); // А вот здесь начинается наш костыль. // Костыль потому, что внутреннее устройство структуры FILE может поменяться без предупреждения // и наш код перестанет компилироваться на какой-нибудь новой версии компилятора. // Назначаем функцию 'my_putchar', как функцию вывода символов в нашем потоке вывода mystdout.put = my_putchar; // Говорим. что наш поток будет работать только на вывод mystdout.flags = _FDEV_SETUP_WRITE; // Костыль закончен // Переопределяем стандартный поток вывода нашим потоком stdout = &mystdout; // Всё. // Можно использовать стандартные функции типа printf, для вывода в последовательный интерфейс // Все строки после форматирования будут посимвольно попадать в нашу функцию 'my_putchar', // которая будет их отправлять в Serial printf("Serial:\n"); } Пример использования в loop(): Код (C++): void loop() { int d = SPI.transfer(0); // Раньше было так: // Serial.print("Received: "); // Serial.println(d); // Сейчас так: printf("Received: %d\n", d); delay(500); } Ни каких буферов и лишних раздумий о размерах этих буферов, а так же не надо вмешиваться в потроха ардуиновских библиотек. PS: Правда стоит оговориться, применение данного подхода более затратно в плане потребления памяти микроконтроллера. Точных замеров не проводил, но где-то лишний килобайт Flash-а.