ESP8266 MCU: RS485 pH sensor reading zero value

Hi,

I only have the RX pin left in my ESP8266 D1 mini microcontroller as all other pins are occupied. I have connected my pH sensor via a MAX485 transceiver to the MCU. The R0 pin of the MAX485 module is connected to the RX pin of the ESP8266. RE and DE pins of the MAX485 module are connected to 5V supply to provide a high signal and put it in a permanent transmitter mode. DI is not connected to anything at all. The pH reading is zero however. I only need to read the pH data from the RS485 module. Hence, it is only a half duplex communication. Below is my code. please help me find the issue. Thank you.

float PH;
#include <SoftwareSerial.h>
// Define the RX pin of the ESP8266
const int rxPin = RX;
// Create a SoftwareSerial object
SoftwareSerial rs485(rxPin, rxPin);
byte pHBuffer[10];
int pHBufferIndex = 0;


void setup() {
  // Set the baud rate of the SoftwareSerial object
  rs485.begin(115200);
}

void loop()
{
// Check if there is any data available
if (rs485.available()) {
    pHBuffer[pHBufferIndex++] = rs485.read();
  }

  if (pHBufferIndex >= 10) {
    // All of the pH data has been received.
    // Read the pH value from the buffer.
    PH = pHBuffer[0];

    // Clear the buffer.
    pHBufferIndex = 0;

// Print the data to the serial monitor
    Serial.print(PH);

 }
}

Please provide a full diagram. If the sensor has a RS485 port, then the MAX485 transceiver should be in 'Receive' mode not transmitter mode, therefore !RE & DE should be pulled LOW. Also if the MAX485 is powered with 5v as it should most likely be, that means that RO is using 5v logic levels, depending on the esp8266 that you use you should drop that down to 3.3v using a voltage divider.

There is no need for swSerial. You have hwSerial available on the esp on GPIO3 & GPIO 1. If you need GPIO 1 for something else you can set the pinMode after you have called

Serial.begin(115200);
pinMode(1, INPUT);

Eh...

SoftwareSerial rs485(rxPin, rxPin);

this will never work. You can not set the same pin for RX & TX. In the end it may result in either RX or TX working, but that will just depend on which pin is setup last for the task it is expected to perform.

This is clearly not the complete code, since there are still many pins available. Whatever other parts of the code you have omitted, may have an effect on the whole that you may not see (or not of course) . By leaving all of that out you create the possibility that the advice you receive is incorrect (it may still be of course).

Ditch SoftwareSerial

Hi Deva,

thanks for replying. I am unable to upload the full cct diagram as I am a new user. I did not post the full code because its too long. But for sure I have no more pins vacant except for RX and A0 in the ESP8266. I will try pulling RE and DE low and ditch swserial . But then what would the replacement for SoftwareSerial rs485(rxPin, rxPin); be?

Your code should look like this

float PH;

byte pHBuffer[10];
int pHBufferIndex = 0;


void setup() {
  // Set the baud rate of the SoftwareSerial object
  Serial.begin(115200);
  pinMode(1, THEMODE); // calling this after Serial begin will change the pinmode from it's UART connection.
}

void loop()
{
// Check if there is any data available
if (Serial.available()) {
    pHBuffer[pHBufferIndex++] = Serial.read();
  }

  if (pHBufferIndex >= 10) {
    // All of the pH data has been received.
    // Read the pH value from the buffer.
    PH = pHBuffer[0];

    // Clear the buffer.
    pHBufferIndex = 0;

// Print the data to the serial monitor
    //Serial.print(PH); // This you can not use if the TX pin is anyway otherwise in use.
   
 }
}

If you do have feedback from the Serial monitor then the TX pin is clearly not being used.

To long for what ?
For sure you can upload a picture, and the whole code.

As you have not provided details on your particular pH sensor, this may not be relevant, but, usually with an RS485 based comms system, the remote device (in this case your pH sensor) won't transmit data unless it receives a message from the host to do so.

my pH sensor is a RS485 IP68 Waterproof Digital Garden Greenhouse pH Meter Sensor

