ESP8266 + NodeMCU: sending AT commands over serial or TCP (Arduino or NodeMCU)

Commanding the GSM module connected to RX2/TX2

Requirements: have the hardware setup described in previous tutorial

Method 1: over serial

A problem with ESP is that it has only one UART for communicating with a GSM module, and this UART is also used by USB connection.

This presents us a challenge for testing the connected GSM module because ideally we would want one UART connected to the GSM for sending AT commands and receiving the responses, and another UART for the USB/serial interface for connecting a terminal/serial-monitor to send AT commands and getting debug messages to actually see the responses of the AT commands.

That would require the use of two UARTs simultaneously.

With the previous hardware setup I presented, we can use UART0 to send AT commands and control the GSM module (with an API call to switch the pins to GPIO13/GPIO15).

The AT commands that will be sent must be hard-coded in our code and are sent using a timer because we need to wait for the response of the previous command before sending a new one.

We use the transmit-only UART1 to send the output of UART0 (the responses of the AT commands) to our terminal/serial-monitor connected to our computer through the USB<->serial converter.

Seems trickie, but it works.

In order to do that for NodeMCU, we replace the print() function with a custom one so it prints to UART1 instead of UART0. Here is the LUA code to upload to Wemos:

NodeMCU firmware - init.lua:

tmr.alarm(0, 1000, tmr.ALARM_SINGLE, function()
	Setup()
end)

--replace print() so it writes to UART1
function print(...)
	for i,v in ipairs(arg) do
		uart.write(1, tostring(v).." ")
	end
	uart.write(1, "\n")
end


local tm_sender
local atcommands
local icommand = 1

function Setup()
    --print something to UART1 -> check if you receive it on you serial-monitor
    print("Hello there!")
    print("Hello there!")
    print("Hello there!")

    --send any data received from UART0 to UART1
    uart.on("data", "\n", function(d)
        print(d, "\n")
    end, 0)
    
    --swap UART0 to GPIO13/GPIO15
    uart.alt(1)

    --list of AT commands to send
    atcommands =
    {
        "AT",
        "AT+CPIN?",
        "AT+CREG?",
        "AT+CSQ",
        "ATD996543493;"-- call this number
    }

    --start timer to send them
    tm_sender = tmr.create()
    tm_sender:register(1000, tmr.ALARM_AUTO, SendATCommand)
    tm_sender:start()
end

function SendATCommand()
    local cmd = atcommands[icommand]
    print("Sending AT commands:"..cmd)

    --send AT command not forgeting the \r\n newline sequence
    uart.write(0, cmd.."\r\n")

    if(icommand == #atcommands) then
        tm_sender:stop()
    else
        icommand = icommand + 1
    end
end

Now for Arduino, the process is almost same. We can't replace functions in C++ as in LUA. What we can do is to declare a custom printDebug() function, and use it instead of the standard print() function.

Arduino firmware:

#include <Ticker.h>

bool atmode = true;
String atcommand = "";
String atresponse = "";
Ticker timer;

void setup() 
{
	Serial.begin(115200);
	inputString.reserve(200);
}

void loop()
{
	if(Serial.available())
	{
		char inChar = (char)Serial.read();
		if(atmode)
		{
			atcommand += inChar;
			if(inChar == '\n')
			{
				Serial.write("SENDING COMMAND: ");
				Serial.write(atcommand);

				Serial.switch();
				Serial.write(atcommand);
				timer.attach(1, switchBack);
			}
		} else {
			atresponse += inChar;
		}
	}
}

void switchBack()
{
	Serial.switch();
	Serial.write("RETURN FROM A6: ");
	Serial.write(atresponse);
	
	atcommand = "";
	atresponse = "";
	atmode = true;
}

Then use any serial monitor for sending commands to the Wemos connected to your USB / COM port. I am using ESPlorer.

When I send an AT commands, after 1 second, the OK is printed to my console:

A limitation of this solution is that it only listens for the GSM module for 1 second, so you won't see the entire output of AT commands that take more than 1 second to execute.

Method 2: over TCP

A much better solution exists over Method 1. Essentially it is do all the communication to the GSM module wirelessly over TCP.

With this method you don't even need to connect the ESP to you computer, that is, less wires.

TBD