Отправка поплавков из Arduino в Python с использованием структуры - PullRequest
0 голосов
/ 09 октября 2019

Я использую перо Bluefruit для отправки информации от датчика температуры на скрипт Python на моем компьютере через BLEUART.

У меня есть рабочая версия этого кода для акселерометра, единственное отличие заключается вчто отправленная информация составляет 4 дюйма (для акселерометра: x, y, z, id), против 2 поплавков для датчика температуры (temp, float id). Я проверил значения, которые датчик посылает через последовательный монитор, и они верны. Проблема возникает, когда поплавки распакованы в Python: их коэффициент примерно равен 1.36*e-45.

В обоих случаях я сохраняю переменные в структуре и отправляю эту структуру через BLE. Код пера выглядит так:

void sendData(){
  int numVals = 2;
  int vals[numVals];
  vals[0] = temp; 
  vals[1] = id; //1.0
  Serial.println(temp);
  Serial.println(id);  
  int cnt = numVals * sizeof(float) ;
  uint8_t buf[cnt];
  for (int _i=0; _i<numVals; _i++)
    memcpy(&buf[_i*sizeof(float)], &vals[_i], sizeof(float));
  bleuart.write( buf, cnt );
}

А на конце Python это выглядит так:

def received(data):
    floats = struct.unpack('ff', data)
    print('Received:', floats)

Это действительно таинственно! У меня есть ощущение, что это как-то связано с тем, как поплавки представлены между C и Python, но я пытался изменить значения на longs / unsigned longs, и он либо вылетел, либо имел схожие проблемы.

1 Ответ

1 голос
/ 12 октября 2019

Проблема, которую вы представляете, на самом деле является более широкой, касающейся того, как объекты сериализуются и десериализуются в разных операционных системах, архитектурах машин, разных компиляторах и т. Д.

В частности, вам следует обратить внимание на:

  • как структуры отображаются в физической памяти - не гарантируется, что ваша структура занимает минимально возможное пространство в памяти. Фактически, вполне вероятно, что компилятор вводит пропуски между полями для оптимизации скорости доступа к памяти (см. этот вопрос SO ).
  • machine Endianess , что является порядкомв котором многобайтовые примитивы (такие как float) хранятся в памяти

Чтобы решить вашу проблему, вы можете либо разработать собственную схему (например, сконфигурировать компилятор для плотной упаковки структур впамять - см. атрибут gcc packed) и всегда кодирует числа с плавающей точкой как big-endian. Еще лучше то, что вы можете использовать такую ​​инфраструктуру, как буфер протокола Google , которая является кросс-языковой, кросс-платформенной, кросс-платформенной и любой другой, чтобы справиться с сериализацией для вас.

Лично я бы выбрал вариант II, хотя он привносит некоторые накладные расходы.

...