PlatformIO Community

Can't get Soil Moisture and LDR analog value using cpp

guys, i want to send the soil moisture and ldr data value using mqtt and send it on json format, and i dont know the code or library i used, here is my code, the dht value is able to send, but the soil moisture and ldr not
please help me

(main.cpp)

#include <Arduino.h>
#include "ESPAsyncWebServer.h"
// #include <ESPAsyncTCP.h>
#include <definitions.h>
#include <FS.h>
#include <storage.hpp>
#include <auth.hpp>
#include <Hash.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Simple_HCSR04.h>
#include <PubSubClient.h>
#include <I2CSoilMoistureSensor.h>

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
String channelState(int numCh);
String htmlProcess(const String &var);
void deviceInit();
void mqttCallback(char *topic, byte *payload, unsigned int length);
void mqttInit();
void mqttReconnect();
String composeSensorJson();
// Replaces placeholder with button section in your web page
String htmlProcess(const String &var)
{
  Serial.println(var);
  if (var == "DNM")
  {
    return String(DeviceConfig.DeviceName);
  }
  if (var == "APSSID")
  {
    return String(DeviceConfig.ApSSID);
  }
  else if (var == "APPWD")
  {
    return String(DeviceConfig.ApPwd);
  }
  else if (var == "TETPWD")
  {
    return String(DeviceConfig.TetherPwd);
  }
  else if (var == "PUSER")
  {
    return String(DeviceConfig.PortalUser);
  }
  else if (var == "PPWD")
  {
    return String(DeviceConfig.PortalPwd);
  } 
  else if (var == "MAXSTR")
  {
    return String(MAX_CONF_STRING);
  }
  else if (var == "MAXSSID")
  {
    return String(MAX_CONF_SSID_NAME);
  }
  else if (var == "SHAPWD")
  {
    return sha1(DeviceConfig.PortalPwd);
  }
  else if (var == "FWVER")
  {
    return FW_VER;
  }
  else if (var == "PRODNAME")
  {
    return PRODUCT_NAME;
  }  
  else if (var == "SELDHT")
  {
    return DeviceConfig.Device == DeviceSelect::DHT_11 ? "selected" : "";
  }
  else if (var == "SELSOIL")
  {
    return DeviceConfig.Device == SoilMoisture ? "selected" : "";
  }
  else if (var == "SELPIR")
  {
    return DeviceConfig.Device == PIR ? "selected" : "";
  }
  else if (var == "SELLDR")
  {
    return DeviceConfig.Device == LDR ? "selected" : "";
  }
 else if (var == "SELRELAY")
  {
    return DeviceConfig.Device == Relay ? "selected" : "";
  }
  else if (var == "MQTTSRVR")
  {
    return String(DeviceConfig.MqttServer);
  }
  else if (var == "MQTTPORT")
  {
    return String(DeviceConfig.MqttPort);
  }
  else if (var == "MQTTPORTMIN")
  {
    return "3";
  }
  else if (var == "MQTTPORTMAX")
  {
    return "6";
  }
  else if (var == "MQTTUSER")
  {
    return String(DeviceConfig.MqttUser);
  }
  else if (var == "MPWD")
  {
    return String(DeviceConfig.MqttPwd);
  }
 
  else if (var == "MQTTPUB")
  {
    return String(DeviceConfig.MqttPub);
  }
  else if (var == "MQTTSUB")
  {
    return String(DeviceConfig.MqttSub);
  }
  else if (var == "MQTTPUBSEC")
  {
    return String(DeviceConfig.MqttPubSec);
  }
  return String();
}

// Set IP addresses
IPAddress apLocalIp(192, 168, 1, 1);
IPAddress apLocalIpGateway(192, 168, 1, 1);
IPAddress apLocalIpSubnet(255, 255, 255, 0);

uint64_t lastMsWiFiSta, lastMsHb;

I2CSoilMoistureSensor *soil = nullptr;
DHT_Unified *dht = nullptr;
Simple_HCSR04 *hcsr = nullptr;
WiFiClient espClient;
PubSubClient client(espClient);


