ARDUINO MEGA 2560 (sender) to ESP8266 NodeMCU via Serial1 communication

Hi everyone, badly need help, I connect theboth microcontrollers via level shifter bi-directional and I use tx1 (18 pin) to rx1 pin 19 in arduino mega. I don't know if my approach is correct cause RX is blinking instead the TX light indicator. i use esp8266 for communicating through the blynk app:

#include <EEPROM.h>
#include <NewPing.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "DFRobot_EC.h"
#include "GravityTDS.h"


// Pin assignments
const int phPin1 = A0;   // Pre-test pH sensor
const int phPin2 = A1;   // Post-test pH sensor
const int ecPin1 = A2;   // Pre-test EC sensor
const int ecPin2 = A3;   // Post-test EC sensor
const int tempPin1 = 4;  // Pre-test temperature sensor
const int tempPin2 = 5;  // Post-test temperature sensor
const int tdsPin1 = A8;  // Pre-test TDS sensor
const int tdsPin2 = A9;  // Post-test TDS sensor
const int turbidityPin1 = A10; // Pre-test turbidity sensor
const int turbidityPin2 = A11; // Post-test turbidity sensor


const int TRIGGER_PIN = 6;  // Ultrasonic sensor trigger
const int ECHO_PIN  = 7;  // Ultrasonic sensor echo
const int MAX_DISTANCE = 200; 

// Relay pin assignments
int relayPump1 = 9; // Pump 1 relay
int relayPump2 = 10; // Pump 2 relay
int relayValve = 8;  // Solenoid valve relay


// Variables for sensor readings
float pH1, pH2, ec1, ec2, temp1, temp2, tds1, tds2, turbidity1, turbidity2, distance;

// Calibration coefficients (these will be loaded from EEPROM)
float TDS1_value, TDS2_value; // Store TDS values directly from EEPROM

// Variables for turbidity2 smoothing
const int numReadings = 10;
int readings1[numReadings];
int readings2[numReadings];
int index1 = 0;
int index2 = 0;
float total1 = 0;
float total2 = 0;
float average1 = 0;
float average2 = 0;
float filteredValue1 = 0;
float filteredValue2 = 0;
float alpha = 0.1;

const float tempCoefficient = 0.003; // Adjust if needed

// SoftwareSerial setup for ESP8266 communication
SoftwareSerial espSerial(19, 18); // RX, TX

// Function prototypes
float readUltrasonic();
float readCalibratedPH(int pin, float temp);
float readCalibratedEC(int pin, float temp, float K);

// Setup for temperature sensors
OneWire oneWire1(tempPin1);
OneWire oneWire2(tempPin2);
DallasTemperature sensors1(&oneWire1);
DallasTemperature sensors2(&oneWire2);

// Initialize EC sensor objects
DFRobot_EC ec1_sensor, ec2_sensor;

// Initialize TDS sensor objects
GravityTDS tds1_sensor, tds2_sensor;

// Calibration values for pH sensor 1
float pH_voltage_4_01 = 2.869;      // Voltage for pH 4.01
float pH_voltage_6_86 = 2.5;     // Voltage for pH 6.86
float pH_voltage_9_18 = 2.20;      // Voltage for pH 9.18

// Calibration values for pH sensor 2
float voltage_4_01 = 2.92;
float voltage_6_86 = 2.5;
float voltage_9_18 = 2.20;


//ph solutions
float pH_4_01 = 4.01;
float pH_6_86 = 6.86;
float pH_9_18 = 9.18;

// EC Variables
float voltage, ecValue, temperature = 25;



void setup() {
    Serial.begin(9600);
    Serial1.begin(9600);

    // Initialize pin modes
    pinMode(relayPump1, OUTPUT);  // Set pump 1 relay as OUTPUT
    pinMode(relayPump2, OUTPUT);  // Set pump 2 relay as OUTPUT
    pinMode(relayValve, OUTPUT);  // Set valve relay as OUTPUT
    digitalWrite(relayPump1, LOW);
    digitalWrite(relayPump2, LOW);
    digitalWrite(relayValve, LOW);

    // Initialize sensors
    sensors1.begin();
    sensors2.begin();
    ec1_sensor.begin();
    ec2_sensor.begin();
    tds1_sensor.setPin(tdsPin1);
    tds2_sensor.setPin(tdsPin2);
    tds1_sensor.setAref(5.0);
    tds2_sensor.setAref(5.0);
    tds1_sensor.setAdcRange(1024);
    tds2_sensor.setAdcRange(1024);
    tds1_sensor.begin();
    tds2_sensor.begin();


    // Initialize readings array
    for (int i = 0; i < numReadings; i++) {
        readings1[i] = 0;
        readings2[i] = 0;
    }
}

