0

I am facing issue in using 2 Serial communication device with Arduino uno. I am trying to use ESP8266, Neo 6M GPS module with Arduino UNO, but only one of device is working at a time. Is there any solution available to make this work? When I comment processGPS() and uncomment TCP related API and vice-versa then either of the device working. Any idea how we can make work both?

My code:

// This is a demo example using a public http server for testing both GET and POST requests

#include <Arduino.h>
#include <LiteESP8266Client.h>
#include "TinyGPS++.h"
#include "SoftwareSerial.h"

#define PACKET_MTU 500    // Standard network MTU is 500 bytes

LiteESP8266 radio;

const char ssid[] PROGMEM = "xyz";    //change it to your wifi SSID
const char password[] PROGMEM = "xyz";    //change it to your wifi password
const char host[] PROGMEM = "192.168.0.156";
const int port = 8080;

const char http_get_request[] PROGMEM = "GET /getLedStatus HTTP/1.1\r\n";
const char http_useragent[] PROGMEM = "User-Agent: Arduino-stm32/0.1\r\n";
const char http_content_type_json[] PROGMEM = "Content-Type: application/json\r\n";
const char http_host[] PROGMEM = "Host: 192.168.0.156\r\n";
const char http_close_connection[] PROGMEM = "Connection: close\r\n\r\n";
const char http_content_length_header[] PROGMEM = "Content-Length: ";
const char success[] PROGMEM = "success";
const char failed[] PROGMEM = "failed";
const char CRLF[] PROGMEM = "\r\n";
const char error_data_null[] PROGMEM = "Error: data came back null.";
const int ledPin=11;
// Choose two Arduino pins to use for software serial
int RXPin = 5;
int TXPin = 4;

int GPSBaud = 9600;

// Create a TinyGPS++ object
TinyGPSPlus gps;

// Create a software serial port called "gpsSerial"
SoftwareSerial gpsSerial(RXPin, TXPin);

void setupStationMode() {
  Serial.print(F("Setup station mode... "));
  if (radio.set_station_mode()) {
    Serial.println(F("success"));
  } else {
    Serial.println(F("failed"));
  }
}

void joinAP() {
  Serial.print(F("Join AP "));
  Serial.print(F("... "));
  if (radio.connect_to_ap(ssid, password)) {
    Serial.println(F("Success"));
  } else {
    Serial.println(F("Failed"));
  }
}

boolean establishTcpConnect() {
  Serial.print(F("Establish TCP Connection... "));
  if (radio.connect_progmem(host, port)) {
    Serial.println(F("Success"));
    return true;
  } else {
    Serial.println(F("Failed"));
    return false;
  }
}

void readHttpPacketAndProcessLEDStatus() {
  char *data;
  while ((data = radio.get_response_packet(PACKET_MTU, 5000))) {
    if (data) {
      Serial.println(F("Response Received..."));
      Serial.println(data);
      if(strstr(data, "ON") != NULL) {
        digitalWrite(ledPin, HIGH);
      }else{
        digitalWrite(ledPin, LOW);
      }
      free(data);//Mandatory
    } else {
      Serial.println(error_data_null);
    }
  }
}

