В предыдущей статье я подробно рассмотрел относительно дорогую (цвета морской волны 🙂 ) плату модуля 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)); }
При запуске кода имеем следующее.