• IP68 waterproof and dust proof rated. i.e., water resistant in fresh water to a maximum depth of 1.5m for up to 30 minutes.
• High accuracy, reliable and quick response time. 3 to 9 pH can be measured with up to ±0.3pH accuracy.
• DC Power Supply (default): 12-24V DC
• Power Consumption: ≤ 0.15W (@12V DC, 25℃)
• Long-term Stability: ≤5%/y
• Output Signal: RS485/0-5V / 0-10V / 4-20mA output
• Operating Temperature: 0-55℃
• Response Speed: ≤15S

An id / datasheet of the actual sensor or a link to where you got it from would help.

https://www.amazon.com/Worii-Waterproof-Digital-Greenhouse-Transmitter/dp/B088TJ56PC

above is the link

@Deva_Rishi below is the full code I have compiled prior to your recomendations

#include <Adafruit_ADS1X15.h>

Adafruit_ADS1015 ads;     /* Use this for the 12-bit version */

//FirebaseESP8266.h must be included before ESP8266WiFi.h
#include "FirebaseESP8266.h"
#include <ESP8266WiFi.h>
#include <DHT11.h>

#define FIREBASE_HOST "          " //Without http:// or https:// schemes
#define FIREBASE_AUTH "     "
#define WIFI_SSID "       "   //
#define WIFI_PASSWORD "       "
#define LED_PIN 12
#define LED2_PIN 13
#define LED3_PIN 15
#define LED4_PIN 2
#define LED5_PIN 0
#define LED6_PIN 16
#define LED7_PIN TX

DHT11 dht11(14);

float gas, pressu, pho, soil;
float PH;
float humidity;
float temperature;

//Define FirebaseESP8266 data object
FirebaseData firebaseData;

String path = "/values";  // change it accord with the project firebase
unsigned long sendDataPrevMillis = 0;
unsigned long previousMillis = 0;
const int interval = 60000;
uint16_t count = 0;
void printResult(FirebaseData &data);

#include <SoftwareSerial.h>

// Define the RX pin of the ESP8266
const int rxPin = RX;

// Create a SoftwareSerial object
SoftwareSerial rs485(rxPin, rxPin);
byte pHBuffer[10];
int pHBufferIndex = 0;

void setup()
{

  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED2_PIN, OUTPUT);
  pinMode(LED3_PIN, OUTPUT);
  pinMode(LED4_PIN, OUTPUT);
  pinMode(LED5_PIN, OUTPUT);
  pinMode(LED6_PIN, OUTPUT);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);

  //Set the size of WiFi rx/tx buffers in the case where we want to work with large data.
  firebaseData.setBSSLBufferSize(1024, 1024);

  //Set the size of HTTP response buffers in the case where we want to work with large data.
  firebaseData.setResponseSize(1024);

  if (!ads.begin()) {
    while (1);
  }

  // Set the baud rate of the SoftwareSerial object
  rs485.begin(115200);

}

