Типы данных Arduino

Я работаю над рабочим листом для начала с arduino. У меня есть предыдущий опыт работы с ардуино, но проблема является новой для моей области знаний. Любая помощь будет хорошо оценена (нужна помощь, пожалуйста, uwu)

Постановка проблемы:

Problem statement

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

Методы, которые я пробовал до сих пор:

  • используя ограничения.h, плавает.h и встроенные переменные этой библиотеки -- Проблема: я получаю неправильные минимальные и максимальные значения для float и double: Wrong output Код:
#include <stdio.h>
#include <limits.h>
#include <float.h>
#include <math.h>

char fltmax[250];
char fltmin[250];
char dblmax[250];
char dblmin[250];

void sint() {
  Serial.print("Range of signed int: ");
  Serial.print(INT_MIN);
  Serial.print(" to ");
  Serial.print(INT_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(int));
  Serial.println(" bytes");
}
void usint() {
  Serial.print("Range of unsigned int: 0 to ");
  Serial.print(UINT_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(unsigned int));
  Serial.println(" bytes");
}
void schar() {
  Serial.print("Range of signed char: ");
  Serial.print(SCHAR_MIN);
  Serial.print(" to ");
  Serial.print(SCHAR_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(signed char));
  Serial.println(" bytes");
}
void uschar() {
  Serial.print("Range of unsigned char: 0 to ");
  Serial.print(UCHAR_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(unsigned char));
  Serial.println(" bytes");
}
void slong() {
  Serial.print("Range of signed long: ");
  Serial.print(LONG_MIN);
  Serial.print(" to ");
  Serial.print(LONG_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(signed long));
  Serial.println(" bytes");
}
void uslong() {
  Serial.print("Range of unsigned long: 0 to ");
  Serial.print(ULONG_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(unsigned long));
  Serial.println(" bytes");
}
void sshort() {
  Serial.print("Range of signed short: ");
  Serial.print(SHRT_MIN);
  Serial.print(" to ");
  Serial.print(SHRT_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(signed short));
  Serial.println(" bytes");
}
void usshort() {
  Serial.print("Range of unsigned long: 0 to ");
  Serial.print(USHRT_MAX);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(unsigned short));
  Serial.println(" bytes");
}
void flt() {
  Serial.print("Range of float: ");
  dtostrf(FLT_MIN, -1, 50, fltmin);
  Serial.print(fltmin);
  Serial.print(" to ");
  sprintf(fltmax,"%e", FLT_MAX);
  puts(fltmax);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(float));
  Serial.println(" bytes");
}
void dbl() {
  Serial.print("Range of double: ");
  dtostrf(DBL_MIN, -1, 50, dblmin);
  Serial.print(dblmin);
  Serial.print(" to ");
  dtostrf(DBL_MAX, -1, 0, dblmax);
  Serial.print(dblmax);
  Serial.print(", which has a storage size of ");
  Serial.print(sizeof(double));
  Serial.println(" bytes");
}


void setup() {
  Serial.begin(115200);
  sint();
  usint();
  schar();
  uschar();
  slong();
  uslong();
  sshort();
  usshort();
  flt();
  dbl();
}


void loop() {
}
  • Помимо использования dtostrf(), я также нашел лучшие альтернативы на exchange здесь, такие как: Печать без знака long long в ESP8266 и https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htm

Я попытался объединить оба, где тестовый код, который я использовал до фактической реализации:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <float.h>
#include <limits.h>



void setup () {
  char str[30];
  Serial.begin(115200);
  snprintf(str, 30, "Значение float max = %e", FLT_MAX);
  /*puts(str);*/
  Serial.print(str);
  return(0);
}
void loop(){
  
}

Но puts(str) не печатается на последовательном мониторе. Затем щелкнуло, что я должен использовать Serial.(код), чтобы он был напечатан в serial monitor, но в итоге код Serial.puts(str) не найден. Затем я попробовал просто Serial.print(str), но он просто выводит значение float max = ? (Изначально, до того, как я написал эту проблему здесь, она выводила только Va, и я понятия не имею, как она изменилась, но все равно это неправильно). Что мне теперь делать? кроме того, почему я не могу использовать puts для печати на последовательном мониторе?

Плата, которую я использую для этого, - Arduino UNO (ATmega328P)

, 👍2


1 ответ


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

4

Здесь есть две проблемы.

Одна заключается в том, что в Arduino Core использует последовательный для обработки последовательного ввода/вывода, а чем традиционные библиотеки libc интерфейс (функции printf(), помещает() и co.). В АВР-библиотеки libc обеспечивает традиционные функции stdio, но они будут не получится, пока вы не скажете, где стандартный вывод , который является немного сложным.

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

Тогда возникает вопрос: почему он напечатал “Значение float max = ?”. Причина в том, что avr-libc по умолчанию не поддерживает форматирование чисел с плавающей запятой с помощью sprintf(). Эта поддержка довольно дорога во флэш-памяти, и она отсутствует, если вы не свяжетесь с определенной версией avr-libc. Простые обходные пути заключаются в следующем:

  • Используйте Serial.print() как для форматирования, так и для печати чисел с плавающей запятой, что неудобно для очень маленьких или очень больших чисел.
  • Используйте dtostre() или dtostrf() для их форматирования.

В вашем случае dtostre() лучше подходит:

void setup() {
    char val[40];
    Serial.begin(9600);
    Serial.print("Range of float: ");
    dtostre(FLT_MIN, val, 5, 0);
    Serial.print(val);
    Serial.print(" to ");
    dtostre(FLT_MAX, val, 5, 0);
    Serial.print(val);
    Serial.println();
}

void loop(){}

отпечатки пальцев:

Range of float: 1.17549e-38 to 3.40282e+38
,

Ах, я вижу, я прочитаю документацию dtostre (), я думаю, она похожа на dtostrf (), но вывод скорее %e вместо %f, но я прочитаю на всякий случай. Кроме того, я только что узнал, что DBL_MIN и FLT_MIN не обеспечивают абсолютный минимум типа данных, а скорее положительное минимальное значение :) Я просто добавлю символ тире вручную и использую DBL/FLT_MAX для минимального значения. Хотя это не этично/кодекс stackexchange, чтобы сказать спасибо в комментариях, я все равно буду благодарен вам, я застрял на этом вопросе на прошлой неделе :'(, @UnfreeHeX