Arduino not respecting interval to transmit data to thingspeak

Hello guys,

Today i implemented the code so my data from DHT22 (temp, humidity) and distance sensor (distance,volume) gets transmitted via ethernet shield to thingspeak.

I have a few problems:

  1. The arduino sends data from my sensors but only when i reset it.
    It doesnt follow the agreed upon interval of 30 seconds.

  2. I have no idea what im doing with my distance and volume data, i tried doing it using the same commands as i used with the DHT22 but it keeps showing 0 on my charts.

Can anyone point me in the right direction?
I have been spending all afternoon trying to fix things but i have no clue how to fix this.

All help is very much appreciated!

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>

byte mac[] = {  0x00, 0x11, 0x32, 0x03, 0x5f, 0x0f }; // mac adress
char thingSpeakAddress[] = "api.thingspeak.com";
String writeAPIKey = "PDBEM4YSKWYFRZR5"; // api key thingspeak
const int updateThingSpeakInterval = 30000; // Time interval in milliseconds to update ThingSpeak (30 seconds)
// Variable Setup
long lastConnectionTime = 0;
boolean lastConnected = false;
int failedCounter = 0;
// Initialize Arduino Ethernet Client
EthernetClient client;

int trig = 7;
int echo = 6;

#include <DHT.h>

#define DHTPIN 9
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

int chk;
float H; // slaat de vochtigheid op (humidity)
float T; // slaat de temperatuur op (temperature)
float v; // slaat het volume op
float d; // slaat de afstand op (distance)

#include <LiquidCrystal.h>

LiquidCrystal lcd(A0, A1, 5, 4, 3, 2);

int valve = 8;  // This is the IO number of the valve

unsigned long intervalTime = 90000; //The interval of the valve opening in milliseconds
unsigned long openTime = 4000; // Time the valve has to be open on milliseconds

unsigned long lastOpenOrClose = 0;
unsigned long updateSensor = 0;

void setup(){
  lcd.begin(16, 2);
  dht.begin();

  startEthernet();
  
  pinMode(valve, OUTPUT);
  if(openTime > intervalTime){   // This is an illegal state so limit opentime to intervaltime
    openTime = intervalTime; 
  }
  
  Serial.begin(9600);
  Serial.println(F("Aan het opstarten"));
  digitalWrite(valve, HIGH);
  lastOpenOrClose = millis();

  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
}

