Преобразовать массив float в char на ATtiny85

Мне трудно преобразовать число с плавающей запятой в массив символов, чтобы он сохранялся как "7.125", точно так же, как выглядит число с плавающей запятой.

Я пытаюсь установить связь с ATtiny85 (подчиненный) и программой на Raspberry Pi (ведущий) через I2C.

Главное устройство ожидает от подчиненного устройства 31 байт при отправке ему данных.

Когда я использую этот код на ATtiny85, все работает как надо, Pi получает данные правильно.

    char computerdata[35]; 
    computerdata[0] = '3';
    computerdata[1] = '.';
    computerdata[2] = '8';
    computerdata[3] = '7';
    computerdata[4] = '7';

    TinyWire.send(1);
    TinyWire.send(computerdata,30);

Конечно, мне нужно поместить в массив переменную с плавающей запятой, а не определять числа, как у меня для тестирования, и здесь все ломается.

Когда я делаю что-то подобное, это не работает, Pi сообщает об ошибке синтаксического анализа, но когда я делаю это на выводах Due with Serial, массив символов выглядит хорошо, но что-то в нем отличается.

  sprintf(computerdata, "%2.32f", pH);

OR

  snprintf (computerdata, 35, "%f", pH);

Что я упускаю? Есть идеи?

Спасибо

, 👍1


2 ответа


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

0

Просто в дополнение к ответу Мишеля Кейзерса: sprintf() или snprintf() обычно являются правильным решением. Однако на платформе AVR плавающие преобразования исключены из их реализации по умолчанию, потому что они занимают довольно много места на флэш-памяти, даже если они не используются. С другой стороны, avr-libc предоставляет нестандартную функцию dtostrf() для выполнения этого преобразования. Программа

void setup() {
    float f = 3.877;
    char str[35];
    dtostrf(f, 0, 3, str);
    Serial.begin(9600);
    Serial.println(str);
}

void loop(){}

выходные данные

3.877
,

отлично спасибо!, @robsworld78


0

Причина в том, что библиотека, реализующая snprintf и sprintf, может зависеть от компилятора, используемого для вашего MCU, поэтому в вашем случае она не поддерживается.

Если вам всегда нужна форма %2.32f, почему бы не указать ее напрямую, например:

int i = int(3.877 * 1000.0); // Предполагая, что f имеет форму a.bcd, i будет 3877
char str[6];
str[0] = (i / 1000) % 10; 
str[1] = '.';
str[2] = (i / 100) % 10;
str[3] = (i /  10) % 10;
str[4] = (i      ) % 10;
str[5] = '0';

Также это будет намного быстрее.

,

Спасибо за ответ, но он не скомпилировался, получил эту ошибку. Эдгар работал хорошо. sketch_feb28b.ino: В функции 'void setup()': sketch_feb28b:21: ошибка: недопустимые операнды типов "double" и "int" для двоичного "operator%" sketch_feb28b:22: ошибка: недопустимые операнды типов "double" и "int" для двоичного "operator%" недопустимые операнды типов 'double' и 'int' для двоичного 'operator%', @robsworld78

Правда, поменял, теперь компилируется (на Ардуино не проверял). Я оставлю его, несмотря на то, что в большинстве случаев dtostrf лучше., @Michel Keijzers

теперь работает хорошо. :), @robsworld78

Спасибо за подтверждение, @Michel Keijzers

На attiny85 реальный вопрос заключается в том, почему вы получили поплавок в начале. :), @DataFiddler

@DataFiddler Потому что вам нужен один (?) … или вы имеете в виду, что обычно лучше избегать чисел с плавающей запятой и умножать значение с плавающей запятой на целое число с некоторыми конкретными цифрами (например, используйте целое значение * 1000, чтобы иметь 3 цифры в форме a.bcd ?), @Michel Keijzers

Вы конвертируете float в int. Вероятно, он стал плавать по * 5.0/1023 или подобной ерунде, @DataFiddler

@DataFiddler, я думаю, оператор должен ответить., @Michel Keijzers