void httpGetLedStatus() {
  Serial.println(F("Sending GET request... "));
  radio.send_progmem(http_get_request);
  radio.send_progmem(http_useragent);
  radio.send_progmem(http_host);
  radio.send_progmem(http_close_connection);
}
void setupGPS(){
  // Start the software serial port at the GPS's default baud
  gpsSerial.begin(GPSBaud);
  Serial.println("GPS Start");//Just show to the monitor that the sketch has started
}
void setup() {
  delay(2000);
  pinMode(ledPin, OUTPUT);
  radio.begin(9600,2,3);
  Serial.begin(9600);
  while (!Serial) {};
  //setupStationMode();
  //joinAP();
  setupGPS();
}
void displayInfo()
{
  if (gps.location.isValid())
  {
    Serial.print("Latitude: ");
    Serial.println(gps.location.lat(), 6);
    Serial.print("Longitude: ");
    Serial.println(gps.location.lng(), 6);
    Serial.print("Altitude: ");
    Serial.println(gps.altitude.meters());
    Serial.println("Speed MPH:");
    Serial.println(gps.speed.mph());
  }
  else
  {
    Serial.println("Location: Not Available");
  }
  
  Serial.print("Date: ");
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print("/");
    Serial.print(gps.date.day());
    Serial.print("/");
    Serial.println(gps.date.year());
  }
  else
  {
    Serial.println("Not Available");
  }

  Serial.print("Time: ");
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(":");
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(":");
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(".");
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.println(gps.time.centisecond());
  }
  else
  {
    Serial.println("Not Available");
  }

  Serial.println();
  Serial.println();
  delay(1000);
}
void processGps(){
   // This sketch displays information every time a new sentence is correctly encoded.
  if (gpsSerial.available() > 0)
    if (gps.encode(gpsSerial.read()))
      displayInfo();
}
void loop() {
  /*if(establishTcpConnect()){
    httpGetLedStatus();
    readHttpPacketAndProcessLEDStatus();
  }*/
  processGps();
  }
  • 1
    Both the ESP8266 and the GPS use SoftwareSerial. Using SoftwareSerial, only one port can receive data at a time. See here. For the Arduino Uno there's no simple solution. You will need different hardware that has more than one Hardware Serial port (like the Mega2560 if you want to stick to the AVRs). – StarCat Aug 10 at 16:32
  • 1
    Correction to my own comment: The ESP8266 doesn't actually use SoftwareSerial but the Arduino side communicating with the ESP8266 does. – StarCat Aug 10 at 16:56
  • Agreed with @StarCat. Why even bother with the Arduino UNO? If your ESP8266 has enough pins exposed it can run the code itself and talk directly to the GPS module with much less hassle. – romkey Aug 10 at 17:15
  • @romkey, True, hence my comment about sticking to AVRs. Running directly on the ESP8266 would be much preferable. Of course I don't know what needs to be connected in addition from the GPS (displays, other peripherals?). – StarCat Aug 10 at 17:27
1

As mentioned by StarCat and romkey, SoftwareSerial only allows one connection at a time.

There are two potential solutions to this in my opinion, but each requires some new hardware.

Solution 1 - Replace Arduino Uno with an STM32 Blue Pill

STM32 Blue Pill has more than one hardware serial interfaces, so that you don't even need the SoftwareSerial, in fact, the LiteESP8266Client.h will auto detect if a STM32 is used or an AVR-based Arduino is used to decide whether to use HardwareSerial or SoftwareSerial, see here.

Pros:

  • Minimum code change. You be able to use what you have written so far and continue to use ESP-01 as a WiFi-shield;

Cons:

  • A little bit extra works to setup STM32duino Core for Arduino and requires either a SWDI programmer or USB-serial programmer.

Read this for getting started with STM32 and the things need to be aware of.

Solution 2 - Replace both Arduino Uno and ESP-01 with an ESP8266 Dev Board

Instead of using an ESP-01 as a WiFi shield, get an ESP12-based development board as an Arduino to replace both the Arduino Uno and ESP-01. In this case, you run Arduino sketch directly on the board and replace the AT firmware with Arduino bootloader.

Pros:

  • Integrated Arduino Uno with ESP wireless functionality into one hardware.

Cons:

  • Need complete re-write of your application.

ESP8266 Arduino github should have sufficient information for getting started.

| improve this answer | |
  • why STM32? Arduino has ARM boards – Juraj Aug 11 at 5:01
  • Why not an ESP32? – StarCat Aug 11 at 5:48
  • @Juraj Personally I never used any SAMD boards so can't comment on that. – hcheung Aug 11 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.