В предыдущей статье я подробно рассмотрел относительно дорогую (цвета морской волны 🙂 ) плату модуля SIM800C и его подключение к ESP32/ESP8266. Схемотехника платы SIM800C мне не понравилась. На мой взгляд нет смысла переплачивать за этот модуль, лучше взять недорогой «красный» модуль SIM800C/L и немного его усовершествовать, добавив в схемотехнику:
- Резистивный делитель на вход RX модуля для согласования уровня. Расчет делителя в предыдущей статье.
- DC-DC step down converter. В схеме использовался недорогой модуль Mini-360 за 0,3 $.
- Несколько емкостей для фильтрации пульсаций DC-DC step down converter-а.
По крайней мере этот модуль без проблем встает в монтажную плату, поскольку расстояние между разъемами «гребенки» кратно 2,54 мм. Нюансы работы с SIM800 подробно описаны в предыдущей статье.
Схема подключения SIM800L к ESP32
Поскольку модуль SIM800L у меня используется в дорогом оборудовании, которое должно работать гарантированно, я добавил емкостей в соответствии с рекомендациями datasheet.

Танталовый конденсатор на модуле распаян. Я добавил электролитический конденсатор на 2200 мкФ и остальные емкости по datasheet.
Микроконтроллер ESP32 в данном примере запитывался от USB порта ноутбука.
Поскольку один UART порт используется для передачи данных, а второй для приема, вместо преобразователя уровней можно использовать резистивный делитель. Но с таким способом связан один риск. Если все распаять правильно, но при этом программно, при задании номеров пинов для RX и TX, можно их перепутать и сжечь TXD порт чипа SIM800. Поэтому в случае такой экономии нужно очень внимательно писать код. 🙂
Если делать конвертацию уровней по-серьезному, то тогда нужно использовать плату преобразователя уровней, подав со стороны микроконтроллера опорное напряжение 3,3V, а со стороны SIM800L опорное напряжение снятое с простой цепочки резистор и стабилитрон. Её расчет здесь. Стабилитроны бывают на 2,7 V и 3 V.
В datasheet модуля указан максимальный уровень логической единицы на входе RX — 3,1 В (при минимальном 2,1 В). Соотвественно, 2,7 V будет достаточно, а 3 V уже рискованно. Если посмотреть в datasheet напряжение для выхода опорного напряжения SIM800L

Как раз минимальное значение 2,7 V. Сразу говорю — я эту схему пока не пробовал, ограничился простым вариантом с резистивным делителем.

Mini-360 DC-DC конвертер — не самый лучший вариант. Он нормально выдерживает нагрузку, SIM800L грузится с ним стабильно, однако качество переменного резистора весьма посредственное. При вибрации в производственном помещении, где будет размещаться оборудование, выходное напряжение может «уходить» от установленного значения. Поэтому этот DC-DC конвертер заменю на что-то более качественное.
Однако, модуль крошечный, поэтому легко разместился вместе с емкостями (за исключением электролитического) и резисторами под модулем SIM800L. GSM модуль обычно монтирую на гнездах.