void loop()
{
  updateTimeStamp();
  int16_t adc0, adc1, adc2, adc3;
  float volts0, volts1, volts2, volts3;

  // Read the photoresistor from the sensor.
  adc0 = ads.readADC_SingleEnded(0);
  pho = map(adc0, 0, 1300, 0, 500);
  Serial.println(adc0);
  // Read the pressure from the sensor.
  adc1 = ads.readADC_SingleEnded(1);
  pressu = map(adc1, 0, 1400, 0, 900);
    // Read the gas from the sensor.
  adc2 = ads.readADC_SingleEnded(2);
  gas = map(adc2, 0, 1400, 0, 14000);
    // Read the soilmoisture from the sensor.
  adc3 = ads.readADC_SingleEnded(3);
  soil = map(adc3, 350, 1800, 100, 0);
  Serial.println("adc=");
  Serial.println(adc2);
  Serial.println("gas");
  Serial.println(gas);
  
  // Read the humidity from the sensor.
  humidity = dht11.readHumidity();
  // Read the temperature from the sensor.
  temperature = dht11.readTemperature();

// Check if there is any data available
if (rs485.available()) {
    pHBuffer[pHBufferIndex++] = rs485.read();
  }

  if (pHBufferIndex >= 10) {
    // All of the pH data has been received.
    // Read the pH value from the buffer.
    PH = pHBuffer[0];

    // Clear the buffer.
    pHBufferIndex = 0;

// Print the data to the serial monitor
    Serial.print(PH);
  
  }
  
  Serial.print(pho); Serial.print("\t");
  Serial.print(pressu); Serial.print("\t");
  Serial.print(soil); Serial.print("\t");
  Serial.print(gas); Serial.print("\t");
  Serial.println();
  
  // to send the data from the sensor to firebase vvvvv
  Firebase.setString(firebaseData, path + "/ PHOTORESITOR" , pho); 
  Firebase.setString(firebaseData, path + "/ Pressure Sensor " , pressu);
  Firebase.setString(firebaseData, path + "/ GAS Sensor " , gas);
  Firebase.setString(firebaseData, path + "/Soil moisture" , soil );
  Firebase.setString(firebaseData, path + "/readHumidity" , humidity);
  Firebase.setString(firebaseData, path + "/readTemperature" , temperature);
  Firebase.setString(firebaseData, path + "/PH" , PH);

  Firebase.getString(firebaseData, "/values/PHOTORESITOR_DATA"); // to get the PHOTORESITOR data from firebase
  Serial.println(firebaseData.stringData());
  String PHOTORESITOR_DATA = firebaseData.stringData();
  Serial.println("PHOTORESITOR_DATA=");
  Serial.println(PHOTORESITOR_DATA);
  if ( PHOTORESITOR_DATA.toInt() >= pho)
  {
    Serial.println("inside1");
    digitalWrite(LED_PIN, 1);
  }
  else

  {
    digitalWrite(LED_PIN, 0);
  }
  /// GAS
  Firebase.getString(firebaseData, "/values/GAS_Sensor_DATA"); // to get the GAS data from firebase
  Serial.println(firebaseData.stringData());
  String  GAS_DATA = firebaseData.stringData();
  Serial.println("GAS_DATA=");
  Serial.println(GAS_DATA);
  if ( GAS_DATA.toInt() >= gas)
  {
    Serial.println("inside2");
    digitalWrite(LED3_PIN, 1);
  }
  else

  {
    digitalWrite(LED3_PIN, 0);
  }
//Pressure
  Firebase.getString(firebaseData, "/values/Pressure_Sensor_DATA"); // to get the Pressure data from firebase
  Serial.println(firebaseData.stringData());
  String  Pressure_DATA = firebaseData.stringData();
  Serial.println("Pressure_DATA=");
  Serial.println(Pressure_DATA);
  if ( Pressure_DATA.toInt() >= pressu)
  {
    Serial.println("inside3");
    digitalWrite(LED2_PIN, 1);
  }
  else

  {
    digitalWrite(LED2_PIN, 0);
  }

//Soil_moisture
  Firebase.getString(firebaseData, "/values/Soil_moisture_DATA"); // to get the Soil_moisture data from firebase
  Serial.println(firebaseData.stringData());
  String  moisture_DATA = firebaseData.stringData();
  Serial.println("moisture_DATA=");
  Serial.println(moisture_DATA);
  if ( moisture_DATA.toInt() >= soil)
  {
    Serial.println("inside4");
    digitalWrite(LED4_PIN, 1);
  }
  else

  {
    digitalWrite(LED4_PIN, 0);
  }

//PH
  Firebase.getString(firebaseData, "/values/PH_DATA"); // to get the PH data from firebase
  Serial.println(firebaseData.stringData());
  String PH_DATA = firebaseData.stringData();
  Serial.println("PH_DATA=");
  Serial.println(PH_DATA);
  if ( PH_DATA.toInt() >= PH)
  {
    Serial.println("inside7");
    digitalWrite(LED7_PIN, 1);
  }
  else

  {
    digitalWrite(LED7_PIN, 0);
  }
  
  //TEMPREATURE
  // If the temperature and humidity readings were successful, print them to the serial monitor.
  Firebase.getString(firebaseData, "/values/TEMPREATURE_DATA");  // to get the TEMPREATURE data from firebase
  if (temperature != -1 && humidity != -1)
  {
    Serial.print("Temperature: ");
    Serial.print(temperature);
    Serial.println(" C");
    Serial.println(firebaseData.stringData());
    String  TEMPREATURE_DATA = firebaseData.stringData();
    if ( TEMPREATURE_DATA.toInt() >= temperature)
    {
      Serial.println("inside4");
      digitalWrite(LED6_PIN, 1);
    }
    else

    {
      digitalWrite(LED6_PIN, 0);
    }
	// Humidity
    Serial.print("Humidity: ");
    Serial.print(humidity);
    Serial.println(" %");
    Firebase.getString(firebaseData, "/values/HUMIDITY_DATA"); // to get the Humidity data from firebase
    String  HUMIDITY_DATA = firebaseData.stringData();
    if ( HUMIDITY_DATA.toInt() >= humidity)
    {
      Serial.println("inside4");
      digitalWrite(LED5_PIN, 1);
    }
    else

    {
      digitalWrite(LED5_PIN, 0);
    }
  }
  else
  {
    // If the temperature or humidity reading failed, print an error message.
    Serial.println("Error reading data");
  }

  // Wait for 2 seconds before the next reading.

  delay(1000);

}

void updateTimeStamp()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    FirebaseJson json;
    json.set("Photoresistor", pho);
    json.set("Gas", gas);
    json.set("Soil moisture", soil);
    json.set("Temperature", temperature);
    json.set("Humidity", humidity);
    json.set("Pressure", pressu);
    json.set("PH", PH);
    json.set("Ts/.sv", "timestamp");
    Serial.println("updateTimeStamp: " );
    Serial.printf("Push data with timestamp... %s\n", Firebase.pushJSON(firebaseData, "/history of farm1", json) ? "ok" : firebaseData.errorReason().c_str());
    previousMillis = currentMillis;
  }
}


The 5th photo on the Amazon page you linked to shows the part/model number as 3001-PH-RS.

A quick google search suggests that it might be a JXBS-3001-PH-RS manufactured by JXPT. The web page for the possible sensor is here.

A further google search for that part number quickly located a PDF of a user manual.

I couldn't find much on the manufacturer that Amazon indicate. It could well be a rebadged JXPT device.

If your sensor is the one (rebadged or cloned etc) sold by JXPT, then that datasheet I located indicates that it uses the Modbus protocol the extract information from the sensor. That means that you would need to have a 2 way conversation with it in order to get each pH reading - i.e. you need to be able to transmit a message to the pH sensor in order to get it to report back the pH reading.

Thanks, but the pH sensor I have at hand is the one shown in the first 3 photos. The ones with the grey sticker on it. Anyway if the sensor requires two way communication I presume you're suggesting me to use both RX and TX pins of the ESP8266. Plus I will have to connect the DI pin of the RS485 to the TX pin of the ESP8266?

For 2 way Comms you do need Tx + Rx (DI & RO) and RE + DE. Note that you can drive RE & DE from 1 pin - so 3 pins in total.

EDIT:

I would not reply simply on photos on an Amazon website to determine which device you have.

Are there any labels on your pH sensor that would give a clue as to the actual part number and/or manufacturer.

Did you get any user manual/guide with your pH sensor? If you didn't, then I would suggest you ask for some documentation. If the seller can't provide it, then return the sensor to them and look for an alternative that comes with the relevant supporting documentation.

Well in the manual there is stated

Baud rate
2400bps/4800bps/9600bps Optional. Can Customize. Default is 9600bps

And yes an inquiry needs to be sent (see section 4.4)

I do not find the manual very clear on how to implement this for another MCU not using the PC software, but i guess it could be done, with a bit of trial and error, and maybe even easier by installing the software, Making contact with the sensor thru the PC and sniff the RS485 bus and find out what is being transmitted between them.

Yes, and you may need a voltage divider between the ESP RX and Ri of the MAX485.

Now other than the baud rate, i think your sketch has some more issues.
GPIO 15 is and should always be connected to GND so the LED needs to be connected active HIGH (eg GPIO 15 -> Resistor -> LED -> GND)
whereas GPIO 0, 2 & 1 (although 1is TX and we will need it) should be connected active LOW or the wrong boot mode will be selected.

As the sketch is now you will not see anything on the Serial monitor, since you change the pinmode of the TX pin to OUTPUT, after which it is disconnected from the UART (FUNCTION_0 or SPECIAL selects it as the UART0 tx pin)
You are just wasting pins on lighting up leds. There are ways to do this that involve a lot less pins.

Using MAX3485 in stead of MAX485. No need for divider.

That is not what the OP is using is it ?

Your valuable suggestions are much appreciated. I will perform some trial and error and try to crack this issue. Thanks guys.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.