void setup()
{

  //Serial port for debugging purposes
  Serial.begin(115200);

  deviceInit();

  // Initialize SPIFFS
  if (!SPIFFS.begin())
  {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  loadConfig();
  WiFi.setHostname(DeviceConfig.DeviceName);
  WiFi.begin();

  pinMode(LED_HB, OUTPUT);

  // Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(DeviceConfig.ApSSID, DeviceConfig.ApPwd);

  // Route for web pages

  server.on(WEB_PAGE_ROOT, HTTP_GET, [](AsyncWebServerRequest *request) {
    handleRedirect(request);
  });
  server.on(WEB_PAGE_INDEX, HTTP_GET, [](AsyncWebServerRequest *request) {
    if (!handleLoginAuth(request))
      return;
    request->send(SPIFFS, WEB_FILE_INDEX, CONTENT_TYPE_HTML, false, htmlProcess);
  });
  server.on(WEB_FAVICON, HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(SPIFFS, WEB_FILE_FAVICON, CONTENT_TYPE_PNG, false);
  });
  server.on(WEB_PAGE_LOGIN, HTTP_ANY, [](AsyncWebServerRequest *request) {
    handleLoginPage(request);
  });
  server.on(WEB_PAGE_SETTINGS, HTTP_GET, [](AsyncWebServerRequest *request) {
    if (!handleLoginAuth(request))
      return;
    request->send(SPIFFS, WEB_FILE_SETTINGS, CONTENT_TYPE_HTML, false, htmlProcess);
  });
  server.on(WEB_PAGE_LOGOUT, HTTP_GET, [](AsyncWebServerRequest *request) {
    handleLogout(request);
  });
  server.on(WEB_PAGE_REBOOT, HTTP_GET, [](AsyncWebServerRequest *request) {
    if (!handleLoginAuth(request))
      return;
    request->send(SPIFFS, WEB_FILE_REBOOT, CONTENT_TYPE_HTML, false, htmlProcess);
  });
  server.on(WEB_PAGE_REBOOT_NOW, HTTP_GET, [](AsyncWebServerRequest *request) {
    if (!handleLoginAuth(request))
      return;
    ESP.restart();
  });

  // Send a GET request to <ESP_IP>/updt
  server.on(WEB_PAGE_UPDATE, HTTP_GET, [](AsyncWebServerRequest *request) {
    if (!handleLoginAuth(request))
      return;
    String resp = composeSensorJson();
    Serial.print("RESP: ");
    Serial.println(resp);
    request->send(200, CONTENT_TYPE_JSON, resp);
  });

  server.on(WEB_PAGE_SETTINGS_SAVE, HTTP_POST, [](AsyncWebServerRequest *request) {
    if (!handleLoginAuth(request))
      return;
    for (int i = 0; i < request->params(); i++)
    {
      Serial.print("Prm:");
      Serial.println(request->getParam(i)->value());
      if (request->getParam(i)->name().equals(PARAM_INPUT_DEVICE_NAME))
      {
        String deviceName = request->getParam(i)->value();
        if (deviceName.length() > 0 && deviceName.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.DeviceName, deviceName.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_TETHERING_PWD))
      {
        String tetPwd = request->getParam(i)->value();
        if (tetPwd.length() > 0 && tetPwd.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.TetherPwd, tetPwd.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_AP_SSID))
      {
        String apSsid = request->getParam(i)->value();
        if (apSsid.length() > 0 && apSsid.length() <= MAX_CONF_SSID_NAME)
        {
          strcpy(DeviceConfig.ApSSID, apSsid.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_AP_PWD))
      {
        String apPwd = request->getParam(i)->value();
        if (apPwd.length() > 0 && apPwd.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.ApPwd, apPwd.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_PORTAL_USERNAME))
      {
        String pUser = request->getParam(i)->value();
        if (pUser.length() > 0 && pUser.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.PortalUser, pUser.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_PORTAL_PWD))
      {
        String pPwd = request->getParam(i)->value();
        if (pPwd.length() > 0 && pPwd.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.PortalPwd, pPwd.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_SENSOR_SEL))
      {
        String val = request->getParam(i)->value();

        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          DeviceConfig.Device = static_cast<DeviceSelect>(val.toInt());
        }
      }
      //mqtt
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_SERVER))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.MqttServer, val.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_PORT))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          DeviceConfig.MqttPort = val.toInt();
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_USER))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.MqttUser, val.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_PWD))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.MqttPwd, val.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_PUB_TOPIC))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.MqttPub, val.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_SUB_TOPIC))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          strcpy(DeviceConfig.MqttSub, val.c_str());
        }
      }
      if (request->getParam(i)->name().equals(PARAM_INPUT_MQTT_PUB_SEC))
      {
        String val = request->getParam(i)->value();
        if (val.length() > 0 && val.length() <= MAX_CONF_STRING)
        {
          DeviceConfig.MqttPubSec = val.toInt();
        }
      }
    }
    request->redirect(WEB_PAGE_ROOT);
    saveConfig();
    deviceInit();
    mqttInit();
    if (client.connected())
    {
      client.disconnect();
    }
  });

  server.serveStatic(WEB_PAGE_ASSETS, SPIFFS, WEB_PAGE_ASSETS);

  // Start server
  server.begin();

  lastMsWiFiSta = millis();

  mqttInit();
  mqttReconnect();
  Serial.println("Started...");
}

