Problem in sending data via wifi

Hello guys.

I am sending liquid data from arduino to ThingSpeak cloud. The problem I am facing that if I send data after the ‘if’ statement inside the loop, the data is sent but it is not entirely accurate and even when the sensor is not receiving any liquid, the last reading is continuously being sent which is problematic.

Can anyone tell me where should I use the data sending code to send the accurate readings?

The code is below:

#include "ThingSpeak.h"
//#define USE_WIFI101_SHIELD

#if defined(ARDUINO_AVR_YUN)
    #include "YunClient.h"
    YunClient client;
#else
  #if defined(USE_WIFI101_SHIELD) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_ARCH_ESP8266)
    // Use WiFi
    #ifdef ARDUINO_ARCH_ESP8266
      #include <ESP8266WiFi.h>
    #else
      #include <SPI.h>
      #include <WiFi101.h>
    #endif
    char ssid[] = "<>";    //  your network SSID (name) 
    char pass[] = "<>";   // your network password
    int status = WL_IDLE_STATUS;
    WiFiClient  client;
  #elif defined(USE_ETHERNET_SHIELD)
    // Use wired ethernet shield
    #include <SPI.h>
    #include <Ethernet.h>
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
    EthernetClient client;
  #endif
#endif

unsigned long myChannelNumber = ;
const char * myWriteAPIKey = "";

byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 3;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 9.5;

volatile byte pulseCount;  

float flowRate;
 unsigned int flowMilliLitres;
 unsigned long totalMilliLitres;

unsigned long oldTime;


void setup() {
  #ifdef ARDUINO_AVR_YUN
    Bridge.begin();
  #else   
    #if defined(ARDUINO_ARCH_ESP8266) || defined(USE_WIFI101_SHIELD) || defined(ARDUINO_SAMD_MKR1000)
      WiFi.begin(ssid, pass);
    #else
      Ethernet.begin(mac);
    #endif
  #endif

  ThingSpeak.begin(client);

  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);


}



void loop() {
   if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;
      
    unsigned int frac;

  // Serial.print("Flow rate: ");
    //Serial.print(int(flowRate));  // Print the integer part of the variable
    //Serial.print(".");             // Print the decimal point
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate)) * 10;
    ThingSpeak.writeField(myChannelNumber, 1, (long) totalMilliLitres, myWriteAPIKey);
    delay(20000); // ThingSpeak will only accept updates every 15 seconds.
    //Serial.print(frac, DEC) ;      // Print the fractional part of the variable
    //Serial.print("L/min");
    // Print the number of litres flowed in this second
    //Serial.print("  Current Liquid Flowing: ");             // Output separator
    //Serial.print(flowMilliLitres);
    //Serial.print("mL/Sec");

    // Print the cumulative total of litres flowed since starting
    //Serial.print("  Output Liquid Quantity: ");             // Output separator
    //Serial.print(totalMilliLitres);
    //Serial.println("mL"); 
   

    pulseCount = 0;

 
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

     
   
     ThingSpeak.writeField(myChannelNumber, 1, (long) totalMilliLitres, myWriteAPIKey);
    delay(20000); // ThingSpeak will only accept updates every 15 seconds.
    
    
    
    
   

  }
  
   
   
}
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

I look forward to your suggestions and help.

Thanks
Rushan

even when the sensor is not receiving any liquid, the last reading is continuously being sent which is problematic.

    totalMilliLitres += flowMilliLitres;

Your code does explicitly send the total amount to the service.

The problem I am facing that if I send data after the 'if' statement inside the loop, the data is sent but it is not entirely accurate

What do you mean by "not entirely accurate". The value should be as accurate as the sensor you're using. Please provide an example of what you mean (read value and expected value).

Hello

Thanks for your reply. If i used the ThingSpeak writefield statement after the 'if' statement, the amount of liquid is sent is accurate as long as liquid is passing through the sensor but when there is no liquid flowing, the last value is still being sent every 15 seconds. Thats the problem.
If i use the code given above where I have used Thingspeak writefield statement inside 'if' statement, the value sent is always 0.

Can you help me in resolving this? what could be the problem?

Thanks
Rushan

Thanks for your reply. If i used the ThingSpeak writefield statement after the 'if' statement, the amount of liquid is sent is accurate as long as liquid is passing through the sensor but when there is no liquid flowing, the last value is still being sent every 15 seconds. Thats the problem.

That's exactly what your code does. It always sends the total amount of liquid run through the sensor. If there is no more flow through the sensor the total still stays at that value and doesn't fall back to 0.

If i use the code given above where I have used Thingspeak writefield statement inside 'if' statement, the value sent is always 0.

There are two calls of writefield inside the if clause, the second one is surely not necessary. The delay is more than problematic because you have disabled the counting interrupt during that delay, so you loose the flow while you're waiting. In such an application you should never use delay(). The code already contains a way to do the calculations and sending not to often (the if clause), so change that not to be one second but 20 and you can remove all delay() calls.

Hello,

I have tried what you said but now the readings are constantly 0. The new code is below and graph is attached:

#include "ThingSpeak.h"
//#define USE_WIFI101_SHIELD

#if defined(ARDUINO_AVR_YUN)
    #include "YunClient.h"
    YunClient client;
#else
  #if defined(USE_WIFI101_SHIELD) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_ARCH_ESP8266)
    // Use WiFi
    #ifdef ARDUINO_ARCH_ESP8266
      #include <ESP8266WiFi.h>
    #else
      #include <SPI.h>
      #include <WiFi101.h>
    #endif
    char ssid[] = "<>";    //  your network SSID (name) 
    char pass[] = "<>";   // your network password
    int status = WL_IDLE_STATUS;
    WiFiClient  client;
  #elif defined(USE_ETHERNET_SHIELD)
    // Use wired ethernet shield
    #include <SPI.h>
    #include <Ethernet.h>
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
    EthernetClient client;
  #endif
#endif

unsigned long myChannelNumber = ;
const char * myWriteAPIKey = "";

byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 3;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 9.5;

volatile byte pulseCount;  

float flowRate;
 unsigned int flowMilliLitres;
 int totalMilliLitres;

unsigned long oldTime;


void setup() {
  #ifdef ARDUINO_AVR_YUN
    Bridge.begin();
  #else   
    #if defined(ARDUINO_ARCH_ESP8266) || defined(USE_WIFI101_SHIELD) || defined(ARDUINO_SAMD_MKR1000)
      WiFi.begin(ssid, pass);
    #else
      Ethernet.begin(mac);
    #endif
  #endif

  ThingSpeak.begin(client);

  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, RISING);


}



void loop() {
  
    
   if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;
      
    unsigned int frac;

  // Serial.print("Flow rate: ");
    //Serial.print(int(flowRate));  // Print the integer part of the variable
    //Serial.print(".");             // Print the decimal point
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate)) * 10;
    // ThingSpeak will only accept updates every 15 seconds.
    //Serial.print(frac, DEC) ;      // Print the fractional part of the variable
    //Serial.print("L/min");
    // Print the number of litres flowed in this second
    //Serial.print("  Current Liquid Flowing: ");             // Output separator
    //Serial.print(flowMilliLitres);
    //Serial.print("mL/Sec");

    // Print the cumulative total of litres flowed since starting
    //Serial.print("  Output Liquid Quantity: ");             // Output separator
    //Serial.print(totalMilliLitres);
    //Serial.println("mL"); 
  }
   ThingSpeak.writeField(myChannelNumber, 1, (long ) totalMilliLitres, myWriteAPIKey);
  pulseCount=0;
 
    
    // Enable the interrupt again now that we've finished sending output
    
        
    attachInterrupt(sensorInterrupt, pulseCounter, RISING);
  //unsigned long tl = totalMilliLitres;  
}
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

Can you tell me what should I do now so that the readings are neither lost nor are incorrect? I am comparatively new to arduino so maybe I am doing something basic wrong.

You just removed the delay() calls and the double call of the writeField() method. You didn't change the repeat period in the if clause (it's still 1 sec) and you call the writeField() method now outside that if which let the call happen to often for ThingSpeak I guess. I also don't see why you deactivate the interrupt and later on activate it again. Just reset pulseCount immediately after you calculated the flowrate then you don't loose some spikes.

Can you tell me what should I do now so that the readings are neither lost nor are incorrect? I am comparatively new to arduino so maybe I am doing something basic wrong.

Do you understand what the program does? I get the impression that you just copy/paste some code and you don't understand a bit of what the underlying code really does. Please excuse if I'm wrong but you should have a basic knowledge of what your sketch does to apply the changes I suggested above.

Thank you very much for your suggestions. I am not losing the spikes now but one problem still lies, when the liquid stops flowing, the last reading is still being sent to ThingSpeak. I have made the changes according to your suggestions.

Can you tell me what else I need to change? Updated code is below:

#include "ThingSpeak.h"
//#define USE_WIFI101_SHIELD

#if defined(ARDUINO_AVR_YUN)
    #include "YunClient.h"
    YunClient client;
#else
  #if defined(USE_WIFI101_SHIELD) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_ARCH_ESP8266)
    // Use WiFi
    #ifdef ARDUINO_ARCH_ESP8266
      #include <ESP8266WiFi.h>
    #else
      #include <SPI.h>
      #include <WiFi101.h>
    #endif
    char ssid[] = "<>";    //  your network SSID (name) 
    char pass[] = "<>";   // your network password
    int status = WL_IDLE_STATUS;
    WiFiClient  client;
  #elif defined(USE_ETHERNET_SHIELD)
    // Use wired ethernet shield
    #include <SPI.h>
    #include <Ethernet.h>
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
    EthernetClient client;
  #endif
#endif

unsigned long myChannelNumber = ;
const char * myWriteAPIKey = "";

byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 3;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 9.5;

volatile byte pulseCount;  

float flowRate;
 unsigned int flowMilliLitres;
 int totalMilliLitres;

unsigned long oldTime;


void setup() {
  #ifdef ARDUINO_AVR_YUN
    Bridge.begin();
  #else   
    #if defined(ARDUINO_ARCH_ESP8266) || defined(USE_WIFI101_SHIELD) || defined(ARDUINO_SAMD_MKR1000)
      WiFi.begin(ssid, pass);
    #else
      Ethernet.begin(mac);
    #endif
  #endif

  ThingSpeak.begin(client);

  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, RISING);


}



void loop() {
  
    
   if((millis() - oldTime) > 20000)
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    pulseCount=0;
    
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;
      
    unsigned int frac;

  // Serial.print("Flow rate: ");
    //Serial.print(int(flowRate));  // Print the integer part of the variable
    //Serial.print(".");             // Print the decimal point
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate)) * 10;
    ThingSpeak.writeField(myChannelNumber, 1, (long ) totalMilliLitres, myWriteAPIKey);
  
 
    
        
    
  }
   
  //unsigned long tl = totalMilliLitres;  
}
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

STOP spamming this message board.

Continue the discussion at your original post

And another post about the same thing

Sheesh.

You should get banned for doing this!

ieee488:
STOP spamming this message board.

Continue the discussion at your original post
http://forum.arduino.cc/index.php?topic=490401.msg3346749#msg3346749

And another post about the same thing
http://forum.arduino.cc/index.php?topic=490266.msg3345298#msg3345298

Sheesh.

You should get banned for doing this!

I'm sorry for spamming. I tried deleting the other posts but i'm unable to. wont happen again.

I am not losing the spikes now but one problem still lies, when the liquid stops flowing, the last reading is still being sent to ThingSpeak.

If it works while there is a flow, than that's exactly what the ThingSpeak end seems to expect.

As I already wrote: you're sending the total amount of fluid that came across your sensor to ThingSpeak. If the flow stops, the total amount stays the same number as long as there no flow. When there's flow again, the number increases but it never decreases (OK at some point the integer will overflow but a technical limitation). I explained that above but you never even tried to react on that. What does your ThingSpeak (I don't know that service) expects to be sent? The total amount (sum) of fluid or the fluid that passed since the last value was sent?

Thank You for your reply.
Actually, there are two variables here. one is flowMilliLitres and then there is totalMilliLitres. flowMilliLitres calculate the liquid passed through the sensor in 1 second through flowRate. whereas totalMilliLitres aggregates the flowMilliLitres and then it sends to ThingSpeak.

So the problem is solved now. The mistake I was making after I changed the if statement to 20 seconds that I forgot to divide the flowRate by 3 instead of 60 when calculating flowMilliLitres. Now the readings are accurate at ThingSpeak.

Thank You very much for your assistance.