void loop() {

  long duration, inches, cm;
    pinMode(TRIGGER_PIN, OUTPUT);
    digitalWrite(TRIGGER_PIN, LOW);
    delayMicroseconds(2);
    digitalWrite(TRIGGER_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIGGER_PIN, LOW);
    pinMode(ECHO_PIN, INPUT);
    duration = pulseIn(ECHO_PIN, HIGH);

    inches = microsecondsToInches(duration);
    cm = microsecondsToCentimeters(duration);
    distance = inches;

  if (distance < 3.00) {
    digitalWrite(relayPump1, HIGH);
    digitalWrite(relayPump2, HIGH);
    digitalWrite(relayValve, HIGH);
} else if (distance >= 7.00) {
    digitalWrite(relayPump1, LOW);
    digitalWrite(relayPump2, LOW);
    digitalWrite(relayValve, LOW);
}else{
  digitalWrite(relayPump1, LOW);
    digitalWrite(relayPump2, LOW);
    digitalWrite(relayValve, LOW);
}

    // Read temperatures for compensation
    sensors1.requestTemperatures();
    temp1 = sensors1.getTempCByIndex(0);
    sensors2.requestTemperatures();
    temp2 = sensors2.getTempCByIndex(0);

    // Set temperature for TDS sensors
    tds1_sensor.setTemperature(temp1);
    tds2_sensor.setTemperature(temp2);

    // Update TDS readings
    tds1_sensor.update();
    tds2_sensor.update();
    TDS1_value = tds1_sensor.getTdsValue();
    TDS2_value = tds2_sensor.getTdsValue();

    // Read sensors with temperature compensation
    pH1 = readCalibratedPH1(phPin1, temp1);
    pH2 = readCalibratedPH2(phPin2, temp2);
    ec1 = readCalibratedEC1(ecPin1, temp1);
    ec2 = readCalibratedEC2(ecPin2, temp2);

    // Calculate turbidity1 with smoothing
    total1 -= readings1[index1];
    readings1[index1] = analogRead(turbidityPin1);
    total1 += readings1[index1];
    index1 = (index1 + 1) % numReadings;
    average1 = total1 / numReadings;

    filteredValue1 = (alpha * (average1 * (5.0 / 1024.0))) + ((1 - alpha) * filteredValue1);
    turbidity1 = (3.498 - filteredValue1) / 0.0017;

    // Calculate turbidity2 with smoothing
    total2 -= readings2[index2];
    readings2[index2] = analogRead(turbidityPin2);
    total2 += readings2[index2];
    index2 = (index2 + 1) % numReadings;
    average2 = total2 / numReadings;

    filteredValue2 = (alpha * (average2 * (5.0 / 1024.0))) + ((1 - alpha) * filteredValue2);
    turbidity2 = (3.498 - filteredValue2) / 0.0017;
    
    
    // Print raw values to Serial
    Serial.print("pH1: "); Serial.println(pH1);
    Serial.print("pH2: "); Serial.println(pH2);
    Serial.print("EC1: "); Serial.println(ec1);
    Serial.print("EC2: "); Serial.println(ec2);
    Serial.print("Temp1: "); Serial.println(temp1);
    Serial.print("Temp2: "); Serial.println(temp2);
    Serial.print("TDS1: "); Serial.println(TDS1_value);
    Serial.print("TDS2: "); Serial.println(TDS2_value);
    Serial.print("Turbidity1: "); Serial.println(turbidity1 < 0 ? 0 : turbidity1);
    Serial.print("Turbidity2: "); Serial.println(turbidity2 < 0 ? 0 : turbidity2);
    Serial.print("Distance: "); Serial.println(distance);

// Print raw values to Serial (sending to ESP8266)
    String dataToSend = String(pH1) + "," + String(pH2) + "," + String(ec1) + "," + String(ec2) + "," +
                        String(temp1) + "," + String(temp2) + "," + String(TDS1_value) + "," +
                        String(TDS2_value) + "," + String(turbidity1) + "," + String(turbidity2) + "," +
                        String(distance);
    Serial1.println(dataToSend);  // Send the data to ESP8266


    delay(1000); // 1-second delay
}