void deviceInit()
{
  Serial.println("Device init...");
  if (DeviceConfig.Device == DeviceSelect::DHT_11)
  {
    dht = new DHT_Unified(AIO_SENSOR_PIN_1, DHT11);
    Serial.print("Using DHT...");
    dht->begin();
    sensor_t sensor;
    dht->temperature().getSensor(&sensor);
    dht->humidity().getSensor(&sensor);
  }
  else if (DeviceConfig.Device == PIR || DeviceConfig.Device == LDR /*||
           DeviceConfig.Device == Sound*/)
  {
    Serial.print("Using digital sensor...");
    pinMode(AIO_SENSOR_PIN_1, INPUT);
  }
  else if (DeviceConfig.Device == Relay)
  {
    Serial.print("Using relay...");
    pinMode(AIO_SENSOR_PIN_1, OUTPUT);
  }
  else if (DeviceConfig.Device == Distance)
  {
    Serial.print("Using distance ensor...");
    hcsr = new Simple_HCSR04(DISTANCE_ECHO_PIN, DISTANCE_TRIG_PIN);
  }
  else if (DeviceConfig.Device == SoilMoisture)
  {
    Serial.print("Using Soil Moisture sensor...");
    pinMode(AIO_SENSOR_PIN_1, INPUT); 
  }
}

void mqttInit()
{
  client.setServer(DeviceConfig.MqttServer, DeviceConfig.MqttPort);
  client.setCallback(mqttCallback);//fungsi yang akan diesekusi ketika mqtt mendapat data masuk
}

void mqttCallback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if (strcmp(topic, DeviceConfig.MqttSub) == 0)
  {
    Serial.print("Recvd relay command parse code: ");
    StaticJsonDocument<100> doc;
    DeserializationError error = deserializeJson(doc, (char *)payload);
    Serial.println(error.code());
    if (error == DeserializationError::Ok)
    {
      if (doc.containsKey("state") && doc["state"].is<int>())
      {
        DeviceConfig.RelayOn = (doc["state"].as<int>() == 1);
        Serial.print("Changing state: ");
        Serial.print(DeviceConfig.RelayOn );
        Serial.println();
      }
    }
  }
}

uint32_t lastReconnectMs = 0;
void mqttReconnect()
{
  if (!client.connected() && WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED &&
       millis() - lastReconnectMs > 5000)
  {
    Serial.print("Attempting MQTT connection...");
    String clientId = String(DeviceConfig.DeviceName) + "-";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str(), DeviceConfig.MqttUser, DeviceConfig.MqttPwd))
    {
      Serial.println("connected");
      if (DeviceConfig.Device == Relay)
      {
        client.setCallback(mqttCallback);
        Serial.println("Subscribing " + String(DeviceConfig.MqttSub) + (client.subscribe(DeviceConfig.MqttSub) ? " OK" : " FAIL"));
      }
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
    }
    lastReconnectMs = millis();
  }
}

#define FIRE_THRESH 1000

