ESP32 SIM800L: публикация данных в облако без Wi-Fi (TTGO T-Call)
Этот проект показывает, как подключить плату TTGO T-Call ESP32 SIM800L к интернету с помощью тарифного плана SIM-карты и публиковать данные в облако без использования Wi-Fi. Мы будем программировать эту плату в Arduino IDE.
Знакомство с TTGO T-Call ESP32 SIM800L
TTGO T-Call — это новая плата разработки на базе ESP32, которая включает в себя модуль GSM/GPRS SIM800L. Её можно приобрести примерно за $11.
Помимо Wi-Fi и Bluetooth, с этой платой ESP32 можно связываться по SMS или телефонным звонкам, а также подключать её к интернету через тарифный план SIM-карты. Это отлично подходит для IoT-проектов, которые не имеют доступа к ближайшему роутеру.
Важно: SIM800L работает в сетях 2G, поэтому он будет работать только в вашей стране, если доступны сети 2G. Проверьте наличие сети 2G в вашей стране, иначе он не будет работать.
Для использования возможностей этой платы вам понадобится nano SIM-карта с тарифным планом и кабель USB-C для загрузки кода на плату.
В комплект входят штыревые разъёмы, коннектор для батареи и внешняя антенна, которую следует подключить к плате.
Однако у нас возникли некоторые проблемы с этой антенной, поэтому мы решили перейти на другой тип антенны, и все проблемы были решены. На следующем рисунке показана новая антенна.
Обзор проекта
Идея этого проекта — публиковать данные датчиков из любого места в любой облачный сервис по вашему выбору. ESP32 не нужен доступ к роутеру через Wi-Fi, потому что мы будем подключаться к интернету через тарифный план SIM-карты.
В предыдущем проекте мы создали собственный серверный домен с базой данных для отображения показаний датчиков в графиках, к которым вы можете получить доступ из любой точки мира.
В этом проекте мы будем публиковать показания датчиков на этот сервер. Вы можете публиковать свои показания датчиков в любой другой сервис, например ThingSpeak, IFTTT и т.д.
Если вы хотите повторить именно этот проект, вам следует сначала выполнить предыдущее руководство, чтобы подготовить собственный серверный домен. Затем загрузите код, предоставленный в этом проекте, на вашу плату ESP32.
Вкратце, вот как работает проект:
Плата T-Call ESP32 SIM800L находится в режиме глубокого сна.
Она просыпается и подключается к интернету через тарифный план SIM-карты.
Публикует показания датчиков на сервер и снова засыпает.
В нашем примере время сна составляет 60 минут, но вы можете легко изменить его в коде.
Мы будем использовать датчик BME280, но вы можете использовать любой другой датчик, который лучше всего подходит для ваших нужд.
Хостинг-провайдер
Если у вас нет аккаунта хостинга, рекомендуем зарегистрироваться на Bluehost, так как он может обеспечить все требования проекта.
Предварительные требования
1. Дополнение ESP32 для Arduino IDE
Мы будем программировать ESP32 в Arduino IDE. Поэтому вам необходимо установить дополнение ESP32 в Arduino IDE. Следуйте следующему руководству, если вы этого ещё не сделали.
2. Подготовка серверного домена
В этом проекте мы покажем, как публиковать данные в любой облачный сервис. Мы будем использовать собственный серверный домен с базой данных для публикации всех данных, но вы можете использовать любой другой сервис, например ThingSpeak, IFTTT и т.д.
Если вы хотите повторить именно этот проект, следуйте следующему руководству для подготовки собственного серверного домена.
3. SIM-карта с тарифным планом
Для использования платы TTGO T-Call ESP32 SIM800L вам нужна nano SIM-карта с тарифным планом для передачи данных. Мы рекомендуем использовать SIM-карту с предоплаченным или ежемесячным тарифом, чтобы вы точно знали, сколько потратите.
4. Данные APN
Для подключения SIM-карты к интернету вам необходимо знать данные APN вашего оператора. Вам нужны: доменное имя, имя пользователя и пароль.
В моём случае я использую vodafone Portugal. Если вы поищете GPRS APN settings с названием вашего оператора (в моём случае: «GPRS APN vodafone Portugal»), обычно можно найти на форуме или на их сайте всю необходимую информацию.
Я нашёл этот сайт, который может быть очень полезен для поиска всей нужной информации.
Может быть немного сложно найти данные, если вы используете не очень известного оператора. В этом случае вам, возможно, придётся связаться с ними напрямую.
5. Библиотеки
Для этого проекта вам нужно установить следующие библиотеки: Adafruit_BME280, Adafruit_Sensor и TinyGSM. Следуйте инструкциям ниже для установки этих библиотек.
Установка библиотеки Adafruit BME280
Откройте Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Откроется Library Manager.
Введите «adafruit bme280» в поле поиска и установите библиотеку.
Установка библиотеки Adafruit Sensor
Для использования библиотеки BME280 вам также нужно установить библиотеку Adafruit_Sensor. Выполните следующие шаги для установки библиотеки в Arduino IDE:
Перейдите в Sketch > Include Library > Manage Libraries и введите «Adafruit Unified Sensor» в поле поиска. Прокрутите вниз, найдите библиотеку и установите её.
Установка библиотеки TinyGSM
В Library Manager Arduino IDE найдите TinyGSM. Выберите библиотеку TinyGSM от Volodymyr Shymanskyy.
После установки библиотек перезапустите Arduino IDE.
Необходимые компоненты
Для сборки этого проекта вам понадобятся следующие компоненты:
Схема подключения
Подключите BME280 к плате T-Call ESP32 SIM800L, как показано на следующей схеме.
Мы подключаем вывод SDA к GPIO 18, а вывод SCL к GPIO 19. Мы не используем стандартные выводы I2C, потому что они уже используются микросхемой управления питанием батареи платы T-Call ESP32 SIM800L.
Код
Скопируйте следующий код в Arduino IDE, но пока не загружайте его. Сначала необходимо внести некоторые изменения, чтобы он заработал.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-sim800l-publish-data-to-cloud/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Your GPRS credentials (leave empty, if not needed)
const char apn[] = ""; // APN (example: internet.vodafone.pt) use https://wiki.apnchanger.org
const char gprsUser[] = ""; // GPRS User
const char gprsPass[] = ""; // GPRS Password
// SIM card PIN (leave empty, if not defined)
const char simPIN[] = "";
// Server details
// The server variable can be just a domain name or it can have a subdomain. It depends on the service you are using
const char server[] = "example.com"; // domain name: example.com, maker.ifttt.com, etc
const char resource[] = "/post-data.php"; // resource path, for example: /post-data.php
const int port = 80; // server port number
// Keep this API Key value to be compatible with the PHP code provided in the project page.
// If you change the apiKeyValue value, the PHP file /post-data.php also needs to have the same key
String apiKeyValue = "tPmAT5Ab3j7F9";
// TTGO T-Call pins
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
// BME280 pins
#define I2C_SDA_2 18
#define I2C_SCL_2 19
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800 // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
// Define the serial console for debug prints, if needed
//#define DUMP_AT_COMMANDS
#include <Wire.h>
#include <TinyGsmClient.h>
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
// I2C for SIM800 (to keep it running when powered from battery)
TwoWire I2CPower = TwoWire(0);
// I2C for BME280 sensor
TwoWire I2CBME = TwoWire(1);
Adafruit_BME280 bme;
// TinyGSM Client for Internet connection
TinyGsmClient client(modem);
#define uS_TO_S_FACTOR 1000000UL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 3600 /* Time ESP32 will go to sleep (in seconds) 3600 seconds = 1 hour */
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
bool setPowerBoostKeepOn(int en){
I2CPower.beginTransmission(IP5306_ADDR);
I2CPower.write(IP5306_REG_SYS_CTL0);
if (en) {
I2CPower.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
} else {
I2CPower.write(0x35); // 0x37 is default reg value
}
return I2CPower.endTransmission() == 0;
}
void setup() {
// Set serial monitor debugging window baud rate to 115200
SerialMon.begin(115200);
// Start I2C communication
I2CPower.begin(I2C_SDA, I2C_SCL, 400000);
I2CBME.begin(I2C_SDA_2, I2C_SCL_2, 400000);
// Keep power when running from battery
bool isOk = setPowerBoostKeepOn(1);
SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));
// Set modem reset, enable, power pins
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
// Restart SIM800 module, it takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// use modem.init() if you don't need the complete restart
// Unlock your SIM card with a PIN if needed
if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
modem.simUnlock(simPIN);
}
// You might need to change the BME280 I2C address, in our case it's 0x76
if (!bme.begin(0x76, &I2CBME)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
// Configure the wake up source as timer wake up
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
}
void loop() {
SerialMon.print("Connecting to APN: ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
}
else {
SerialMon.println(" OK");
SerialMon.print("Connecting to ");
SerialMon.print(server);
if (!client.connect(server, port)) {
SerialMon.println(" fail");
}
else {
SerialMon.println(" OK");
// Making an HTTP POST request
SerialMon.println("Performing HTTP POST request...");
// Prepare your HTTP POST request data (Temperature in Celsius degrees)
String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bme.readTemperature())
+ "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
// Prepare your HTTP POST request data (Temperature in Fahrenheit degrees)
//String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(1.8 * bme.readTemperature() + 32)
// + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
// You can comment the httpRequestData variable above
// then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
//String httpRequestData = "api_key=tPmAT5Ab3j7F9&value1=24.75&value2=49.54&value3=1005.14";
client.print(String("POST ") + resource + " HTTP/1.1\r\n");
client.print(String("Host: ") + server + "\r\n");
client.println("Connection: close");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(httpRequestData.length());
client.println();
client.println(httpRequestData);
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 10000L) {
// Print available data (HTTP response from server)
while (client.available()) {
char c = client.read();
SerialMon.print(c);
timeout = millis();
}
}
SerialMon.println();
// Close client and disconnect
client.stop();
SerialMon.println(F("Server disconnected"));
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
}
}
// Put ESP32 into deep sleep mode (with timer wake up)
esp_deep_sleep_start();
}
Перед загрузкой кода вам нужно вставить данные APN, PIN-код SIM-карты (если применимо) и домен вашего сервера.
Важно: Большинство хостинг-сервисов требуют выполнения HTTPS-запросов. Этот код несовместим с HTTPS. Поэтому, чтобы он заработал, вам нужно отключить HTTPS на вашем сервере или включить одновременно HTTP и HTTPS (свяжитесь с вашим хостинг-провайдером). Хотя эта плата поддерживает HTTPS-запросы, нам не удалось заставить их работать. Тем не менее, вы можете попробовать этот пример скетча и проверить, работают ли HTTPS-запросы для вашей платы.
Как работает код
Введите учётные данные GPRS APN в следующие переменные:
const char apn[] = ""; // APN (example: internet.vodafone.pt) use https://wiki.apnchanger.org
const char gprsUser[] = ""; // GPRS User
const char gprsPass[] = ""; // GPRS Password
В нашем случае APN — это internet.vodafone.pt. У вас он должен быть другим. Ранее в этом руководстве мы объяснили, как получить данные APN.
Введите PIN-код SIM-карты, если применимо:
const char simPIN[] = "";
Вам также нужно указать данные сервера в следующих переменных. Это может быть ваш собственный серверный домен или любой другой сервер, на который вы хотите публиковать данные.
const char server[] = "example.com"; // domain name: example.com, maker.ifttt.com, etc
const char resource[] = "/post-data.php"; // resource path, for example: /post-data.php
const int port = 80; // server port number
Если вы используете собственный серверный домен, как мы в этом руководстве, вам также понадобится API-ключ. В данном случае apiKeyValue — это просто случайная строка, которую вы можете изменить. Она используется в целях безопасности, чтобы только тот, кто знает ваш API-ключ, мог публиковать данные в вашу базу данных.
Код подробно прокомментирован, чтобы вы понимали назначение каждой строки.
Следующие строки определяют выводы, используемые модулем SIM800L:
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
Определяем выводы I2C для BME280. В этом примере мы не используем стандартные выводы, потому что они уже используются микросхемой управления питанием батареи платы T-Call ESP32 SIM800L. Поэтому мы используем GPIO 18 и GPIO 19.
#define I2C_SDA_2 18
#define I2C_SCL_2 19
Определяем последовательное соединение для Serial Monitor и ещё одно для связи с модулем SIM800L:
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1
Настраиваем библиотеку TinyGSM для работы с модулем SIM800L.
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800 // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
Подключаем следующие библиотеки для связи с SIM800L.
#include <Wire.h>
#include <TinyGsmClient.h>
И эти библиотеки для работы с датчиком BME280:
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Создаём экземпляр I2C-соединения для SIM800L.
TwoWire I2CPower = TwoWire(0);
И ещё одно I2C-соединение для датчика BME280.
TwoWire I2CBME = TwoWire(1);
Adafruit_BME280 bme;
Инициализируем TinyGSMClient для интернет-соединения.
TinyGsmClient client(modem);
Определяем время глубокого сна в переменной TIME_TO_SLEEP в секундах.
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 3600 /* Time ESP32 will go to sleep (in seconds) 3600 seconds = 1 hour */
В setup() инициализируем Serial Monitor на скорости 115200:
SerialMon.begin(115200);
Запускаем I2C-соединение для модуля SIM800L и для модуля датчика BME280:
I2CPower.begin(I2C_SDA, I2C_SCL, 400000);
I2CBME.begin(I2C_SDA_2, I2C_SCL_2, 400000);
Настраиваем выводы SIM800L в правильное состояние для работы:
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
Инициализируем последовательное соединение с модулем SIM800L:
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
Инициализируем модуль SIM800L и разблокируем PIN-код SIM-карты при необходимости:
SerialMon.println("Initializing modem...");
modem.restart();
// use modem.init() if you don't need the complete restart
// Unlock your SIM card with a PIN if needed
if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
modem.simUnlock(simPIN);
}
Инициализируем модуль датчика BME280:
if (!bme.begin(0x76, &I2CBME)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
Настраиваем глубокий сон как источник пробуждения:
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Рекомендуемое чтение: ESP32 Deep Sleep и источники пробуждения
В loop() происходит непосредственное подключение к интернету и выполнение HTTP POST-запроса для публикации данных датчиков. Поскольку ESP32 перейдёт в режим глубокого сна в конце loop(), этот код выполнится только один раз.
Следующие строки подключают модуль к интернету:
SerialMon.print("Connecting to APN: ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
}
else {
SerialMon.println(" OK");
SerialMon.print("Connecting to ");
SerialMon.print(server);
if (!client.connect(server, port)) {
SerialMon.println(" fail");
}
else {
SerialMon.println(" OK");
Подготавливаем данные сообщения для отправки через HTTP POST-запрос:
String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bme.readTemperature())
+ "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
По сути, мы создаём строку с API-ключом и всеми показаниями датчиков. Вам следует изменить эту строку в зависимости от данных, которые вы хотите отправить.
Следующие строки выполняют POST-запрос.
client.print(String("POST ") + resource + " HTTP/1.1\r\n");
client.print(String("Host: ") + server + "\r\n");
client.println("Connection: close");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(httpRequestData.length());
client.println();
client.println(httpRequestData);
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 10000L) {
// Print available data (HTTP response from server)
while (client.available()) {
char c = client.read();
SerialMon.print(c);
timeout = millis();
}
}
Наконец, закрываем соединение и отключаемся от интернета.
client.stop();
SerialMon.println(F("Server disconnected"));
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
В конце переводим ESP32 в режим глубокого сна.
esp_deep_sleep_start();
Загрузка кода
После ввода всех необходимых данных вы можете загрузить код на плату.
Для загрузки кода на плату перейдите в Tools > Board и выберите ESP32 Dev module. Перейдите в Tools > Port и выберите COM-порт, к которому подключена ваша плата. Затем нажмите кнопку загрузки, чтобы загрузить код на плату.
Примечание: на данный момент для T-Call ESP32 SIM800L нет отдельной платы в списке, но мы выбрали ESP32 Dev Module, и всё работает нормально.
Демонстрация
Откройте Serial Monitor на скорости 115200 и нажмите кнопку RST на плате.
Сначала модуль инициализируется, затем пытается подключиться к интернету. Обратите внимание, что это может занять некоторое время (в некоторых случаях выполнение запроса заняло почти 1 минуту).
После подключения к интернету он подключится к вашему серверу для выполнения HTTP POST-запроса.
Наконец, он отключится от сервера, отключит интернет и перейдёт в режим сна.
В этом примере новые показания датчиков публикуются каждые 60 минут, но для тестирования можно использовать более короткую задержку.
Затем откройте браузер и введите домен вашего сервера с URL /esp-chart.php. Вы должны увидеть графики с последними показаниями датчиков.
Устранение неполадок
Если на этом этапе вы не можете подключить модуль к интернету, это может быть вызвано одной из следующих причин:
Учётные данные APN могут быть неверными;
Антенна может работать неправильно. В нашем случае нам пришлось заменить антенну;
Возможно, вам нужно выйти на улицу для лучшего покрытия сигнала;
Или вы можете подавать недостаточно тока на модуль. Если вы подключаете модуль к компьютеру через USB-хаб без внешнего блока питания, он может не обеспечить достаточный ток для работы.
Заключение
Надеемся, вам понравился этот проект. На наш взгляд, плата T-Call SIM800 ESP32 может быть очень полезна для IoT-проектов, которые не имеют доступа к ближайшему роутеру через Wi-Fi. Вы можете довольно легко подключить плату к интернету, используя тарифный план SIM-карты.
Вам также может быть интересно:
$11 TTGO T-Call ESP32 with SIM800L GSM/GPRS (подробный обзор)
ESP32/ESP8266 вставка данных в базу MySQL с помощью PHP и Arduino IDE
ESP32/ESP8266 построение графиков показаний датчиков в реальном времени — веб-сервер
Дополнительные ресурсы по ESP32:
Примечание
Данная статья является переводом материала с сайта Random Nerd Tutorials.