void loop(){

  if (digitalRead(valve)==HIGH && millis() - lastOpenOrClose >= openTime) {
    digitalWrite(valve, LOW);
    lastOpenOrClose = millis();
  }
 
  if (digitalRead(valve)==LOW && millis() - lastOpenOrClose >= intervalTime) {
    digitalWrite(valve, HIGH);
    lastOpenOrClose = millis();
  }

  if (millis() - updateSensor > 2000) 
  {
    updateSensor = millis();
    Serial.println("\n"); // Makes space between the reading on serial monitor

    H = dht.readHumidity();
    T = dht.readTemperature(); 
  
    Serial.print("Read sensor: ");
    switch (chk)
    {
      case 0: Serial.println("OK"); break;
      case -1: Serial.println("Checksum error"); break;
      case -2: Serial.println("Time out error"); break;
      default: Serial.println("Unknown error"); break;
            
    }
  
    Serial.print("Vochtigheid (%): ");
    Serial.print(H, 1);
  
    Serial.print("  Temperatuur (oC): ");
    Serial.println(T, 1);
  
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(T, 1);
    lcd.print("C");
  
    lcd.setCursor(0, 1);
    lcd.print("RV: ");
    lcd.print(H, 1);
    lcd.print("%");

    long t = 0, h = 0, d = 0, v = 25; // met t = time, h = height, d= distance, v = volume

    digitalWrite(trig, LOW); //Transmitting the pulse
    delayMicroseconds(2);
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);

    t = pulseIn(echo, HIGH); // waiting for the pulse

    h = t / 58; // afstand berekenen
    h = h - 6; // Correctie van verschil sensor en max water niveau
    h = 50 - h; // Water niveau van 0 - 50 cm

    d = 2 * h; // Afstand in %, 0 - 100%

    v = (v * d) / 100 ; // volume water resterend in reservoir

    Serial.print("Afstand sensor en waterniveau: ");
    Serial.print(d); // versturen naar computer
    Serial.println("cm"); 

    Serial.print("Volume water in het reservoir: ");
    Serial.print(v); // versturen naar computer
    Serial.print(" liter");
        }
    {
    String analogPin2 = String(analogRead(A2), DEC); // heb 0 door 2 verandert door liquidcrystal (functie??)
    char T_buffer[10];
    char H_buffer[10];
    char v_buffer[10];
    char d_buffer[10];
    String temp=dtostrf(T,0,5,T_buffer);
    String humid=dtostrf(H,0,5,H_buffer);
    String volume=dtostrf(v,0,5,v_buffer);
    String distance=dtostrf(d,0,5,d_buffer);
    

    if (!client.connected() && lastConnected)
    {
    Serial.println("...disconnected");
    Serial.println();
    client.stop();
    }
    // Update ThingSpeak
    if(!client.connected() && (millis() - lastConnectionTime > updateThingSpeakInterval))
    {
    updateThingSpeak("field1="+temp+"&field2="+humid+"&field3="+volume+"&field4="+distance);
    }
    // Check if Arduino Ethernet needs to be restarted
    if (failedCounter > 3 ) {startEthernet();}
    lastConnected = client.connected(); 
    
  }
  
  delay(2000);
}
void updateThingSpeak(String tsData)
{
if (client.connect(thingSpeakAddress, 80))
{
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(tsData.length());
client.print("\n\n");
client.print(tsData);
lastConnectionTime = millis();
if (client.connected())
{
Serial.println("Connecting to ThingSpeak...");
Serial.println();
failedCounter = 0;
}
else
{
failedCounter++;
Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");
Serial.println();
}
}
else
{
failedCounter++;
Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
Serial.println();
lastConnectionTime = millis();
}
}

void startEthernet()
{
client.stop();
Serial.println("Connecting Arduino to network...");
Serial.println();
delay(1000);
// Connect to network amd obtain an IP address using DHCP
if (Ethernet.begin(mac) == 0)
{
Serial.println("DHCP Failed, reset Arduino to try again");
Serial.println();
}
else
{
Serial.println("Arduino connected to network using DHCP");
Serial.println();
}
delay(1000);
}

Your code contains this:

       }
    {

Perhaps you want to do something there, I don't know.

Calling Ethernet.begin() should be done just once. If you need to do it more, there is something wrong.

Your sketch has become too much tangled up, you need to organize the code better. That means to seperate the different functionality into seperate blocks of code.

First of all, use indents and brackets and spaces always in the same way. In the menu is Tools / Auto Format. Click it. In Dutch : Hulpmiddelen / Automatische opmaak.

Call Ethernet.begin just once in the setup(), that means you can remove the startEthernet() function.

Is the update of the sensors every 2 seconds working fine ? Keep that if you want to update the sensors every 2 seconds. Why 2 seconds and not 30 seconds ?

For ThingSpeak, open the connection, write the data, close the connection. You are trying to use a open connection, but I don't understand why. ThingSpeak has a library. It is in the Library Manager. Do you know the Library Manager ? But you can use your own code as well.

To make the code better to read, use millis() for ThingSpeak in the same way as you do for the sensors, for example with a variable called updateThingSpeak. Your usage of 'lastConnectionTime' is too hard to see what is going on, and it is a 'long' instead of a 'unsigned long'.

Please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum Your code is too long to study quickly without copying to a text editor.

…R

Robin2:
Please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum Your code is too long to study quickly without copying to a text editor.

…R

Ok i changed it, thanks for the notice.

Koepel:
Your code contains this:

       }