String composeSensorJson()
{
  DynamicJsonDocument doc(2048);

  JsonObject devData = doc.createNestedObject("data");

  if (DeviceConfig.Device == DeviceSelect::DHT_11)
  {
#ifdef DUMMY_SENSOR
    devData["humidity"] = "40 %";
    devData["temperature"] = "33.4 celcius";

#else
    if (dht == nullptr)
      deviceInit();
    sensors_event_t event;
    dht->temperature().getEvent(&event);
    if (isnan(event.temperature))
    {
      Serial.println(F("Error reading temperature!"));
      devData["temperature"] = "error";
    }
    else
    {
      Serial.print(F("Temperature: "));
      Serial.print(event.temperature);
      Serial.println(F("°C"));
      devData["temperature"] = String(event.temperature);// + " celcius";
    }
    // Get humidity event and print its value.
    dht->humidity().getEvent(&event);
    if (isnan(event.relative_humidity))
    {
      Serial.println(F("Error reading humidity!"));
      devData["humidity"] = "error";
    }
    else
    {
      Serial.print(F("Humidity: "));
      Serial.print(event.relative_humidity);
      Serial.println(F("%"));
      devData["humidity"] = String(event.relative_humidity) ;//+ " %";
    }

#endif
  }
  else if (DeviceConfig.Device == DeviceSelect::PIR)
  {
    devData["detection"] = (digitalRead(AIO_SENSOR_PIN_1) == PIR_ACTIVE) ? "Motion Detected" : "No Motion Detected";
  }
  // else if (DeviceConfig.Device == DeviceSelect::SoilMoisture)
  // {
  //   devData["detection"] = (digitalRead(AIO_SENSOR_PIN_1) == PIR_ACTIVE ? "Dry" : "Wet");
  // }
  //else if (DeviceConfig.Device == DeviceSelect::LDR)
  //{
  //  devData["detection"] = (digitalRead(AIO_SENSOR_PIN_1) == PIR_ACTIVE ?  "High" : "Low");
  //}
  else if (DeviceConfig.Device == DeviceSelect::LDR)
  {
    devData["value"] = (analogRead(AIO_SENSOR_PIN_1));
  }
  else if(DeviceConfig.Device == DeviceSelect::SoilMoisture){
    #ifdef DUMMY_SENSOR
    devData["moisture"] = "32.4 ";
#else
    if (soil == nullptr)

    devData["moisture"] = (analogRead(AIO_SENSOR_PIN_1)); //+ " cm";
#endif
    //float test = analogRead(AIO_SENSOR_PIN_1);
    //devData["Moisture"] = String(test);
  }

  /*else if (DeviceConfig.Device == DeviceSelect::SoilMoisture)
  {
#ifdef DUMMY_SENSOR
    devData["moisture"] = "180";
#else
  if(soil == nullptr)
    deviceInit();
  devData["moisture"] = String(analogRead(AIO_SENSOR_PIN_1));
#endif
  }
  else if (DeviceConfig.Device == DeviceSelect::Sound)
  {
    devData["analog_reading"] = (digitalRead(AIO_SENSOR_PIN_1) == PIR_ACTIVE ? "Sound detected" : "No Sound");
  }
  else if (DeviceConfig.Device == DeviceSelect::Distance)
  {
#ifdef DUMMY_SENSOR
    devData["distance"] = "32.4 cm";
#else
    if (hcsr == nullptr)
      deviceInit();
    devData["distance"] = String(hcsr->measure()->cm()) + " cm";
#endif
  }*/
  else if (DeviceConfig.Device == DeviceSelect::Relay)
  {
    devData["state"] = (DeviceConfig.RelayOn ? "ON" : "OFF");
  }
  doc["device_type"] = DEVICE_NAME[DeviceConfig.Device - 1];
  doc["local_ip"] = WiFi.localIP().toString();

  String ret;
  serializeJsonPretty(doc, ret);
  return ret;
}

bool toggleHb = true;
bool staConnected = false;
uint64_t lastSendMs = 0;
void loop()
{
  if (WiFi.getMode() == WIFI_STA && WiFi.status() != WL_CONNECTED && millis() - lastMsWiFiSta > CONNECT_STA_TIMEOUT)
  {
    Serial.print("Dropping AP mode ");
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apLocalIp, apLocalIpGateway, apLocalIpSubnet);
    WiFi.softAP(DeviceConfig.DeviceName, DeviceConfig.TetherPwd);
    WiFi.setHostname(DeviceConfig.DeviceName);
    staConnected = false;
    Serial.println("OK");
  }
  else if (WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED)
  {
    lastMsWiFiSta = millis();
    if (!staConnected)
    {
      staConnected = true;
      Serial.println(String("Connected to [") + WiFi.SSID() + "] IP: " + WiFi.localIP().toString());
      WiFi.setHostname(DeviceConfig.DeviceName);
    }
  }

  if (millis() - lastMsHb > HB_PERIOD_MS)
  {
    lastMsHb = millis();
    digitalWrite(LED_HB, !digitalRead(LED_HB));
  }

  mqttReconnect();
  if (client.connected() && millis() - lastSendMs >= (DeviceConfig.MqttPubSec * 1000))
  {
    Serial.print("Publishing:");
    String json = composeSensorJson();
    Serial.println(json);
    Serial.println(client.publish(DeviceConfig.MqttPub, json.c_str()) ? "OK" : "FAIL");
    lastSendMs = millis();
  }
  if (DeviceConfig.Device == Relay) {
    digitalWrite(AIO_SENSOR_PIN_1, DeviceConfig.RelayOn ? RELAY_ACTIVE : RELAY_INACTIVE);
  }
  client.loop();
}

That’s your code but you don’t know the the code or used library?

Take a look at this code. Depending on DeviceConfig.Device it only sends data for one particular sensor. Rewrite this part to send all irregardless of device config.

Thank you for your help

im sorry, im totally new for this.
I’ve tried to rewrite the code, but I still can’t get the value, it only works for digital reading
can you give me the code that i must write please :slight_smile:

By the way, this is not my own code, this is an assignment code from my lecturer

Thank you :slight_smile:

In the code part above (and only there), have you already tried to comment out all lines that start with

if (DeviceConfig.Device == 

or (else if (DeviceConfig.Device == ..)? You can even leave the { and } in.

1 Like

i tried this code, but the value is 0

else if(DeviceConfig.Device == DeviceSelect::SoilMoisture)
{
    devData["moisture"] = (analogRead(AIO_SENSOR_PIN_1));
}

So it does create the JSON object but the moisture field is 0?
Have you looked into

as to what AIO_SENSOR_PIN_1 resolves to and checked that that pin is connected properly to the moisture sensor (along with power + gnd)?

the AIO_SENSOR_PIN_1 expands to pin 4 and the power + gnd are connected properly

What’s the voltage on IO4 then? 0V would match a read ADC value of 0.

the voltage on IO4 3.3 V

Weird. When I read https://deepbluembedded.com/esp32-adc-tutorial-read-analog-voltage-arduino/ it says

ADC2 is used by the Wi-Fi driver. Therefore the application can only use ADC2 when the Wi-Fi driver has not been started.

And IO4 is ADC2_0 per the picture underneath it. Can you change this to a different pin, e.g. IO36, which is ADC1_0, in soft- and hardware?

i don’t know what’s the problem, but when i try digital read, the sensor can return low or high value

Sure the pin will work as a GPIO, but not as ADC. Have you tried per above?

image
this happen when i try to use ADC1 pin (i tried 33, 34, and 36)

Mhm can you connect the moisture sensor back to GPIO4, does it allow upload then?

yeah, it’s only happen when i use ADC1 pin :frowning:

wait, my bad, i can use adc1 pin, but the value is 4095

 else if(DeviceConfig.Device == DeviceSelect::SoilMoisture)
  {
    devData["moisture"] = String(analogRead(AIO_SENSOR_PIN_3)); //AIO_SENSOR_PIN_3 expand to pin 32
  }

this is my code

Which matches that the pin reads 3.3V.

Readings go from 0 (=0V) to 4095 (=3.3V).

I think you have to put the sensor in some soil to get a different reading.

It work now sir

the actual problem is about the ADC things :sweat_smile:

THANKS for your help

Apreciate it so much ;))