Хранение значений широты и долготы в виде символов с заданной точностью
Я получаю данные широты и долготы от GPS и хочу сохранить эти числа в середине последовательности символов.
Например, широта = -23,123456
длинный = 135.123456
Мне нужно что-то вроде "Ваши координаты -23.123456,135.123456" в виде массива символов.
Я пробовал:
float latitude = -23.123456;
float longitude = 135.123456;
String one = "Your coordinates are ";
String two = ","
String message = one + latitude + two + longitude;
// Преобразование строки в массив символов
int str_len = message.length() + 1;
char textmessage[str_len];
message.toCharArray(textmessage,str_len);
Serial.println(textmessage);
но результат: Ваши координаты -023.12,0135.12
Как это исправить?
Заранее спасибо!
@Anwar, 👍0
Обсуждение1 ответ
Если форматирование последовательного вывода вызывает беспокойство, стоит загрузить и использовать Streaming.h
предоставленная библиотека, которая добавляет некоторый «синтаксический сахар» в Arduino C. То есть во время компиляции она преобразует C++-подобные операторы последовательного потока <<
в Serial.print
без увеличения размера кода. Если у вас не установлен Streaming.h
, вы можете получить Streaming5.zip
с сайта arduiniana.org.
В настоящее время Streaming.h
не поддерживает setw()
и setfill()
, которые в обычном C++ устанавливают ширину поля и заполняющий символ.
Однако он поддерживает четыре спецификатора преобразования базы: _HEX, _DEC, _OCT и _BIN; функция _FLOAT с указанным количеством знаков после запятой; и endl
.
Таким образом, чтобы напечатать «Ваши координаты -23.123456, 135.123456», нужно написать:
Serial << "Your coordinates are " << _FLOAT(latitude,6) << ", " << _FLOAT(longitude,6) << endl;
Обратите внимание, что в отличие от класса String
использование Streaming.h
не влечет за собой какого-либо динамического управления памятью — все, что он делает, происходит во время компиляции — и не увеличивает размер кода — он переводит потоковые операции в обычные вызовы .print()
и .println()
. Это должно привести к несколько меньшему, более быстрому и более надежному коду за счет исключения String
. Использование динамической памяти во встроенных системах с небольшим объемом памяти может быть проблематичным, и это позволяет избежать этих проблем.
Редактировать 1a: Как отмечает Крис Страттон, числа с плавающей запятой Arduino не поддерживают 9-значную точность. Я думаю, что арифметика с плавающей запятой в Arduino предназначена для соответствия IEEE 754, который устанавливает стандарты для использования на современных компьютерах, поддерживать арифметику с плавающей запятой.
В формате binary32, используемом для реализации стандарта IEEE 754 single-point точность двоичного числа с плавающей запятой, точность мантиссы составляет 24 бита. Это соответствует примерно 7,22 десятичных разряда (т. е. 24*log₁₀(2)), поэтому для простых вычислений реалистична точность до 7 знаков, более того — нет.
[Часть] Редактировать 1b: В более широком смысле, возможно, нет необходимости создавать и сохранять форматированную строку, подобную этой. Это бесполезно для вычислений — для этого лучше подходят значения с плавающей запятой. Для связи это не требуется — можно выполнить другую потоковую запись.
Изменить 2 [заменяет большую часть 1b]: Streaming.h не создает никаких строк, а просто доставляет текст своего символа <<
-arguments -посимвольно в поток. Однако класс PString в arduiniana может создавать строки из входных потоков, как в следующем примере кода.
#include <Streaming.h>
#include <PString.h>
char buffer[28];
PString pstr(buffer, sizeof(buffer));
void setup() {
Serial.begin(115200);
pstr.begin(); // Очистить буфер
}
void loop() {
int first=50, second=100;
pstr.begin(); // Очистить буфер
pstr << 'X' << first << 'Y' << second << 'T';
pstr += " hihi ";
pstr << millis() << endl;
Serial << pstr;
delay(1000);
}
Вот как выглядит часть его вывода в Serial:
X50Y100T hihi 263198
X50Y100T hihi 264199
X50Y100T hihi 265199
X50Y100T hihi 266201
X50Y100T hihi 267201
X50Y100T hihi 268201
В примере кода сначала инициализируется строковый буфер, затем создается часть символьной строки с помощью оператора потоковой передачи <<
, затем часть с помощью конкатенации, затем еще немного с помощью <<
, затем напечатайте строку. Обратите внимание, что задействованные здесь строки находятся в фиксированных буферах, а не в динамически выделенных буферах, как это использует класс String.
Возможно, вы можете сделать лучше, чем код в вопросе, но вы * не * получите желаемую точность от «поплавка» Arduino Uno на базе ATmega., @Chris Stratton
Спасибо! Однако мне нужно сохранить эту напечатанную последовательность как массив символов, который будет использоваться позже в коде. Можно ли это сделать из напечатанного Serial <<... ?, @Anwar
@ChrisStratton, отражено в Edit 1a, @James Waldby - jwpat7
@ Анвар, см. Редактировать 1b, @James Waldby - jwpat7
Несмотря на то, что потоковая библиотека — это приятная синтаксическая конфета, вам не нужно указывать количество цифр для печати. Вы также можете использовать Serial.print(широта, 6);
., @Edgar Bonet
@ ЭдгарБонет, правда. Но если кто-то выполняет большое количество операций форматирования (т. е. случай «Когда форматирование последовательного вывода вызывает беспокойство»), Streaming.h помогает сделать код компактным и более четким, чем длинная серия распечаток. (Мое первоначальное прочтение вопроса, возможно, неправильное, предполагало проблемы с форматированием, а не проблемы с получением строки.), @James Waldby - jwpat7
Спасибо за участие, ребята. Однако я ищу решение, которое не считывает строку из последовательного окна (как предложено в Edit 1b), так как в конечном итоге я буду использовать этот модуль без подключения к компьютеру., @Anwar
@Анвар, редактирование 2 объясняет, как построить строку, используя класс PString
. В любом случае, 1a и 1b были о том, как отправлять данные через Serial, без предложения «прочитать строку из окна Serial»., @James Waldby - jwpat7
- Как преобразовать строку в шестнадцатеричный массив
- Ввод строки в массив символов
- Float печатается только 2 десятичных знака после запятой
- Отправка и получение различных типов данных через I2C в Arduino
- GPS-модуль uBlox Neo 6M не отвечает
- Очень простая операция Arduino Uno Serial.readString()
- Как преобразовать строку в массив байтов
- Как отправить строку с подчиненного устройства Arduino с помощью SPI?
Действительно ли ваш GPS дает вам «поплавок»? Большая часть выводимого текста на последовательный порт; если вам не нужно выполнять числовые операции со значениями, возможно, вам следует просто обрабатывать их как текст на всем протяжении. Обратите внимание, что если вы используете
float
, их точность ограничена, что вполне может быть причиной того, что вы видите с вашими поддельными тестовыми данными., @Chris StrattonВы уверены в своем результате? Пробую ваш код и получаю "Ваши координаты -23.123456,135.123456". На всякий случай, если вы не заметили, вы пропустили один
;
, @dhimaspwОтносительно ограниченной точности формата float32: для чисел в диапазоне \[128, 256) (например, ваша долгота) [единица измерения на последнем месте](https://en.wikipedia.org/wiki/Unit_in_the_last_place) около 1,53e-5, что соответствует разрешению 1,7 м на поверхности Земли. Присвоение долготы «поплавку» может привести к ошибке округления до половины ulp или около 85 см., @Edgar Bonet
Почему бы просто не использовать функцию члена String c_str() для доступа к массиву символов?
message.c_str()
https://www.arduino.cc/en/Reference/CStr, @Mikael Patel