Массив float в строку, разделенную запятыми

У меня есть команда цикла, считывающая данные датчика температуры с 8 термисторов и сохраняющая их в виде float в массиве. Вместо того, чтобы печатать в Serial на каждой итерации, я хотел бы создать разделенную запятыми строку этих значений и отправить в serial (в одном экземпляре вместо 8). Каков был бы наилучший способ сделать это? Я пробовал использовать команды sprintf, но безрезультатно.

Заранее спасибо!

Редактировать: я хотел бы также записать эту строку значений, разделенных запятыми, в слот для карт microSD, поэтому я предполагаю, что создание строки один раз, печать в последовательный формат и сохранение на карту microSD более эффективны, чем 8 отдельных итераций

, 👍0

Обсуждение

Похоже, вы ожидаете, что последовательная связь будет похожа на пакет конфет. Все это находится в одном месте в одно и то же время. На самом деле последовательная связь больше похожа на это: 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


2 ответа


Лучший ответ:

3

Базовые 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


0

Вот пример программы, использующей 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)
{
   ;
}

,