GSM and LCD functions don't work together

I’m trying to create a system that allows me to water my plants and turn on the LED strips through SMS. I’m also displaying data from the sensors on an LCD. Both of these things work separately.

When I text “Water” to my GSM module (DFRobot Gravity UART A6 GSM Module) it turns on a pump for 10 seconds. The “Lights” command turns on the LED strip for 6 seconds. This part usually works well although sometimes I get CMS errors 500 or 518 and I’m not sure why. My problem is that when I try to display sensor data on the LCD (standard Hitachi HD44780 LCD controller) the GSM function stops responding to my commands. So I can either text my system and have it respond (and no sensor data is shown) or I can see the data but my texts don’t do anything. The output on the serial monitor indicates that the GSM module receives an SMS (I’ve attached a picture) but it doesn’t do anything with it. What it should do is display my text on the serial monitor before proceeding with the task.

I’m using an Arduino Mega 2560 and all of the components receive enough power.

I’ve pasted the relevant Arduino code below and attached it as a file. GSMResponse(incomingByte) takes the text and waters the plant/turns on LEDs while lcdText() displays values from my moisture sensor (SparkFun soil moisture sensor) and relative humidity and temperature sensor (DHT22). I would like lcdText() to continually update values when there’s no SMS. Right now the display gets stuck on “Done” if the SMS goes through.

#include "DHTesp.h"
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

// LCD
const int rst = 3, enable = 2, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rst, enable, d4, d5, d6, d7);

// GSM
int rxPin = 53;
int txPin = 51;
char incomingByte[150];   // array to compare incoming SMS
SoftwareSerial MySerial(rxPin, txPin);

// DHT
int DHT22Pin = 9;
DHTesp dht;

// Soil
int soilMoisture = 0;
float percentMoisture = 0.0;
int moistureSensorPin = A1;
int moistureSensorPower = 8;

// Motor
int motorPin = 44;

// LED
int ledPin = 47;

/*----------Moisture Sensor functions----------*/
int readSoilMoisture()
{
  delay(100);
  soilMoisture = analogRead(moistureSensorPin);
  return soilMoisture;
}

void waterPlant()
{
  digitalWrite(motorPin, HIGH);
  delay(10000);
  digitalWrite(motorPin, LOW);
}

float convertMoistureValue(int moistureVal)
{
  float percentOutput = 0.0;
  float temp = moistureVal - 870;

  if (temp < 0)
  {
    percentOutput = (temp / 870) * 100;
  }
  if (temp == 0)
  {
    percentOutput = 0.0;
  }
  if (temp > 0)
  {
    percentOutput = (temp / 154) * 100;
  }
  
  return percentOutput;
}

/*----------RHTemp sensor functions----------*/
float readTemp()
{
  float temperature = dht.getTemperature();
  return temperature;
}

float readHumid()
{
  float humidity = dht.getHumidity();
  return humidity;
}

/*----------GSM functions----------*/
void GSMInitialization()
{
  MySerial.begin(9600);
  MySerial.println("AT");
  updateSerial();
  delay(1000);
  MySerial.println("AT+CMGF=1");
  updateSerial();
  MySerial.println("AT+CMGD=1,4");
  delay(700); // Serial monitor dislays ERROR without a delay
  updateSerial();
  MySerial.println("AT+CNMI=1,2,0,0,0");
  updateSerial();
  sendSMS("Hello!");
  delay(1000);
}

void updateSerial()
{
  delay(2000);
  while (Serial.available()) {
    MySerial.write(Serial.read());
  }
  while (MySerial.available()) {
    Serial.write(MySerial.read());
  }
}

// Send text message
void sendSMS(String msg)
{
  MySerial.println("AT+CMGS=\"+XXXXXXXXXXX\""); // Phone number here
  updateSerial();
  MySerial.println(msg);
  updateSerial();
  MySerial.write(26);
}

// Clear incoming byte
void clearIncomingByte(char byteArray[])
{
  for (int y = 0; y < 100; y++)
  {
    byteArray[y] = 0;
  }
}

