Struggling with odd sensor readings

Hi, I am working on a watering system for my plants. I am almost done but i have one problem. I have 3 of the same type of soil moisture sensors but they are not reading the same values, i understand that it wont be exactly the same value from each sensor but the difference is inconsistent and big. Also, as of today when i uploaded a very small change to my code on the arduino uno that shouldnt affect the sensor readings. The change i made was the variables intervall and sampleIntervall which determines how often it should read the values and send them to esp which then sends to server, the sensors are reading negative values ?!?! I have no clue why this is and it hasn't happened before to me. So what i am asking is how i can get atleast consistent values from one sensor and what it could be that is causing this problem. I'm reading the negative values from my server logs. But the server "can't" be the problem here as i haven't changed anything on it after these negative values started comming. I will post the code that is uploaded to the arduino:

// Import the libraries for the 1-wire DS18B20 temperature sensor
#include <OneWire.h>
#include <DallasTemperature.h>


const int lightPin = A0;
int lightType = 1;
const int lightID = 1;

const int tempPin = A1;
int tempType = 2;
const int tempID = 2;

const int moistPin = A2;
int moistType = 3;
const int moistID = 3;

#define oneWireBus 12
const int temp2ID = 4;

const int moist2Pin = A3; 
const int moist2ID = 5;

const int buttonPin = 2;
const int valvePin = 11;
// bool watered = false;


// const unsigned long intervall = 1800000; //30 min
const unsigned long intervall = 900000;  //15 min
// const unsigned long intervall = 300000; //5 min
const unsigned long sampleIntervall = 60000; //1 min
// const unsigned long sampleIntervall = 10000; //10 sec
int arraySize = intervall/sampleIntervall; 

int latestMoist[intervall/sampleIntervall];
int latestMoist2[intervall/sampleIntervall];
int latestTemp[intervall/sampleIntervall];
int latestTemp2[intervall/sampleIntervall];
int latestLight[intervall/sampleIntervall];

int index = 0;


const int waterBorder = 40;

unsigned long currTime;
unsigned long prevSampleTime = 0;


OneWire oneWire(oneWireBus);  // 1-wire instance on the oneWireBus pin
DallasTemperature sensors(&oneWire);

float tempSensRdg;
float volt;
float temp;
float temp2;
int moist;
int moist2;
int light;


void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(lightPin, INPUT);
  pinMode(tempPin, INPUT);
  pinMode(moistPin, INPUT);
  pinMode(valvePin, OUTPUT);
  pinMode(buttonPin, INPUT);
  sensors.begin();
}

void loop() {
  // watered = false;
  currTime = millis();

  if (currTime - prevSampleTime > sampleIntervall){
    prevSampleTime = currTime;
    readSensors();
    index++;

      if (index == arraySize) {
        index = 0;
        calcMeans();

        if (moist > waterBorder) {
          waterGarden();
        }
        send();
       }
  }


  if (digitalRead(buttonPin) == HIGH) {
    waterGarden();
  }
}






void calcMeans(){
  light,temp,temp2,moist,moist2 = 0;

  for (int i = 0; i<arraySize; i++) {
    light += latestLight[i];
  }



  for (int i = 0; i<arraySize; i++) {
    temp += latestTemp[i];
  }


  for (int i = 0; i<arraySize; i++) {
    temp2 += latestTemp2[i];
  }



  for (int i = 0; i<arraySize; i++) {
    moist += latestMoist[i];
  }



  for (int i = 0; i<arraySize; i++) {
    moist2 += latestMoist2[i];
  }


  light/=(arraySize*10);
  light = round(light);

  temp/=arraySize;
  temp2/=arraySize;

  moist/=(arraySize*10);
  moist+=4;
  moist = round(moist);

  


  moist2/=(arraySize*10);
  moist2 = round(moist2);

}


void send() {
  sendSerial(light, lightType, lightID);
  sendSerial(temp, tempType, tempID);
  sendSerial(moist, moistType, moistID);
  sendSerial(temp2, tempType, temp2ID);
  sendSerial(moist2, moistType, moist2ID);
  // if(watered){
  //   Serial.print("<watered>");
  // }
}

void waterGarden() {
  // watered = true;
  digitalWrite(valvePin, HIGH);
  delay(10000);
  digitalWrite(valvePin, LOW);
}

void readSensors() {
  tempSensRdg = analogRead(tempPin);
  volt = tempSensRdg / 1024.0 * 5.0;
  latestTemp[index] = (volt - 0.5) * 100;
  //temp-=10 //"kalibrering"
  latestMoist[index] = analogRead(moistPin);
  latestMoist2[index] = analogRead(moist2Pin);
  latestLight[index] = analogRead(lightPin);

  sensors.requestTemperatures();       // read the temperature of all 1-wire sensors connected to the 1-wire bus
  latestTemp2[index] = sensors.getTempCByIndex(0);  // get the temperature of the first sensors in Celcius (lists start with 0 not 1)
}