В качестве блока питания использовался 12 V блок питания на 3A. За цену в 4 USD — просто волшебное качество. Брал здесь.
Сразу отмечу, что мощная 4-х портовая USB зарядка AUKEY 5V, по 2.4 A на каждый USB порт, подключенная к блоку питания для breadboard-а, нагрузку не потянула. При загрузке модуля идет пиковое потреблении мощности и напряжение на GSM модуле просело до 3 V. Модуль даже не стартанул толком. Возможно, проблема в БП для breadboard-а. Он даже без нагрузки выдавал меньше 5 V.
Код для работы с SIM800L на ESP32
Код тестировался на 38-ми пиновой плате MH-ET Live ESP32 Devkit 38 pins. Это кусок кода в проекте находится в виде *.cpp файла, поэтому просто переименуйте функцию Init_GSM_SIM800L() в setup() и добавьте функцию loop().
#include "GSM_SIM800L.h"
/*
* There are three serial ports on the ESP known as U0UXD, U1UXD and U2UXD.
*
* U0UXD is used to communicate with the ESP32 for programming and during reset/boot.
* U1UXD is unused and can be used for your projects. Some boards use this port for SPI Flash access though
* U2UXD is unused and can be used for your projects.
*
*/
#define TINY_GSM_MODEM_SIM800
#define DEBUG //enable debug mode
#include <TinyGsmClient.h>
#define RXD2 16
#define TXD2 17
#define Max_Modem_Reboots 5
#define APN_NAME "internet.beeline.ru"
#define APN_USER "beeline"
#define APN_PSWD "beeline"
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 38400
// set your cad pin (optional)
#define SIM_PIN ""
// define your board pin here
#define LED_PIN 27
TinyGsm modemGSM(Serial2);
int Modem_Reboots_Counter = 0;
//Command must be without AT prefix
/*String sendAT(String command)
{
modemGSM.sendAT(GF(command));
if (modemGSM.waitResponse(GF(GSM_NL)) != 1) {
return "Empty";
}
String res = modemGSM.stream.readStringUntil('\n');
modemGSM.waitResponse();
return res;
}*/
//Command must be without AT prefix
String sendAT(String command)
{
String response = "";
Serial2.println("AT" + command);
while(!Serial2.available());
response = Serial2.readString();
return response;
}
String printAT(String command, String message = "")
{
String res = "";
if (message != "")
{
Serial.println(message);
}
if (command != "")
{
Serial.println("AT" + command);
res = sendAT(command);
Serial.println(res);
}
return res;
}
void RestartGSMModem()
{
Serial.println("Restarting GSM...");
if (!modemGSM.restart())
{
Serial.println("\tFailed. :-(\r\n");
//ESP.restart();
}
if (Modem_Reboots_Counter < Max_Modem_Reboots)
{
Init_GSM_SIM800L();
}
Modem_Reboots_Counter++;
}
String GSMSignalLevel(int level)
{
switch (level)
{
case 0:
return "-115 dBm or less";
case 1:
return "-111 dBm";
case 31:
return "-52 dBm or greater";
case 99:
return "not known or not detectable";
default:
if (level > 1 && level < 31)
return "-110... -54 dBm";
}
return "Unknown";
}
String GSMRegistrationStatus(RegStatus state)
{
switch (state)
{
case REG_UNREGISTERED:
return "Not registered, MT is not currently searching a new operator to register to";
case REG_SEARCHING:
return "Not registered, but MT is currently searching a new operator to register to";
case REG_DENIED:
return "Registration denied";
case REG_OK_HOME:
return "Registered, home network";
case REG_OK_ROAMING:
return "Registered, roaming";
case REG_UNKNOWN:
return "Unknown";
}
return "Unknown";
}
String SwapLocation(String location)
{
int i = location.indexOf(',');
int j = location.indexOf(',', i+1);
String longitude = location.substring(i+1, j);
i = location.indexOf(',', j+1);
String latitude = location.substring(j+1, i);
return latitude + "," + longitude;
}
void Init_GSM_SIM800L() {
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
Serial.println("Serial GSM Txd is on pin: "+String(TXD2));
Serial.println("Serial GSM Rxd is on pin: "+String(RXD2));
//pinMode(LED_PIN, OUTPUT);
delay(3000);
TinyGsmAutoBaud(Serial2, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
String info = modemGSM.getModemInfo();
Serial.println(info);
if (!modemGSM.restart())
{
RestartGSMModem();
}
else
{
Serial.println("Modem restart OK");
}
//printAT("+CMEE=2", "Enable +CME ERROR: <err> result code and use verbose <err> values.");
//printAT("+COPS=?", "Show list of available operators")
if (modemGSM.getSimStatus() != 3) //printAT("AT+CPIN?", "Check PIN code status").startsWith("+CME ERROR:"))
{
Serial.println("Check PIN code for the SIM.");
if (SIM_PIN != "")
{
Serial.println("Try to unlock SIM PIN.");
modemGSM.simUnlock(SIM_PIN);
delay(3000);
if (modemGSM.getSimStatus() != 3)
{
RestartGSMModem();
}
}
}
if (!modemGSM.waitForNetwork())
{
Serial.println("Failed to connect to network");
RestartGSMModem();
}
else
{
RegStatus registration = modemGSM.getRegistrationStatus();
Serial.println("Registration: [" + GSMRegistrationStatus(registration) + "]");
Serial.println("Modem network OK");
}
Serial.println(modemGSM.gprsConnect(APN_NAME,APN_USER,APN_PSWD) ? "GPRS Connect OK" : "GPRS Connection failed");
bool stateGPRS = modemGSM.isGprsConnected();
if (!stateGPRS)
{
RestartGSMModem();
}
String state = stateGPRS ? "connected" : "not connected";
Serial.println("GPRS status: " + state);
Serial.println("CCID: " + modemGSM.getSimCCID());
Serial.println("IMEI: " + modemGSM.getIMEI());
Serial.println("Operator: " + modemGSM.getOperator());
IPAddress local = modemGSM.localIP();
Serial.println("Local IP: " + local.toString());
int csq = modemGSM.getSignalQuality();
if (csq == 0)
{
Serial.println("Signal quality is 0. Restart modem.");
RestartGSMModem();
}
Serial.println("Signal quality: " + GSMSignalLevel(csq) + " [" + String(csq) + "]");
int battLevel = modemGSM.getBattPercent();
Serial.println("Battery level: " + String(battLevel) + "%");
float battVoltage = modemGSM.getBattVoltage() / 1000.0F;
Serial.println("Battery voltage: " + String(battVoltage));
String gsmLoc = modemGSM.getGsmLocation();
Serial.println("GSM location: " + gsmLoc);
Serial.println("GSM location: " + SwapLocation(gsmLoc));
}При запуске кода имеем следующее.