{



Perhaps you want to do something there, I don't know.

Calling Ethernet.begin() should be done just once. If you need to do it more, there is something wrong.

Your sketch has become too much tangled up, you need to organize the code better. That means to seperate the different functionality into seperate blocks of code.

First of all, use indents and brackets and spaces always in the same way. In the menu is Tools / Auto Format. Click it. In Dutch : Hulpmiddelen / Automatische opmaak.

Call Ethernet.begin just once in the setup(), that means you can remove the startEthernet() function.

Is the update of the sensors every 2 seconds working fine ? Keep that if you want to update the sensors every 2 seconds. Why 2 seconds and not 30 seconds ?

For ThingSpeak, open the connection, write the data, close the connection. You are trying to use a open connection, but I don't understand why.
ThingSpeak has a library. It is in the Library Manager. Do you know the Library Manager ?
But you can use your own code as well.

To make the code better to read, use millis() for ThingSpeak in the same way as you do for the sensors, for example with a variable called updateThingSpeak.
Your usage of 'lastConnectionTime' is too hard to see what is going on, and it is a 'long' instead of a 'unsigned long'.

Because i used someone else his code that i found on instructable.com the code is very all over the place, I used the help tool to clean it up.

After searching the Thinkspeak library i used the github example and it works perfectly now.
Thanks for getting me on the way.

This is the code i have now, if you have any remarks let me know!

#include <ThingSpeak.h>
#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  0x00, 0x11, 0x32, 0x03, 0x5f, 0x0f };
IPAddress ip(192, 168, 1, 11);    // Your IP Address
EthernetClient client;

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

int trig = 7;
int echo = 6;

#include <DHT.h>

#define DHTPIN 9
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

int chk;
float H; // slaat de vochtigheid op (humidity)
float T; // slaat de temperatuur op (temperature)

#include <LiquidCrystal.h>

LiquidCrystal lcd(A0, A1, 5, 4, 3, 2);

int valve = 8;  // This is the IO number of the valve

unsigned long intervalTime = 90000; //The interval of the valve opening in milliseconds
unsigned long openTime = 4000; // Time the valve has to be open on milliseconds

unsigned long lastOpenOrClose = 0;
unsigned long updateSensor = 0;

void setup() {
  lcd.begin(16, 2);
  dht.begin();

  Ethernet.begin(mac, ip);
  ThingSpeak.begin(client);

  pinMode(valve, OUTPUT);
  if (openTime > intervalTime) { // This is an illegal state so limit opentime to intervaltime
    openTime = intervalTime;
  }

  Serial.begin(9600);
  Serial.println(F("Aan het opstarten"));
  digitalWrite(valve, HIGH);
  lastOpenOrClose = millis();

  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
}

void loop() {

  if (digitalRead(valve) == HIGH && millis() - lastOpenOrClose >= openTime) {
    digitalWrite(valve, LOW);
    lastOpenOrClose = millis();
  }

  if (digitalRead(valve) == LOW && millis() - lastOpenOrClose >= intervalTime) {
    digitalWrite(valve, HIGH);
    lastOpenOrClose = millis();
  }

  if (millis() - updateSensor > 2000)
  {
    updateSensor = millis();
    Serial.println("\n"); // Makes space between the reading on serial monitor

    H = dht.readHumidity();
    T = dht.readTemperature();

    Serial.print("Read sensor: ");
    switch (chk)
    {
      case 0: Serial.println("OK"); break;
      case -1: Serial.println("Checksum error"); break;
      case -2: Serial.println("Time out error"); break;
      default: Serial.println("Unknown error"); break;
    }

    Serial.print("Vochtigheid (%): ");
    Serial.print(H, 1);

    Serial.print("  Temperatuur (oC): ");
    Serial.println(T, 1);

    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(T, 1);
    lcd.print("C");

    lcd.setCursor(0, 1);
    lcd.print("RV: ");
    lcd.print(H, 1);
    lcd.print("%");

    long t = 0, h = 0, d = 0, v = 25; // met t = time, h = height, d= distance, v = volume

    digitalWrite(trig, LOW); //Transmitting the pulse
    delayMicroseconds(2);
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);

    t = pulseIn(echo, HIGH); // waiting for the pulse

    h = t / 58; // afstand berekenen
    h = h - 6; // Correctie van verschil sensor en max water niveau
    h = 50 - h; // Water niveau van 0 - 50 cm

    d = 2 * h; // Afstand in %, 0 - 100%

    v = (v * d) / 100 ; // volume water resterend in reservoir

    Serial.print("Afstand sensor en waterniveau: ");
    Serial.print(d); // versturen naar computer
    Serial.println("cm");

    Serial.print("Volume water in het reservoir: ");
    Serial.print(v); // versturen naar computer
    Serial.print(" liter");

    ThingSpeak.setField(1, T);
    ThingSpeak.setField(2, H);
    ThingSpeak.setField(3, v);
    ThingSpeak.setField(4, d);

    ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

  }

  delay(2000);
}