void sendSerial(float data, int type, int ID) {
  String serialString = String(data);
  serialString.concat(" ");
  serialString.concat(type);
  serialString.concat(" ");
  serialString.concat(ID);

  Serial.print('<');
  Serial.print(serialString);
  Serial.print('>');
}

}

Note that the code isn't completly finished but everything necessary i think is there.

Your braces look a little screwed.

This is the code i have on the esp to read the serial data from the arduino. I use the "<" and ">" as start and stopmarkers. It may not be the prettiest communication but it has worked for me. Here is the code on the esp:

#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>


#define ON LOW
#define OFF HIGH

const byte numChars = 32;
int length;
char receivedChars[numChars];  // an array to store the received data
const int startMarker ='<';
const int stopMarker = '>';
WiFiClient wifiClient;


boolean newData = false;


void setup() {

  Serial.begin(9600);                        //Serial connection to gather from arduino
  WiFi.begin("wifiUsername", "wifipass");  //WiFi connection
  pinMode(LED_BUILTIN, OUTPUT);
  
  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion
    delay(500);
  }
  digitalWrite(LED_BUILTIN, OFF);  //this is LOW
}


void loop() {
  recvWithStartEndMarkers(); //read from serial
  if (newData == true) {
    sendHttpToServer();  //send data to server
  }
}


