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.
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.
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...
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
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...
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 ..
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 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!