float readCalibratedPH1(int pin, float temp) {
sensors1.requestTemperatures();     // Request temperature from DS18B20
  float temp1 = sensors1.getTempCByIndex(0);
 int sensorValue = analogRead(pin);
    double voltage = sensorValue * (5.0 / 1024.0); // Analog-to-Digital Conversion

    // pH calculation logic for sensor 2
    float pH1_step_4_to_6 = (pH_voltage_6_86 - pH_voltage_4_01) / (pH_6_86 - pH_4_01);
    float pH1_step_6_to_9 = (pH_voltage_9_18 - pH_voltage_6_86) / (pH_9_18 - pH_6_86);

    float pH = 0.0;

    if (voltage > voltage_6_86) {
    // For voltages between pH 4.01 and pH 6.86
    pH = pH_4_01 + ((voltage - pH_voltage_4_01) / pH1_step_4_to_6);
  } else {
    // For voltages between pH 6.86 and pH 9.18
    pH = pH_6_86 + ((voltage - pH_voltage_6_86) / pH1_step_6_to_9);
  }
    pH += tempCoefficient * (temp1 - 25.0);

    return pH;
}


float readCalibratedPH2(int pin, float temp) {
  sensors2.requestTemperatures();     // Request temperature from DS18B20
  float temp2 = sensors2.getTempCByIndex(0);
 int sensorValue = analogRead(pin);
    double voltage = sensorValue * (5.0 / 1024.0); // Analog-to-Digital Conversion

    // pH calculation logic for sensor 2
    float pH_step_4_to_6 = (voltage_6_86 - voltage_4_01) / (pH_6_86 - pH_4_01);
    float pH_step_6_to_9 = (voltage_9_18 - voltage_6_86) / (pH_9_18 - pH_6_86);

    float pH = 0.0;

    if (voltage > voltage_6_86) {
    // For voltages between pH 4.01 and pH 6.86
    pH = pH_4_01 + ((voltage - voltage_4_01) / pH_step_4_to_6);
  } else {
    // For voltages between pH 6.86 and pH 9.18
    pH = pH_6_86 + ((voltage - voltage_6_86) / pH_step_6_to_9);
  }
    pH += tempCoefficient * (temp2 - 25.0);

    return pH;

}

float readCalibratedEC1(int pin, float temp) {
    static unsigned long timepoint = millis(); // Store the current time

    // Check if 1 second has passed
    if (millis() - timepoint > 1000U) { 
        timepoint = millis();

        // Read temperature from DS18B20
        sensors1.requestTemperatures(); // Request temperature readings
        float temperature = sensors1.getTempCByIndex(0); // Get temperature in Celsius

        // Read EC sensor voltage
        voltage = analogRead(pin) / 1024.0 * 5000; // Convert ADC value to voltage (mV)

        // Convert voltage to EC with temperature compensation
        ecValue = ec1_sensor.readEC(voltage, temperature);
        
        // Calibration process if needed (remove if not applicable)
        // ec1_sensor.calibration(voltage, temperature);
    }

    return ecValue; // Return the EC value
}

float readCalibratedEC2(int pin, float temp) {
    static unsigned long timepoint = millis(); // Store the current time

    // Check if 1 second has passed
    if (millis() - timepoint > 1000U) { 
        timepoint = millis();

        // Read temperature from DS18B20
        sensors2.requestTemperatures(); // Request temperature readings
        float temperature = sensors2.getTempCByIndex(0); // Get temperature in Celsius

        // Read EC sensor voltage
        voltage = analogRead(pin) / 1024.0 * 5000; // Convert ADC value to voltage (mV)

        // Convert voltage to EC with temperature compensation
        ecValue = ec2_sensor.readEC(voltage, temperature);
        
        // Calibration process if needed (remove if not applicable)
        // ec2_sensor.calibration(voltage, temperature);
    }

    return ecValue; // Return the EC value
}

long microsecondsToInches(long microseconds){
  return (microseconds / 74) / 2;
}

long microsecondsToCentimeters(long microseconds){
  return (microseconds / 29) / 2;
}

