В данном руководстве рассмотрим, как загружать данные в облако с платы TTGO T-Call ESP32 SIM800L через мобильный интернет.
Плата TTGO T-Call ESP32 SIM800L
Данная плата является модификацией платы ESP32 с модулем SIM800L GSM/GPRS.
Взаимодействовать с данной платой возможно не только по Wi-Fi и Bluetooth, но также с помощью СМС и мобильных звонков. Также возможно использовать мобильный интернет, что может быть очень удобным для IoT-проектов.
Важно: SIM800L работает в сети 2G, а она, в свою очередь, работает не везде. Проверьте покрытие вашего мобильного оператора.
Для использования данной платы вам потребуется nano-SIM карта и кабель USB Type-C для загрузки скетча.
В комплекте с платой идут несколько штыревых разъемов, коннектор питания и внешняя антенна, которую надо присоединить к плате.
Однако, антенна из комплекта плохо работала и мы заменили ее другой.
Обзор
Суть проекта заключается в загрузке данных датчика в облако используя мобильный интернет, а не Wi-Fi.
В предыдущем проекте мы создали сервер с базой данных для хранения показаний датчика.
В данном проекте мы будем загружать данные на этот сервер, хотя вы можете использовать любой другой сервис: ThingSpeak, IFTTT и др.
Если вы хотите в точности повторять наши действия, то вам следует сначала ознакомиться с предыдущим проектом.
Вот, непосредственно, суть проекта:
- Плата находится в спящем режиме;
- Затем она подключается к мобильному интернету;
- Плата выкладывает показания датчика на сервер и уходит в спящий режим.
В нашем случае время нахождения в спящем режиме – 60 секунд.
Мы будем использовать датчик BME280, однако код легко изменить под любой другой датчик.
Что нам потребуется?
- Пакет ESP32 для Arduino IDE
Скетч для платы ESP32 мы будем писать в среде Arduino, поэтому необходимо, чтобы плата была установлена.
- Подготовка сервера
В данном проекте мы покажем, как загружать данные в облако. Мы используем свой домен с базой данных.
Если вы хотите в точности следовать данному руководству, то сначала нужно ознакомиться с этим руководством.
- SIM-карта
Для использования платы TTGO T-Call ESP32 SIM800L вам потребуется nano-SIM.
- Настройки APN
Ваша SIM-карта должна поддерживать подключение к мобильному интернету, поэтому нужно выставить правильные настройки APN. Обычно, оператор сотовой связи сам их предоставляет, но если нет, то найдите их на веб-сайте вашего мобильного оператора.
- Установка библиотек
Для работы с проектом вам потребуется установить библиотеки Adafruit_BME280, Adafruit_Sensor и TinyGSM. Выполните следующие шаги, чтобы установить библиотеки:
Чтобы получить показания от модуля датчика BME280, мы будем использовать библиотеку Adafruit_BME280. Вам также необходимо установить библиотеку Выполните следующие шаги, чтобы установить библиотеки в вашу Arduino IDE:
- Откройте IDE Arduino и выберите Скетч> Подключить библиотеку> Управлять библиотеками. Должен открыться менеджер библиотек.
- Найдите adafruit bme280 в поле поиска и установите библиотеку.
Чтобы использовать библиотеку BME280, также необходимо установить Adafruit Unified Sensor. Выполните следующие шаги, чтобы установить библиотеку в вашу среду разработки Arduino:
Найдите Adafruit Unified Sensor в поле поиска. Прокрутите до конца, найдите библиотеку и установите ее.
В менеджере библиотек найдите библиотеку TinyGSM и установите её:
После установки всех библиотек перезапустите Arduino IDE.
Какие компоненты потребуются?
Нам потребуются следующие компоненты:
- TTGO T-Call ESP32 SIM800L
- Кабель USB Type-C
- Антенна (не обязательно)
- Датчик BME280
- Макетная плата
- Провода DuPont
Схема
Соедините датчик BME280 с платой согласно следующей схеме:
Мы подключаем пин SDA к выходу GPIO18 и SCL к GPIO19. Мы не используем выход I2C потому, что они используются регулятором батареи платы.
Код
Скопируйте следующий код в свой скетч, но пока не загружайте. Вам потребуется внести некоторые изменения.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
/* 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. */ // Настройки GPRS (если не требуются, оставьте пустыми) const char apn[] = ""; //APN const char gprsUser[] = ""; // имя пользователя const char gprsPass[] = ""; // пароль // пин-код SIM-карты const char simPIN[] = ""; // В переменной сервера указываем домен (или субдомен) const char server[] = "example.com"; // domain name: example.com, maker.ifttt.com, etc const char resource[] = "/post-data.php"; // путь к файлу const int port = 80; // номер порта для сервера // Оставьте данный API, чтобы /post-data.php работал на странице проекта // Если вы его измените, что в файле /post-data.php тоже придется его менять String apiKeyValue = "tPmAT5Ab3j7F9"; // пины платы TTGO T-Call #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 #define I2C_SDA_2 18 #define I2C_SCL_2 19 // указываем порт для монитора порта #define SerialMon Serial // устанавливаем порт для команд AT #define SerialAT Serial1 // настраиваем библиотеку TinyGSM #define TINY_GSM_MODEM_SIM800 // SIM800 - модем #define TINY_GSM_RX_BUFFER 1024 // Устанавливаем буфер равным 1Кб // Определяем команды для монитора порта //#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 для SIM800 TwoWire I2CPower = TwoWire(0); // I2C для датчика BME280 TwoWire I2CBME = TwoWire(1); Adafruit_BME280 bme; // клиент TinyGSM для подключения к интернету TinyGsmClient client(modem); #define uS_TO_S_FACTOR 1000000UL /* преобразуем микросекунды в секунды */ #define TIME_TO_SLEEP 3600 /* время спящего режима 1 час = 3600 секунд */ #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); // если 1 включаем плату, если 0 - выключаем } else { I2CPower.write(0x35); // 0x37 – значение по умолчанию } return I2CPower.endTransmission() == 0; } void setup() { // запускаем монитор порта SerialMon.begin(115200); // Начинаем подключение I2C I2CPower.begin(I2C_SDA, I2C_SCL, 400000); I2CBME.begin(I2C_SDA_2, I2C_SCL_2, 400000); // Не выключаем плату при питании от батареи bool isOk = setPowerBoostKeepOn(1); SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL")); // Сброс, включение и контакты питания 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); // Устанавливаем скорость передачи данных модуля GSM и контакты UART. SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX); delay(3000); // Перезапускаем модуль SIM800 // Для пропуска вместо restart() напишите init(0 SerialMon.println("Initializing modem..."); modem.restart(); // Вводим пин-код SIM-карты, если требуется if (strlen(simPIN) && modem.getSimStatus() != 3 ) { modem.simUnlock(simPIN); } // Требуется поменять адрес датчика BME280, в нашем случае 0x76 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); } 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"); // Делаем запрос POST SerialMon.println("Performing HTTP POST request..."); // Подготавливаем данные для отправки String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bme.readTemperature()) + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + ""; 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) { // Выводим данные (HTTP ответ от сервера) while (client.available()) { char c = client.read(); SerialMon.print(c); timeout = millis(); } } SerialMon.println(); // Закрываем клиент и отключаемся client.stop(); SerialMon.println(F("Server disconnected")); modem.gprsDisconnect(); SerialMon.println(F("GPRS disconnected")); } } // Переходим в спящий режим esp_deep_sleep_start(); } |
Как работает код?
Вставьте свои настройки APN в следующие переменные
1 2 3 4 5 |
const char apn[] = ""; //APN const char gprsUser[] = ""; // имя пользователя const char gprsPass[] = ""; // пароль |
Вставьте свой пин-код от SIM-карты (если требуется):
1 |
const char simPIN[] = ""; |
Вам также надо указать данные своего сервера в следующих переменных.
1 2 3 4 5 |
const char server[] = "example.com"; // domain name: example.com, maker.ifttt.com, etc const char resource[] = "/post-data.php"; // путь к файлу const int port = 80; // номер порта для сервера |
Если вы используете свой домен, как мы делаем здесь, то вам также потребуется API-ключ. Он нужен для безопасности, чтобы никто кроме вас не мог загружать данные на сервер.
Эта часть кода подробно закомментирована, так что вы сами можете понять, что она делает.
Следующие строки определяют пины, используемые модулем SIM800L:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#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. В данном руководстве мы не используем пины по умолчанию, так как они уже используются питанием платы. Поэтому мы используем GPIO18 и GPIO19.
1 2 3 |
#define I2C_SDA_2 18 #define I2C_SCL_2 19 |
Настраиваем последовательный порт:
1 2 3 4 5 6 7 |
// указываем порт для монитора порта #define SerialMon Serial // устанавливаем порт для команд AT #define SerialAT Serial1 |
Конфигурируем библиотеку TinyGSM:
1 2 3 4 5 |
// настраиваем библиотеку TinyGSM #define TINY_GSM_MODEM_SIM800 // SIM800 - модем #define TINY_GSM_RX_BUFFER 1024 // Устанавливаем буфер равным 1Кб |
Подключаем следующие библиотеки для работы с SIM800L
1 2 3 |
#include <Wire.h> #include <TinyGsmClient.h> |
И эти библиотеки для датчика BME280
1 2 3 |
#include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> |
Настраиваем I2C соединение для SIM800L
1 |
TwoWire I2CPower = TwoWire(0); |
И такое же, но для нашего датчика
1 2 3 |
TwoWire I2CBME = TwoWire(1); Adafruit_BME280 bme; |
Запускаем клиент TinyGSM для подключения к интернету
1 |
TinyGsmClient client(modem); |
Определяем время нахождения в спящем режиме в секундах
1 2 3 |
#define uS_TO_S_FACTOR 1000000UL /* преобразуем микросекунды в секунды */ #define TIME_TO_SLEEP 3600 /* время спящего режима 1 час = 3600 секунд */ |
Запускаем монитор порта:
1 2 3 4 5 |
void setup() { // запускаем монитор порта SerialMon.begin(115200); |
Начинаем подключение I2C к датчику и модулю SIM800L
1 2 3 |
I2CPower.begin(I2C_SDA, I2C_SCL, 400000); I2CBME.begin(I2C_SDA_2, I2C_SCL_2, 400000); |
Указываем нормальное состояние пинов SIM800L для работы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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); v Запускаем COM-соединение с модулем SIM-800L |
1 2 3 |
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX); delay(3000); |
Запускаем модуль и вводим пин-код (если требуется)
1 2 3 4 5 6 7 8 9 10 11 |
SerialMon.println("Initializing modem..."); modem.restart(); // Вводим пин-код SIM-карты, если требуется if (strlen(simPIN) && modem.getSimStatus() != 3 ) { modem.simUnlock(simPIN); } |
Запускаем датчик BME280
1 2 3 4 5 6 7 |
if (!bme.begin(0x76, &I2CBME)) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1); } |
Конфигурируем режим сна платы
1 2 3 |
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); } |
В loop() мы подключаемся к интернету и делаем POST-запрос для выкладки данных. Из-за того, что мы переводим плату в режим сна в конце loop(). он будет выполняться всего один раз.
Следующие строки отвечают за подключение к интернету:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
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"); |
Подготавливаем данные сообщение для отправки запросом POST
1 2 3 |
String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bme.readTemperature()) + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + ""; |
В общем-то, мы создаем строку с API-ключом и показаниями датчика.
Следующие строки формируют POST-запрос:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
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) { // Выводим данные (HTTP ответ от сервера) while (client.available()) { char c = client.read(); SerialMon.print(c); timeout = millis(); } } SerialMon.println(); |
Ну и наконец, закрываем соединение и отключаемся от интернета:
1 2 3 4 5 6 7 8 9 10 11 |
client.stop(); SerialMon.println(F("Server disconnected")); modem.gprsDisconnect(); SerialMon.println(F("GPRS disconnected")); } } |
И переходим в спящий режим:
1 2 3 |
esp_deep_sleep_start(); } |
Загрузка кода
После внесения необходимых изменений, загрузите код на плату. Для этого перейдите Инструменты>Плата и выберите ESP32 Dev Module. Перейдите Инструменты>Порт и выберите COM-порт для вашей платы. Теперь загрузите код на плату.
Демонстрация
Запустите монитор порт на скорости 115200 и нажмите кнопку RST на плате.
Почти минута уйдет на то, чтобы плата подключилась к интернету. После подключения она начнет подключаться к серверу для отправки запроса. И наконец, плата отключится от сервера, интернета и уйдет в спящим режим.
Теперь откройте браузер и введите адрес своего сервера с /esp–chart.php. На графиках вы должны увидеть новые данные:
Возможные проблемы
Если вы не можете подключить модуль SIM800L к интернету, то вот возможные причины:
- Настройки APN неправильные;
- Антенна неправильно работает. В нашем случае, мы ее заменили;
- Вам нужно вынести плату на улицу, чтобы соединение было лучше;
- Или плате на хватает питания. Если ваша плата подключена к компьютеру по USB кабелю без внешнего питания, то может не хватать тока.
Вопросы по прошивке и работе с кодом лучше писать напрямую автору в комментариях к статье (на англ. языке)
2 комментария. Оставить новый
>Или плате на хватает питания. Если ваша плата подключена к компьютеру по USB кабелю без внешнего питания, то может не хватать тока.
По вашей отстойной инструкции ей и не будет хватать питания из-за gsm модуля. Слабо дописать как подключить питание?
Рекомендуем вам не пользоваться нашей отстойной инструкцией и произвести все необходимые подключения самостоятельно. Слабо самостоятельно догадаться как подключить внешнее питание?