Как отправить поплавок через серийный - PullRequest
7 голосов
/ 17 июля 2010

Какой лучший способ отправить float, double и int16 через серийный номер на Arduino?

Serial.print() отправляет только значения в кодированном виде ASCII . Но я хочу отправить значения в байтах. Serial.write() принимает байты и байтовые массивы, но как лучше преобразовать значения в байты?

Я безуспешно пытался разыграть int16 на byte*. Я также использовал memcpy, но это использует для многих циклов процессора. Arduino использует простой C / C ++. Это микроконтроллер ATmega328 .

Ответы [ 7 ]

10 голосов
/ 17 июля 2010

гм. Как насчет этого:

void send_float (float arg)
{
  // get access to the float as a byte-array:
  byte * data = (byte *) &arg; 

  // write the data to the serial
  Serial.write (data, sizeof (arg));
}
9 голосов
/ 17 июля 2010

Да, чтобы отправить эти числа, вы должны сначала преобразовать их в ASCII строки.Если вы работаете с C, sprintf(), IMO, самый удобный способ сделать это преобразование:

[Добавлено позже: AAAGHH! Я забыл, что для ints / longs, входной аргумент функции хочет быть без знака.Аналогично для строки формата, переданной sprintf().Поэтому я изменил это ниже.Извините за мой ужасный недосмотр, который был бы трудно найти ошибкой.Кроме того, ulong делает его немного более общим.]

char *
int2str( unsigned long num ) {
    static char retnum[21];       // Enough for 20 digits plus NUL from a 64-bit uint.
    sprintf( retnum, "%ul", num );
    return retnum;
}

И аналогично для чисел с плавающей запятой и двойников.Код, выполняющий преобразование, был известен заранее.Нужно сказать - какой тип сущности он конвертирует, так что вы можете в конечном итоге получить функции char *float2str( float float_num) и char *dbl2str( double dblnum).

. Вы получите NUL-концевую регулировку влево (без начальных пробелов).или обнуляет) символьную строку вне преобразования.

Вы можете выполнить преобразование в любом месте / в любом месте;Эти функции являются просто иллюстрациями.

3 голосов
/ 07 сентября 2010

Используйте протокол Firmata . Цитата:

Firmata - это общий протокол для связи с микроконтроллерами. из программного обеспечения на главном компьютере. Предназначен для работы с любым хостом компьютерный пакет программного обеспечения. Прямо сейчас есть соответствующий объект в количество языков. Легко добавлять объекты для другого программного обеспечения в используйте этот протокол. В основном эта прошивка устанавливает протокол для общаюсь с Arduino с хост-программы. Цель состоит в том, чтобы позволить люди, чтобы полностью контролировать Arduino из программного обеспечения на хосте компьютер.

2 голосов
/ 07 сентября 2010

Жаргонное слово, которое вам нужно найти, это «сериализация».

Это интересная проблема, связанная с последовательным соединением, которая может иметь ограничения в отношении того, какие символы могут идти от конца к концу, и может быть не в состояниипередать также восемь битов на символ.

Ограничения на определенные коды символов довольно распространены.Вот некоторые из них:

  • Если используется программное управление потоком данных, то условно управляющие символы DC1 и DC3 (Ctrl-Q и Ctrl-S, также иногда называемые XON и XOFF)) не могут быть переданы как данные, поскольку они отправляются для запуска и остановки отправителя на другом конце кабеля.

  • На некоторых устройствах символы NUL и / или DEL (0x00 и 0x7F) может просто исчезнуть из FIFO получателя.

  • Если получателем является Unix tty, а режимы termio установлены неправильно, то символ Ctrl-D (EOT или 0x04) можетзаставить tty драйвер сигнализировать конец файла процессу, у которого открыт tty.

Последовательное соединение обычно настраивается для ширины байта и возможного включения бита четности.Некоторые соединения требуют использования 7-битного байта с четностью, а не 8-битного байта.Для подключения к (серьезно старому) устаревшему оборудованию даже возможно настроить много последовательных портов для 5-битного и 6-битного байтов.Если на байт доступно менее 8 битов, то для обработки двоичных данных требуется более сложный протокол.

ASCII85 - это популярный метод для работы как с 7-битными данными, так и с ограничениями на управляющие символы.Это соглашение для перезаписи двоичных данных с использованием только 85 тщательно отобранных кодов символов ASCII.

Кроме того, вам, безусловно, следует беспокоиться о порядке следования байтов между отправителем и получателем.Возможно, вам также придется беспокоиться о формате с плавающей запятой, поскольку не каждая система использует IEEE-754.

Суть в том, что достаточно часто выбор чистого протокола ASCII - лучший ответ.Он имеет преимущество в том, что его может понять человек, и гораздо более устойчив к проблемам с последовательным соединением.Если вы не отправляете кучу данных с плавающей запятой, неэффективность представления может перевесить из-за простоты реализации.

Просто будьте либеральными в том, что вы принимаете, и консервативными в том, что вы излучаете.

0 голосов
/ 09 октября 2017

Структуры и профсоюзы решают эту проблему. Используйте упакованную структуру с объединением байтового размера, соответствующим структуре. Перекрыть указатели на структуру и объединение (или добавить объединение в структуре). Используйте Serial.write для отправки потока. Иметь подходящую структуру / соединение на приемном конце. Если порядок следования байтов не имеет значения, в противном случае вы можете распаковать, используя функции "C" hto (s..l) Добавить информацию заголовка для декодирования различных структур / объединений.

0 голосов
/ 23 апреля 2014

Возможно, это лучший способ конвертировать Float в байты, а Byte в Float, - Хамид Реза.

int breakDown(int index, unsigned char outbox[], float member)
{
  unsigned long d = *(unsigned long *)&member;

  outbox[index] = d & 0x00FF;
  index++;

  outbox[index] = (d & 0xFF00) >> 8;
  index++;

  outbox[index] = (d & 0xFF0000) >> 16;
  index++;

  outbox[index] = (d & 0xFF000000) >> 24;
  index++;
  return index;
}


float buildUp(int index, unsigned char outbox[])
{
  unsigned long d;

  d =  (outbox[index+3] << 24) | (outbox[index+2] << 16)
    | (outbox[index+1] << 8) | (outbox[index]);
  float member = *(float *)&d;
  return member;
}

С уважением. `

0 голосов
/ 17 июля 2010

Имеет ли значение размер?Если это так, вы можете кодировать каждую 32-битную группу в 5 символов ASCII, используя ASCII85, см. http://en.wikipedia.org/wiki/Ascii85.

...