Массив float в строку, разделенную запятыми
У меня есть команда цикла, считывающая данные датчика температуры с 8 термисторов и сохраняющая их в виде float в массиве. Вместо того, чтобы печатать в Serial на каждой итерации, я хотел бы создать разделенную запятыми строку этих значений и отправить в serial (в одном экземпляре вместо 8). Каков был бы наилучший способ сделать это? Я пробовал использовать команды sprintf, но безрезультатно.
Заранее спасибо!
Редактировать: я хотел бы также записать эту строку значений, разделенных запятыми, в слот для карт microSD, поэтому я предполагаю, что создание строки один раз, печать в последовательный формат и сохранение на карту microSD более эффективны, чем 8 отдельных итераций
@NRav, 👍0
Обсуждение2 ответа
Лучший ответ:
Базовые Arduino не поддерживают плавающую точку в sprintf
и связанных с ней функциях.
Вместо этого вы должны использовать dtostrf()
для создания строки блок за блоком.
Однако нет никакой пользы в создании строки, а затем в выводе в serial "в одном экземпляре" по сравнению с выводом данных по частям за раз. Сериал идет медленно. Очень медленно. Когда вы "выводите" данные в serial, вы не выводите данные. Вы просто помещаете данные в буфер для отправки, когда это возможно.
По сути, используя несколько вызовов Serial.print()
, вы создаете строку для отправки во внутренний буфер последовательной передачи данных Arduino.
Сначала создавая строку, все, что вы делаете, - это создаете буфер для копирования данных в буфер для отправки их по последовательному каналу. Это излишне, расточительно и совершенно бессмысленно.
Спасибо за ответ и описание @Majenko. Мне тоже следовало бы упомянуть об этом, но я планировал также записать строку значений, разделенных запятыми, на карту microSD. Я подумал, что было бы лучше регистрировать данные один раз, а не 8 раз каждый void loop ()
- следовательно, почему создание строки может быть оптимальным, @NRav
Те же мысли применимы и для записи на SD. (file.print записывает только в буфер) В любом случае, вам следует подумать о вызове flush или close / open реже, чем после каждой печати., @DataFiddler
Спасибо @DataFiddler. Я постараюсь избежать создания строк и просто отправлю запись в Serial / SD по мере поступления данных., @NRav
Вот пример программы, использующей sprintf() для преобразования некоторых данных с плавающей запятой в ASCII в буфере, форматирования выходной строки, содержащей эти данные, в другой буфер и печати результата на терминале. Это не совсем так аккуратно, как
"sprintf(buffer, "i=%2d, T=%f\n", i, Temp);
Это занимает три строки и два буфера, но он выполняет свою работу:
#include <Arduino.h>
float getTemp(void);
void setup()
{
char tempBuf[10+1], outputBuf[50+1];
// Открыть консоль
Serial.begin(115200);
// Выведите 20 последовательных значений температуры на терминал
for( uint8_t i = 1; i <= 20; ++i){
float Temp;
Temp = getTemp(); // получаем следующее значение
dtostrf(Temp, 6, 2, tempBuf); // Преобразовать float в ASCII
sprintf(outputBuf, "i=%2d, T=%s\n", i, tempBuf); // формат значения для печати
Serial.print(outputBuf); // вывести строку на терминал
delay(1000L);
}
}
// Функция возврата температуры.
// ЗАГЛУШКА: данные выдуманы.
float getTemp(void){
static uint8_t n = 0; // количество возвращенных результатов
return( (float)n++ * 1.7 ); // индекс 'n', умноженный на произвольный множитель
}
void loop(void)
{
;
}
- strcmp, похоже, не работает
- Хранение значений широты и долготы в виде символов с заданной точностью
- Чтение из SPIFFS - Как лучше всего работать со строковым (или char) массивом с неопределенной длиной?
- Как преобразовать строку в шестнадцатеричный массив
- Ввод строки в массив символов
- Как отсортировать строку с числом по возрастанию
- Прокрутка текста I2C
- Ничего не получено от функции, возвращающей массив строк
Похоже, вы ожидаете, что последовательная связь будет похожа на пакет конфет. Все это находится в одном месте в одно и то же время. На самом деле последовательная связь больше похожа на это: https://www.youtube.com/watch?v=jv9qaPAlK_g, @Majenko
Если термистор на самом деле не выдает результаты с плавающей запятой, ваш код может выполнять меньше работы, сохраняя данные с фиксированной запятой и преобразуя их. Массив будет меньше, и вы сможете использовать любую из функций семейства printf() для форматирования ваших выходных данных, если это будет полезно, включая однократную генерацию данных ASCII в памяти, а затем отправку их на оба устройства (независимо от того, обрабатываете ли вы 1 или все 8 результатов за один раз)., @JRobert
@JRobert - сможете ли вы предоставить пример
printf ()
? Я думаю, что для чистоты это было бы идеально. И я получаю значения с плавающей запятой от термисторов, @NRavЯ был бы рад, за исключением того факта, что функции библиотеки Arduino printf() исключают преобразования с плавающей запятой. Если вам не нужны никакие десятичные знаки, то мы могли бы это сделать. Даже если вам нужна пара десятичных знаков - но тогда это начинает запутываться, потому что вам нужно будет извлечь целое число градусов и дробный остаток, округленный до n-разрядов, и преобразовать их по отдельности. Это выполнимо, но вы теряете часть прямоты и простоты выражения, которые призвана предложить функция printf()., @JRobert
... В этой ситуации я использую dtostrf() для преобразования числа с плавающей запятой в ASCII в одном буфере, затем форматирую все оставшиеся выходные данные с помощью printf() - или sprintf() - используя строковые версии чисел с плавающей запятой в формате ASCII, на последовательное устройство или в другой буфер соответственно. Это выполнимо, но код выглядит не так красиво, как если бы функции printf() выполняли всю работу сразу., @JRobert
Черт возьми, моя идея, которая, как я думал, была ясной логикой, вероятно, намного сложнее и занимает больше памяти, чем ожидалось. С таким же успехом я мог бы печатать на картах
serial
иmicroSD
в каждом контуре каждого считывания термистора. кажется чище. Спасибо за объяснение (объяснения), @NRav