void GSMResponse(char byteArray[])
{
  clearIncomingByte(byteArray);
  if (MySerial.available())
  {
    int n_char = MySerial.available();
    for (int x = 0; x < n_char; x++)
    {
      byteArray[x] = MySerial.read();
    }

    String C = byteArray;
    Serial.print("  ");
    Serial.println(C);
    Serial.print("  ");

    if (strstr(byteArray, "Water"))
    {
      delay(1000);
      waterPlant();
      sendSMS("Watering plant");
      lcd.clear();
      lcd.print("Watering plant..");
      MySerial.println("AT+CMGD=1,4"); // Not sure if this is needed
      updateSerial();
      delay(10000);
      lcd.clear();
      lcd.print("Done");
      delay(2000);
    }

    if (strstr(byteArray, "Lights"))
    {
      delay(1000);
      lcd.clear();
      lcd.print("Activating LEDs");
      digitalWrite(ledPin, HIGH);
      sendSMS("Activating LEDs");
      MySerial.println("AT+CMGD=1,4"); // // Not sure if this is needed
      updateSerial();
      delay(6000);
      digitalWrite(ledPin, LOW);
      lcd.clear();
      lcd.print("Done");
      delay(2000);
    }
  }
}

/*----------LCD functions----------*/
void lcdText()
{
  // Display moisture percentage
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Moisture: ");
  percentMoisture = convertMoistureValue(readSoilMoisture());
  lcd.print(percentMoisture, 1);
  lcd.print("%");
  delay(3000);

  // Display temperature
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature: ");
  lcd.setCursor(0, 1);
  lcd.print(readTemp(), 1);
  lcd.print((char)223);
  lcd.print(" Celsius");
  delay(3000);

  // Display humidity
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity: ");
  lcd.print(readHumid(), 1);
  lcd.print("%");
  delay(3000);
}

void setup()
{
  lcd.begin(16, 2);

  Serial.begin(9600);

  GSMInitialization();

  // Initialize moisture sensor and motor
  pinMode(moistureSensorPower, OUTPUT);
  digitalWrite(moistureSensorPower, HIGH);
  pinMode(motorPin, OUTPUT);
  digitalWrite(motorPin, LOW);

  // Initialize RH and Temperature sensor
  dht.setup(DHT22Pin, DHTesp::DHT22);

  // Initialize LED pin
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  GSMResponse(incomingByte);
  lcdText();
}

TestCode2.ino (4.61 KB)

TestCode.ino (3.54 KB)

Is that the complete code? I don't see the declaration of MySerial anywhere.

I declared MySerial like this:

SoftwareSerial MySerial(rxPin, txPin);

This code only shows the LCD and GSM functions. I’ve attached everything else here.

#include "DHTesp.h"
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

// LCD
const int rst = 3, enable = 2, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rst, enable, d4, d5, d6, d7);

// GSM
int rxPin = 53;
int txPin = 51;
char incomingByte[150];   // array to compare incoming SMS
SoftwareSerial MySerial(rxPin, txPin);

// DHT
int DHT22Pin = 9;
DHTesp dht;

// Soil
int soilMoisture = 0;
float percentMoisture = 0.0;
int moistureSensorPin = A1;
int moistureSensorPower = 8;

// Motor
int motorPin = 44;

// LED
int ledPin = 47;

/*----------Moisture Sensor functions----------*/
int readSoilMoisture()
{
  delay(100);
  soilMoisture = analogRead(moistureSensorPin);
  return soilMoisture;
}

void waterPlant()
{
  digitalWrite(motorPin, HIGH);
  delay(10000);
  digitalWrite(motorPin, LOW);
}

float convertMoistureValue(int moistureVal)
{
  float percentOutput = 0.0;
  float temp = moistureVal - 870;

  if (temp < 0)
  {
    percentOutput = (temp / 870) * 100;
  }
  if (temp == 0)
  {
    percentOutput = 0.0;
  }
  if (temp > 0)
  {
    percentOutput = (temp / 154) * 100;
  }
  
  return percentOutput;
}

/*----------RHTemp sensor functions----------*/
float readTemp()
{
  float temperature = dht.getTemperature();
  return temperature;
}

float readHumid()
{
  float humidity = dht.getHumidity();
  return humidity;
}