`

Why do you have a SoftwareSerial on pins 18 and 19? That might interfere with Serial1.

The Tx and Rx LEDs on the Mega only react on serial, not on Serial1/2/3.

There is no need to build up 1 large String object just to send it over Serial1. You are making your Mega do a lot of extra work for zero benefit (in fact, you may be fragmenting the memory which is harming it).
Much, much better to just have a series of Serial1.print() statements for all those variables. Faster, less memory used.

1 Like

Hi @capstone_g2024

welcome to the arduino-forum.

Well done to post your code as a code-section in your frist posting
As you can see in this pinout

The Arduino Mega 2560 has three different independant working hardware-serial interfaces.

On the Arduino Mega 2560 the IO-pins 18 and 19 are connected to the hardware-serial

"Serial1"

Of you put a software-serial on the IO-pins 18 and 19

SoftwareSerial espSerial(19, 18); // RX, TX

You mix up the hardware-serial with software-serial.
you should remove this line of code

SoftwareSerial espSerial(19, 18); // RX, TX

As you are already using Serial1

    Serial1.begin(9600);

instead of creating a big string send the data by multiple Serial.print()

Serial1.print(pH1);
Serial1.print(pH2);
Serial1.print(",");

Serial1.print(ec1);
Serial1.print(",");

Serial1.print(ec2)
Serial1.print(",");

Serial1.print(temp1)
Serial.print(",");

Serial1.print(temp2)
Serial1.print(",");
 
Serial1.print(TDS1_value)
Serial1.print(",");

Serial1.print(TDS2_value)
Serial1.print(",");

Serial1.print(turbidity1); 
Serial1.print(",");

Serial1.print(turbidity2); 
Serial1.print(",");

Serial1.println(distance);
1 Like

then what would be my approach to my esp8266 code, this is the recent code i have:

#define BLYNK_TEMPLATE_ID "sample"
#define BLYNK_TEMPLATE_NAME " name"
#define BLYNK_AUTH_TOKEN "sample"

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = BLYNK_AUTH_TOKEN; // Your Blynk authentication token
char ssid[] = "username"; // Your WiFi SSID
char pass[] = "pass"; // Your WiFi password

void setup() {
    Serial.begin(9600); // Start the serial communication
    Blynk.begin(auth, ssid, pass); // Connect to Blynk
}

void loop() {
    // Process Blynk
    Blynk.run();

    // Check for incoming serial data from the Arduino Mega
    if (Serial.available()) {
        String receivedData = Serial.readStringUntil('\n'); // Read incoming data
        Serial.println("Received: " + receivedData); // Print received data for debugging

        // Split the received data into components
        int commaIndex = 0;
        float pH1, pH2, ec1, ec2, temp1, temp2, TDS1_value, TDS2_value, turbidity1, turbidity2, distance;

        // Use String methods to parse the received data
        pH1 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        pH2 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        ec1 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        ec2 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        temp1 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        temp2 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        TDS1_value = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        TDS2_value = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        turbidity1 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        turbidity2 = receivedData.substring(commaIndex, (commaIndex = receivedData.indexOf(',', commaIndex + 1))).toFloat();
        distance = receivedData.substring(commaIndex).toFloat();

        // Send data to Blynk
        Blynk.virtualWrite(V0, pH1); // Assuming you have V0 for pH1 in Blynk
        Blynk.virtualWrite(V1, pH2); // V1 for pH2
        Blynk.virtualWrite(V2, ec1);  // V2 for EC1
        Blynk.virtualWrite(V3, ec2);  // V3 for EC2
        Blynk.virtualWrite(V4, temp1); // V4 for Temp1
        Blynk.virtualWrite(V5, temp2); // V5 for Temp2
        Blynk.virtualWrite(V6, TDS1_value); // V6 for TDS1
        Blynk.virtualWrite(V7, TDS2_value); // V7 for TDS2
        Blynk.virtualWrite(V8, turbidity1); // V8 for Turbidity1
        Blynk.virtualWrite(V9, turbidity2); // V9 for Turbidity2
        Blynk.virtualWrite(V10, distance); // V10 for Distance
    }
}

Did you see correct data on the esp8266 with the previous sketch you were using on the Mega after you converted from software serial to Serial1?

If you did, then the
Serial1.println(distance);
should terminate the transmission with the same '\n' as before and the
Serial.readStringUntil('\n'); should work as before.

If you did not receive the correct data previously, then you have a different issue.

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