void sendHttpToServer() {//ändra till skicka en request med alla tre sensordata
  if (WiFi.status() == WL_CONNECTED) {  //Check WiFi connection status

    HTTPClient http;                                       //Declare object of class HTTPClient
    digitalWrite(LED_BUILTIN, ON);                         //ON
    http.begin(wifiClient,"IPAdress");  //Specify request destination

    http.POST(receivedChars);  //Send the request

    digitalWrite(LED_BUILTIN, OFF);  //OFF
    http.end();                      //Close connection

    newData = false;

  } else {
  }
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

I'm not terribly good with code, however if I were to troubleshoot a system like you have I would output the raw data from the the Arduino(?) or whatever processor that reads the sensor.

Hi, @fredagsmys
Welcome to the forum.

What are ALL your sensors? (link to data/specs)
What readings are inconsistent?

Is there a reason why the ESP32 cannot do it all?

Can you please post a copy of your schematic?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Why not just do:

void sendSerial(float data, int type, int ID) {
  Serial.print('<');
  Serial.print (data);
  Serial.print (" ");
  Serial.print (type);
  Serial.print (" ");
  Serial.print (ID);
  Serial.print('>');
}

And lose all the faff with the String class?

I have one of these: Capacitive Soil Moisture Sensor Corrosion Resistant for Arduino Moisture Detection Garden Watering DIY|Sensors| - AliExpress
And i also have one of these: 10PCS/LOT Capacitive soil moisture sensor Not easy to corrode Wide voltage operation with Wire For arduino|Integrated Circuits| - AliExpress
They are very similar just a difference in their versions: 1.2 and 2.0.

The inconsistent readings was at first from both of the sensors but now one started working as expected again after reading negatives for about 20 hours straight... :thinking:

Yes i only have an esp8266-01 and it only have digital input although i might buy an esp32 board in the future. Didnt know about it when i started out :stuck_out_tongue:

I dont have a schematic available sorry

Thank you for that input! I will change it to that, Thanks!

I read the serial data that the arduino sent to the esp which showed the same negative values that i saw in the server logs. BUT I haven't tried reading the individual sensor-values. I should try that but i'm not currently at the place where the system is and wont be in the near 5 days or so...

Does anyone have anything to solve this issue? Or maybe i just need to buy new sensors?

What new things have you uncovered in the last two weeks?
What changes have you made?
What difference did they make?

I discovered that the problem that i think caused the negative values perhaps had to do with me storing the moistures and such as integers rather than longs, I changed that and then i got somewhat reliable values,
However the values still aren't consistent... Maybe that has to do with the sensors being cheap and therefore bad.

But I wonder how changing the variable to a long from an int could make a difference... Because an integer can be way bigger than what i had :thinking:..

A long is an integer.
An int is an integer, as is a char.

Don't you think it is time we saw your code?

Yes! I posted it in the beginning of the thread, let me know if you find anything strange.

Thank you!

But it must have changed since then, so why not post the updated code?

1 Like

Hi,
Please show your now working code in a NEW post, please do not go back and edit your old post.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

1 Like

Hi, i have changed it quite a lot now, first off, i have gotten a new nodemcu 1.0 board which makes it all much easier. I have also changed the server communication to work via a websocket. Here is the updated code which works to some extent but it is still having some problems unrelated to this thread:

#include <ESP8266WiFi.h>
#include <WebSocketClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

const char* ssid = "Karsjo_1_54";
const char* password = "92ac437921";
char path[] = "/SendDataSocket";
char host[] = "192.168.1.59:1300";

WebSocketClient webSocketClient;
WiFiClient client;

String data;

#define moistID 3
#define moistType 3
#define moistPin A0

#define tempID 2
#define tempType 2

#define buttonPin 3
#define valvePin 4
#define oneWireBus 2




// const unsigned long intervall = 1800000; //30 min
// const unsigned long intervall = 900000;  //15 min
//  const unsigned long intervall = 300000; //5 min
// const unsigned long sampleIntervall = 60000;  //1 min
const unsigned long intervall = 60000;  //1 min
const unsigned long sampleIntervall = 10000; //10 sec
int arraySize = intervall / sampleIntervall;

int latestMoist[intervall / sampleIntervall];
int latestTemp[intervall / sampleIntervall];

int myIndex = 0;



const int waterBorder = 38;

unsigned long currTime;
unsigned long prevSampleTime = 0;


OneWire oneWire(oneWireBus);  // 1-wire instance on the oneWireBus pin

DallasTemperature sensors(&oneWire);

float temp;
long moist;

// Use WiFiClient class to create TCP connections


void setup() {
  Serial.begin(9600);
  pinMode(moistPin,INPUT);
  pinMode(valvePin, OUTPUT);
  pinMode(buttonPin,INPUT);

  
  WiFi.begin(ssid, password); //connect to a WiFi network

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  delay(5000);


  // Connect to the websocket server
  if (client.connect("192.168.1.59", 1300)) {
    Serial.println("Connected to socket");
  } else {
    while (1) {
      Serial.println("Failed to connect to socket");
    }
  }

  // Handshake with the server
  webSocketClient.path = path;
  webSocketClient.host = host;
  handshake();
}


void loop() {
  currTime = millis();
  checkWater();
  if (currTime - prevSampleTime > sampleIntervall) {

    if (client.connected()){
      Serial.println("Socket ready");
    }else{
      Serial.println("Socket is down, reconnecting..");
      reconnectSocket();

  }
    prevSampleTime = currTime;
    readSensors();
    myIndex++;

    if (myIndex == arraySize) {
      myIndex = 0;
      calcMeans();

      if (moist > waterBorder) {
        waterGarden();
      }
      Serial.println("Should send");
      sendToServer();
    }
  
  }

   if (digitalRead(buttonPin) == HIGH) {
     waterGarden();
     Serial.println("Watered from button");
  }
  
}


void checkWater(){
  data = "";
  webSocketClient.getData(data);
  if(data.equals("water")){
    waterGarden();
    Serial.println("Watered from mobile app");
  }
  
}




void sendToServer(){
  if (client.connected()){
    
    Serial.println("sent to server");
    webSocketClient.sendData(String(temp) + " " + String(tempType) + " " + String(tempID));
    webSocketClient.sendData(String(moist) + " " + String(moistType) + " " +String(moistID));
    Serial.println(String(temp));
    Serial.println(String(moist));
  }
  else{
    Serial.println("not connected");

}
}

void handshake(){
    if (webSocketClient.handshake(client)) {
    Serial.println("Handshake successful");
  } else {
    Serial.println("Handshake failed.");
  }
}


void calcMeans() {
  temp, moist = 0;

  for (int i = 0; i < arraySize; i++) {
    temp += latestTemp[i];
    moist += latestMoist[i];
  }


  temp /= arraySize;

  moist /= (arraySize * 10);
  moist = round(moist);
}


void waterGarden() {
  digitalWrite(valvePin, HIGH);
  Serial.println("Water started");
  delay(6000);

  Serial.println("Water ended");
  digitalWrite(valvePin, LOW);
}

void readSensors() {
  latestMoist[myIndex] = analogRead(moistPin);
  sensors.requestTemperatures();
  
  latestTemp[myIndex] = sensors.getTempCByIndex(0);
}

void reconnectSocket(){
    if (client.connect("192.168.1.59", 1300)) {
    Serial.println("Connected to socket");
    handshake();
  } else {
    Serial.println("Failed to reconnect to socket");
  }
}

I suppose we have to guess what those problems are.

No thanks.

I dont want to begin a new problem in the same thread if it is not related to it, I think this thread is done because the problem i had is now solved, thansk all for help!