1
#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";

// WiFiManager
// Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;

// Create AsyncWebServer object on port 80
AsyncWebServer server2(80);
WiFiServer server(80);

// variables to count the pulses of the meters.
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";

// function to increment the meters value by 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); // Set GPIO25 as digital output pin
  attachInterrupt(digitalPinToInterrupt(25), pulse1, RISING); 

  pinMode(19, INPUT_PULLDOWN); // Set GPIO19 as digital output pin
  attachInterrupt(digitalPinToInterrupt(19), pulse2, RISING); 

  pinMode(23, INPUT_PULLDOWN); // Set GPIO22 as digital output pin
  attachInterrupt(digitalPinToInterrupt(23), pulse3, RISING); 

  pinMode(18, INPUT_PULLDOWN);// Set GPIO18 as digital output pin
  attachInterrupt(digitalPinToInterrupt(18), pulse4, RISING); 

  pinMode(21, INPUT_PULLDOWN); // Set GPIO22 as digital output pin
  attachInterrupt(digitalPinToInterrupt(21), pulsegas, RISING); 

  pinMode(5, INPUT_PULLDOWN); // Set GPIO5 as digital output pin
  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();

  // keeps track of the amount of pulses of pulse meters
  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;
  }
  // sends an update to the web
  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))) {
  {
      // checks if wifi is connected.
      if (WiFi.status()== WL_CONNECTED) {
        HTTPClient http;
        // preparation HTTP GET request.
         String serverPath = serverName + "?chip_id=" + chipId + "&count1=" + new_count1 + "&count2=" + new_count2 + "&count3=" +
         new_count3 + "&count4=" + new_count4 + "&countgas=" + new_countgas + "&countwater=" + new_countwater;
        // Your Domain name with URL path or IP address  with path.
        http.begin(serverPath.c_str());
        // Send HTTP GET request.
        int httpResponseCode = http.GET();
        // confirms the arrival of a response from the server or sends an error.
        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);
         }
        // closes the HTTP connection.
        http.end();
      }
      else {
       Serial.println("WiFi Disconnected");
      }  
    }
  }
  
  //reset timer when done sending data
  if (((millis() - lastTime) > timerDelay)) {
    lastTime = millis();
  }
}

The program is a pulse counter which should add 0.001 pulse everytime it detects one. I expect it to send 0.006 to the server, but instead it sends 0.01. How do I make sure it doesn't send rounded data?

5
  • It might be rounded by float to String conversion. You might want to use something like: String(someFloat, 3). Also you have to remember there are limits for the floating point numbers, but in this case it should be ok. Implicitly decimal points are 2 places only: String(double, unsigned char decimalPlaces=2);
    – KIIV
    Commented Jun 23, 2022 at 7:25
  • 1
    @KIIV: This should be an answer. Commented Jun 23, 2022 at 7:28
  • There are too many String objects here, which are heavyweight and unfriendly to the Arduino memory. guifactor1 & co. should be int or float. counter1 & co. should be ints equal to ±1 that you add to the counters: void pulse1() { count1 += increment1; }. Commented Jun 23, 2022 at 7:55
  • @EdgarBonet this is not my entire code the guifactor for example is a string because i save it to the spiffs
    – jay
    Commented Jun 23, 2022 at 7:56
  • Is this code run on a NodeMCU (or other ESP8266 or ESP32-based board)? If so, you could use the printf function i.e. Serial.printf("%.5f", someFloat); with "5" being the number of digits you need after the decimal point. The printf format is described here.
    – StarCat
    Commented Jun 23, 2022 at 11:53

1 Answer 1

3

The constructor for the String object from float is this:

String(double, unsigned char decimalPlaces=2);

So if you don't want to have 2 decimal digits, you have to use String(someFloat, 3).

Also you have to remember there are limits for the floating point numbers, but in this case it shouldn't be the case.

And as Edgar mentioned, String objects are bit dangerous if they are overused, particularly building that serverPath is the worst way how to do it (every single level of it creates new temp object to be copied into next bigger one and released).

It would be cheaper to do it like:

String serverPath;
serverPath.reserve(100); // reserve space so it doesn't have to resize; should be proper estimate
serverPath += serverName;
serverPath += "?chip_id=";  // on AVR it should be 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;

or you can use some c++ magic:

template <class T> inline String & operator<<(String & out, T const & what) {
    out += what;
    return out;
}

String serverPath;
serverPath.reserve(100); // reserve space so it doesn't have to resize

serverPath << serverName << "?chip_id=" << chipId << "&count1="
           << new_count1 << "&count2=" << new_count2 << "&count3="
           << new_count3 << "&count4=" << new_count4 << "&countgas="
           << new_countgas << "&countwater=" << new_countwater;

this code takes serverPath << serverName adds serverName into serverPath and the result is serverPath again, and then it continues as serverPath << "?chip_id=" and so on

1
  • thank you it works with String(someFloat, 3)
    – jay
    Commented Jun 23, 2022 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.