/*----------GSM functions----------*/
void GSMInitialization()
{
  MySerial.begin(9600);
  MySerial.println("AT");
  updateSerial();
  delay(1000);
  MySerial.println("AT+CMGF=1");
  updateSerial();
  MySerial.println("AT+CMGD=1,4");
  delay(700); // Serial monitor dislays ERROR without a delay
  updateSerial();
  MySerial.println("AT+CNMI=1,2,0,0,0");
  updateSerial();
  sendSMS("Hello!");
  delay(1000);
}

void updateSerial()
{
  delay(2000);
  while (Serial.available()) {
    MySerial.write(Serial.read());
  }
  while (MySerial.available()) {
    Serial.write(MySerial.read());
  }
}

// Send text message
void sendSMS(String msg)
{
  MySerial.println("AT+CMGS=\"+XXXXXXXXXXX\""); // Phone number here
  updateSerial();
  MySerial.println(msg);
  updateSerial();
  MySerial.write(26);
}

// Clear incoming byte
void clearIncomingByte(char byteArray[])
{
  for (int y = 0; y < 100; y++)
  {
    byteArray[y] = 0;
  }
}

void GSMResponse(char byteArray[])
{
  clearIncomingByte(byteArray);
  if (MySerial.available())
  {
    int n_char = MySerial.available();
    for (int x = 0; x < n_char; x++)
    {
      byteArray[x] = MySerial.read();
    }

    String C = byteArray;
    Serial.print("  ");
    Serial.println(C);
    Serial.print("  ");

    if (strstr(byteArray, "Water"))
    {
      delay(1000);
      waterPlant();
      sendSMS("Watering plant");
      lcd.clear();
      lcd.print("Watering plant..");
      MySerial.println("AT+CMGD=1,4"); // Not sure if this is needed
      updateSerial();
      delay(10000);
      lcd.clear();
      lcd.print("Done");
      delay(2000);
    }

    if (strstr(byteArray, "Lights"))
    {
      delay(1000);
      lcd.clear();
      lcd.print("Activating LEDs");
      digitalWrite(ledPin, HIGH);
      sendSMS("Activating LEDs");
      MySerial.println("AT+CMGD=1,4"); // // Not sure if this is needed
      updateSerial();
      delay(6000);
      digitalWrite(ledPin, LOW);
      lcd.clear();
      lcd.print("Done");
      delay(2000);
    }
  }
}

/*----------LCD functions----------*/
void lcdText()
{
  // Display moisture percentage
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Moisture: ");
  percentMoisture = convertMoistureValue(readSoilMoisture());
  lcd.print(percentMoisture, 1);
  lcd.print("%");
  delay(3000);

  // Display temperature
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature: ");
  lcd.setCursor(0, 1);
  lcd.print(readTemp(), 1);
  lcd.print((char)223);
  lcd.print(" Celsius");
  delay(3000);

  // Display humidity
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity: ");
  lcd.print(readHumid(), 1);
  lcd.print("%");
  delay(3000);
}

void setup()
{
  lcd.begin(16, 2);

  Serial.begin(9600);

  GSMInitialization();

  // Initialize moisture sensor and motor
  pinMode(moistureSensorPower, OUTPUT);
  digitalWrite(moistureSensorPower, HIGH);
  pinMode(motorPin, OUTPUT);
  digitalWrite(motorPin, LOW);

  // Initialize RH and Temperature sensor
  dht.setup(DHT22Pin, DHTesp::DHT22);

  // Initialize LED pin
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  GSMResponse(incomingByte);
  lcdText();
}

TestCode2.ino (4.61 KB)

Why are you using SoftwareSerial on a Mega? You have 4 hardware serial ports, and are only using 1 of them.

PaulS:
Why are you using SoftwareSerial on a Mega? You have 4 hardware serial ports, and are only using 1 of them.

I'm using the code shown in the datasheet

// LCD
const int rst = 3, enable = 2, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rst, enable, d4, d5, d6, d7);
// Motor
int motorPin = 7;

// LED
int ledPin = 6;

I changed the motor and LED pin to 44 and 47 but I forgot to post that here. Sorry about that. The problem still stands

39071c:
I'm using the code shown in the datasheet

Then why aren't you using the hardware in the datasheet. If you think you are smart enough to change hardware, prove it.