That is a lot better with the ThingSpeak library.

There are a few things that can be improved. The interval is 2 seconds for the sensors and for ThingSpeak. That is a fast update to ThingSpeak, do they allow that, or are you blocked now and then ?

When using millis(), the delays are no longer needed. You use millis() with 'updateSensor', but at the bottom there is still the delay(2000). Perhaps it is safer to increase the interval from 2 seconds to 10 seconds and remove that delay. How often do you want to read the valves ? Perhaps you can use a millis() for that as well.

The ideal sketch with millis() is when the loop() runs over and over again very fast, and only when it is time to do something, then that something is executed. That makes it easy to add new things to it.

Koepel: That is a lot better with the ThingSpeak library.

There are a few things that can be improved. The interval is 2 seconds for the sensors and for ThingSpeak. That is a fast update to ThingSpeak, do they allow that, or are you blocked now and then ?

When using millis(), the delays are no longer needed. You use millis() with 'updateSensor', but at the bottom there is still the delay(2000). Perhaps it is safer to increase the interval from 2 seconds to 10 seconds and remove that delay. How often do you want to read the valves ? Perhaps you can use a millis() for that as well.

The ideal sketch with millis() is when the loop() runs over and over again very fast, and only when it is time to do something, then that something is executed. That makes it easy to add new things to it.

Thingspeak accepts one stream every 15 seconds, the rest gets denied i guess.

I would prefer the sensors to refresh every 2 seconds because i would like to measure the change in humidity and maybe temperature while opening the valve on the serial monitor or lcd. If i only read data every 10 seconds i will miss some data, altpugh its not that important. It would be good to get rid of the unneccesary streams to thingspeak though

The opening and closing of the valve isnt being read at the moment, altough it would be cool to track it to compare the charts with the change in humidity.

The main function of the stream is as an alarm so i can check the values of the sensors as the system is located at my uni.

You could make three sections with millis(). For the values of 500, 2000 and 60000, I added 'UL' to it. That stands for 'unsigned long'. The default is integer, and one minute is 60000, but that can't fit into an integer and must be a long or unsigned long, I added 'UL' to all values to make it look better.

// The previousMillis value (three of them).
unsigned long prevMilValves, prevMilSensors, prevMilThingSpeak;
...
void loop()
{
  unsigned long currentMillis = millis();         // request millis just once.

  if( currentMillis - prevMilValves >= 500UL)
  {
    prevMilValves = currentMillis;
    ...
  }

  if( currentMillis - prevMilSensors >= 2000UL)
  {
    prevMilSensors = currentMillis;
    ...
  }

  if( currentMillis - prevMilThingSpeak >= 60000UL)
  {
    prevMilThingSpeak = currentMillis;
    ...
  }

}

Koepel: You could make three sections with millis(). For the values of 500, 2000 and 60000, I added 'UL' to it. That stands for 'unsigned long'. The default is integer, and one minute is 60000, but that can't fit into an integer and must be a long or unsigned long, I added 'UL' to all values to make it look better.

// The previousMillis value (three of them).
unsigned long prevMilValves, prevMilSensors, prevMilThingSpeak;
...
void loop()
{
  unsigned long currentMillis = millis();         // request millis just once.

  if( currentMillis - prevMilValves >= 500UL)   {     prevMilValves = currentMillis;     ...   }

  if( currentMillis - prevMilSensors >= 2000UL)   {     prevMilSensors = currentMillis;     ...   }

  if( currentMillis - prevMilThingSpeak >= 60000UL)   {     prevMilThingSpeak = currentMillis;     ...   }

}

Excuse me for the late answer.

I talked with my IT department at school and they have no problem with me pinging that much, so id rather leave it alone.

I have another problem though, my valve isnt respecting my openTime and intervalTime like it should.

I made a new post about it: http://forum.arduino.cc/index.php?topic=417626.0