HOWTO · Arduino
Arduino Função printf
Pode-se obter a mesma saída que printf() usando a função sprintf() e a função Serial.print().
Nesta página
O ambiente padrão de programação do Arduino não oferece uma chamada printf() portátil que escreva no monitor serial. Alguns núcleos de placa acrescentam seu próprio método Serial.printf(), então consulte a documentação da placa escolhida. Para sketches portáteis, formate o texto em um buffer de caracteres com sprintf() e envie-o com Serial.print() ou Serial.println(). Se você não precisar de uma string de formato, várias chamadas seriais podem montar a mesma mensagem diretamente.
O Arduino oferece printf()?
Não há uma única interface printf() garantida em todas as placas Arduino. Em geral, printf() da biblioteca C escreve em um fluxo de saída padrão, que pode não estar conectado a uma porta serial em um ambiente de microcontrolador. Pode haver um Serial.printf() específico do núcleo, mas sua disponibilidade e os especificadores de formato compatíveis dependem do alvo. Os sketches abaixo usam setup() e loop() e escrevem por meio de Serial; uma pequena implementação substituta de serial no computador permite executar os mesmos exemplos sem uma placa Arduino. Na placa, o núcleo Arduino fornece Serial e o ciclo de vida do sketch.
Formate o texto com sprintf() e envie-o pela serial
Use sprintf() quando a mensagem precisar de marcadores de posição ou preenchimento. A função grava o texto completo em um array de caracteres; em seguida, Serial.println() envia esse texto e uma quebra de linha. Este sketch usa snprintf() para informar ao formatador a capacidade do array e verifica se a mensagem completa cabe antes de enviá-la:
#include <cstdio>
#ifdef ARDUINO
#include <Arduino.h>
#else
class HostSerial {
public:
void begin(unsigned long) {}
void println(const char* text) { std::puts(text); }
};
HostSerial Serial;
#endif
void setup() {
Serial.begin(9600);
char buffer[32];
const int value = 42;
const int length = std::snprintf(buffer, sizeof(buffer), "The answer is: %d", value);
if (length >= 0 && static_cast<unsigned int>(length) < sizeof(buffer)) {
Serial.println(buffer);
}
}
void loop() {}
#ifndef ARDUINO
int main() {
setup();
return 0;
}
#endif
The answer is: 42
snprintf() retorna o número de caracteres que escreveria, sem contar o caractere nulo terminador. Se essa quantidade for igual ou maior que a capacidade do array, o sketch não envia uma mensagem parcial. Verifique se a biblioteca C da placa escolhida oferece snprintf() conforme esperado; a disponibilidade e o comportamento das funções de formatação podem variar conforme a placa e o núcleo.
Monte a saída com Serial.print()
Para rótulos e valores simples, chamadas diretas evitam um buffer temporário de formatação. Serial.print() continua na mesma linha; Serial.println() encerra a linha. Este sketch monta a mesma linha com chamadas seriais:
#include <cstdio>
#ifdef ARDUINO
#include <Arduino.h>
#else
class HostSerial {
public:
void begin(unsigned long) {}
void print(const char* text) { std::printf("%s", text); }
void print(int value) { std::printf("%d", value); }
void print(double value, int digits) { std::printf("%.*f", digits, value); }
void println(const char* text) { std::printf("%s\n", text); }
};
HostSerial Serial;
#endif
void setup() {
Serial.begin(9600);
const int temperature = 25;
const double humidity = 60.5;
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" C, Humidity: ");
Serial.print(humidity, 1);
Serial.println("%");
}
void loop() {}
#ifndef ARDUINO
int main() {
setup();
return 0;
}
#endif
Temperature: 25 C, Humidity: 60.5%
A implementação substituta de serial no computador reproduz as chamadas usadas aqui para mostrar a linha do sketch sem hardware; ela não é um núcleo Arduino. Na placa, Serial.print(humidity, 1) solicita um dígito após o separador decimal, e a formatação exata disponível depende da implementação de Serial da placa.
Lide com valores de ponto flutuante e limites do buffer
A formatação de valores de ponto flutuante por meio de sprintf() não é uniforme entre os núcleos Arduino: algumas bibliotecas C para sistemas embarcados omitem a conversão de ponto flutuante da E/S formatada para economizar memória de programa. Verifique o núcleo do alvo antes de depender de %f. A forma direta Serial.print(value, digits) é uma alternativa quando o núcleo oferece a implementação usual de Print do Arduino.
Qualquer saída formatada precisa caber no array de caracteres, incluindo o \0 terminador. Quando disponível, use snprintf() com a capacidade real do array e confira o valor de retorno antes de usar o resultado. Se o texto formatado for maior que o array, aumente o buffer ou encurte a mensagem. Um buffer maior consome mais RAM, que é limitada em muitas placas.
Escolha a abordagem certa
Escolha sprintf() ou snprintf() quando uma única string de formato tornar uma mensagem estruturada mais fácil de ler e envie o resultado com Serial.println(). Escolha chamadas de Serial.print() quando precisar apenas combinar alguns rótulos e valores. As duas abordagens enviam texto pela interface serial; nenhuma garante o mesmo suporte à formatação em todas as placas. Confira os métodos específicos do núcleo e o comportamento com valores de ponto flutuante na placa para a qual você compila.