Подключение GSM модуля SIM800L к ESP8266/ESP32/Arduino

Модуль SIM800L

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

Подключение SIM800L к ESP32 Devkit 38 pin
Подключение SIM800L к ESP32 Devkit 38 pin
Mini 360 DC-DC step down converter
Mini 360 DC-DC step down converter

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

Однако, модуль крошечный, поэтому легко разместился вместе с емкостями (за исключением электролитического) и резисторами под модулем SIM800L. GSM модуль обычно монтирую на гнездах.

Блок питания 12V, 3A

В качестве блока питания использовался 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));
}

При запуске кода имеем следующее.

Spread the love
Запись опубликована в рубрике IT рецепты с метками , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *