Почему данные, которые я отправляю на сервер, округляются и как вместо этого отправить все число с плавающей запятой?
#include <Arduino.h>
#include <WiFi.h>
#include "WiFiManager.H"
#include <HTTPClient.H>
#include "ESPAsyncWebServer.h"
#include <AsyncTCP.h>
float version = 1.9;
uint32_t chipId = 0;
String chipId2 = "";
int i;
String serverName = "http://d";
// Менеджер Wi-Fi
// Локальная инициализация. После того, как его бизнес сделан, нет необходимости держать его рядом
WiFiManager wifiManager;
// Создаем объект AsyncWebServer на порту 80
AsyncWebServer server2(80);
WiFiServer server(80);
// переменные для подсчета импульсов счетчиков.
int count1=0;
float prior_count1=0;
int count2=0;
float prior_count2=0;
int count3=0;
float prior_count3=0;
int count4=0;
float prior_count4=0;
int countgas=0;
float prior_countgas=0;
int countwater=0;
float prior_countwater=0;
String payloadpulse = "0";
unsigned long lastTime = 0;
unsigned long timerDelay = 6000;
String guifactor1 = "1000";
String guifactor2 = "1000";
String guifactor3 = "1000";
String guifactor4 = "1000";
String guifactorgas = "1000";
String guifactorwater = "1000";
String counter1 = "1";
String counter2 = "1";
String counter3 = "1";
String counter4 = "1";
String counter5 = "1";
String counter6 = "1";
// функция для увеличения значения счетчика на 1.
void pulse1() {
if (counter1.toInt() == 1) {
count1 = count1 + 1;
}
if (counter1.toInt() == 2) {
count1 = count1 - 1;
}
}
void pulse2() {
if (counter2.toInt() == 1) {
count2 = count2 + 1;
}
if (counter2.toInt() == 2) {
count2 = count2 - 1;
}
}
void pulse3() {
if (counter3.toInt() == 1) {
count3 = count3 + 1;
}
if (counter3.toInt() == 2) {
count3 = count3 - 1;
}
}
void pulse4() {
if (counter4.toInt() == 1) {
count4 = count4 + 1;
}
if (counter4.toInt() == 2) {
count4 = count4 - 1;
}
}
void pulsegas() {
if (counter5.toInt() == 1) {
countgas = countgas + 1;
}
if (counter5.toInt() == 2) {
countgas = countgas - 1;
}
}
void pulsewater() {
if (counter6.toInt() == 1) {
countwater = countwater + 1;
}
if (counter6.toInt() == 2) {
countwater = countwater - 1;
}
}
void setup() {
Serial.begin(115200);
wifiManager.autoConnect("ss", "ss");
pinMode(25, INPUT_PULLDOWN); // Установите GPIO25 в качестве цифрового вывода
attachInterrupt(digitalPinToInterrupt(25), pulse1, RISING);
pinMode(19, INPUT_PULLDOWN); // Установите GPIO19 в качестве цифрового вывода
attachInterrupt(digitalPinToInterrupt(19), pulse2, RISING);
pinMode(23, INPUT_PULLDOWN); // Установите GPIO22 в качестве цифрового вывода
attachInterrupt(digitalPinToInterrupt(23), pulse3, RISING);
pinMode(18, INPUT_PULLDOWN);// Установить GPIO18 в качестве цифрового вывода
attachInterrupt(digitalPinToInterrupt(18), pulse4, RISING);
pinMode(21, INPUT_PULLDOWN); // Установите GPIO22 в качестве цифрового вывода
attachInterrupt(digitalPinToInterrupt(21), pulsegas, RISING);
pinMode(5, INPUT_PULLDOWN); // Установите GPIO5 в качестве цифрового вывода
attachInterrupt(digitalPinToInterrupt(5), pulsewater, RISING);
}
//------------------------------------------------ --------------------
void loop() {
float new_count1 = static_cast<float> (count1) / guifactor1.toInt();
float new_count2 = static_cast<float> (count2) / guifactor2.toInt();
float new_count3 = static_cast<float> (count3) / guifactor3.toInt();
float new_count4 = static_cast<float> (count4) / guifactor4.toInt();
float new_countgas = static_cast<float> (countgas) / guifactorgas.toInt();
float new_countwater = static_cast<float> (countwater) / guifactorwater.toInt();
// отслеживает количество импульсов счетчиков пульса
if (new_count1 != prior_count1 ||
new_count2 != prior_count2 ||
new_count3 != prior_count3 ||
new_count4 != prior_count4 ||
new_countgas != prior_countgas ||
new_countwater != prior_countwater) {
Serial.println(new_count1, 4);
Serial.println(new_count2, 4);
Serial.println(new_count3, 4);
Serial.println(new_count4, 4);
Serial.println(new_countgas, 4);
Serial.println(new_countwater, 4);
prior_count1 = new_count1;
prior_count2 = new_count2;
prior_count3 = new_count3;
prior_count4 = new_count4;
prior_countgas = new_countgas;
prior_countwater = new_countwater;
}
// отправляет обновление в сеть
if ((new_count1 > 0 && ((millis() - lastTime) > timerDelay)) ||
(new_count2 > 0 && ((millis() - lastTime) > timerDelay)) ||
(new_count3 > 0 && ((millis() - lastTime) > timerDelay)) ||
(new_count4 > 0 && ((millis() - lastTime) > timerDelay)) ||
(new_countgas > 0 && ((millis() - lastTime) > timerDelay)) ||
(new_countwater > 0 && ((millis() - lastTime) > timerDelay))) {
{
// проверяет, подключен ли Wi-Fi.
if (WiFi.status()== WL_CONNECTED) {
HTTPClient http;
// подготовка HTTP GET запроса.
String serverPath = serverName + "?chip_id=" + chipId + "&count1=" + new_count1 + "&count2=" + new_count2 + "&count3=" +
new_count3 + "&count4=" + new_count4 + "&countgas=" + new_countgas + "&countwater=" + new_countwater;
// Ваше доменное имя с URL-адресом или IP-адрес с путем.
http.begin(serverPath.c_str());
// Отправляем запрос HTTP GET.
int httpResponseCode = http.GET();
// подтверждает приход ответа от сервера или отправляет ошибку.
if (httpResponseCode>0) {
count1 = 0;
count2 = 0;
count3 = 0;
count4 = 0;
countgas = 0;
countwater = 0;
payloadpulse = http.getString();
Serial.println(payloadpulse);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// закрывает HTTP-соединение.
http.end();
}
else {
Serial.println("WiFi Disconnected");
}
}
}
//сброс таймера после отправки данных
if (((millis() - lastTime) > timerDelay)) {
lastTime = millis();
}
}
Программа представляет собой счетчик импульсов, который должен прибавлять 0,001 импульса каждый раз, когда он его обнаруживает. Я ожидаю, что он отправит на сервер 0,006, но вместо этого он отправляет 0,01. Как убедиться, что он не отправляет округленные данные?
1 ответ
Лучший ответ:
Конструктор объекта String из float выглядит следующим образом:
String(double, unsigned char decimalPlaces=2);
Поэтому, если вы не хотите иметь две десятичные цифры, вам нужно использовать String(someFloat, 3)
.
Также вы должны помнить, что существуют ограничения для чисел с плавающей запятой, но в данном случае это не так.
И, как упоминал Эдгар, объекты String немного опасны, если ими злоупотреблять, особенно построение serverPath — худший способ, как это сделать (каждый его уровень создает новый временный объект, который будет скопирован в следующий больший и освобожден) .
Было бы дешевле сделать так:
String serverPath;
serverPath.reserve(100); // зарезервировать место, чтобы не изменять размер; должна быть правильная оценка
serverPath += serverName;
serverPath += "?chip_id="; // на AVR это должно быть F()
serverPath += chipId;
serverPath += "&count1=";
serverPath += new_count1;
serverPath += "&count2=";
serverPath += new_count2;
serverPath += "&count3=";
serverPath += new_count3;
serverPath += "&count4=";
serverPath += new_count4;
serverPath += "&countgas=";
serverPath += new_countgas;
serverPath += "&countwater=";
serverPath += new_countwater;
или вы можете использовать магию C++:
template <class T> inline String & operator<<(String & out, T const & what) {
out += what;
return out;
}
String serverPath;
serverPath.reserve(100); // резервируем место, чтобы не менять размер
serverPath << serverName << "?chip_id=" << chipId << "&count1="
<< new_count1 << "&count2=" << new_count2 << "&count3="
<< new_count3 << "&count4=" << new_count4 << "&countgas="
<< new_countgas << "&countwater=" << new_countwater;
этот код использует serverPath << имя_сервера
добавляет имя_сервера в путь_сервера, и в результате снова получается путь_сервера, а затем продолжается как путь serverPath << "?chip_id="
и т. д.
спасибо, это работает со строкой (someFloat, 3), @Jay van de Wetering
- Не удается получить данные из кода Python
- Безопасность Ардуино
- Float печатается только 2 десятичных знака после запятой
- Отправка и получение различных типов данных через I2C в Arduino
- Несколько клиентских серверов через Wi-Fi
- WebSocketsServer.h: No such file or directory
- Как перевести float в четыре байта?
- Как получить данные из базы данных моего сервера в переменную в моем Arduino?
Он может быть округлен путем преобразования числа с плавающей запятой в строку. Вы можете использовать что-то вроде:
String(someFloat, 3)
. Также вы должны помнить, что существуют ограничения для чисел с плавающей запятой, но в этом случае все должно быть в порядке. Неявно десятичные точки — это только 2 знака:String(double, unsigned char decimalPlaces=2);
, @KIIV@KIIV: это должен быть ответ., @Edgar Bonet
Здесь слишком много объектов String, которые тяжеловесны и недружественны для памяти Arduino.
guifactor1
и др. должно бытьint
илиfloat
.counter1
и др. должно бытьint
равным ±1, которое вы добавляете к счетчикам:void pulse1() { count1 += increment1; }
., @Edgar Bonet@EdgarBonet это не весь мой код, например, guifactor представляет собой строку, потому что я сохраняю ее в spiffs, @Jay van de Wetering
Запускается ли этот код на NodeMCU (или другой плате на базе ESP8266 или ESP32)? Если это так, вы можете использовать функцию
printf
, т.е.Serial.printf("%.5f", someFloat);
где "5" - это количество цифр, которое вам нужно после запятой. Формат printf описан [здесь] (https://alvinalexander.com/programming/printf-format-cheat-sheet/)., @StarCat