Симулятор LoRa SX1276 онлайн в браузере
LoRa SX1276 это радиомодуль дальней связи: в открытом поле он передаёт данные на несколько километров, а в городе уверенно бьёт на сотни метров. Частота 868 МГц для Европы и России, 433 МГц для Азии, 915 МГц для США. В симуляторе этот модуль виртуальный: эхо-демо, где передатчик шлёт пакет, а приёмник в том же скетче его читает.
Зачем это нужно: каркас протокола, то есть формат пакета, счётчик, проверка целостности, удобно проверять до того, как в почту приедут модули. Радиопередачу в браузере, конечно, не смоделировать, но весь код вокруг неё работает точно так же.
Откройте симулятор, выберите пример «LoRa: Передатчик» или «LoRa: Приёмник» в меню Examples, нажмите «Загрузить». В Serial появятся отправленные и принятые пакеты.
Эхо-демо: TX и RX в одном скетче
В настоящей LoRa-связи нужны две платы: одна передаёт, вторая принимает. В симуляторе достаточно одной: вызов endPacket кладёт сообщение в виртуальный буфер приёмника, а parsePacket его оттуда читает. Так проверяется вся логика протокола: как собирается пакет, что считается счётчиком, что происходит при неполном пакете. Единственное, чего нет, это самого радио.
Грабль питания. SX1276 рассчитан на 3.3 В, и 5 В на его вывод VCC сожжёт чип. На платах-модулях с адаптером стоит LDO, и тогда питание 5 В допустимо, но на дешёвых клонах стабилизатор часто экономят, и чип начинает голодать: пакеты вроде уходят, а дальность падает вдвое. AMS1117-3.3 с конденсатором 10 мкФ на входе и 0.1 мкФ на выходе решает вопрос.
Антенна обязательна, и это не формальность. Без неё выход передатчика оказывается несогласованным, чип перегревается и реальная дальность падает с километров до десятков метров. Для 868 МГц подойдёт проволочная антенна длиной около 8.6 см, это четверть длины волны, или готовая SMA-антенна на 868 МГц.
Код передатчика
#include <LoRa.h>LoRa lora;int counter = 0;void setup() { Serial.begin(9600); lora.begin(868E6); lora.setSpreadingFactor(7); lora.setTxPower(17);}void loop() { lora.beginPacket(); lora.print("ping #"); lora.print(counter); lora.endPacket(); Serial.print("Отправлено: ping #"); Serial.println(counter); counter++; delay(2000);}Параметры LoRa: spreading factor выбирается от SF7 до SF12, чем он выше, тем медленнее передача, но тем лучше пробиваются препятствия. Bandwidth обычно оставляют 125 кГц, это стандарт. TxPower задаёт мощность передачи, для SX1276 через вывод PA_BOOST доступно до 17 dBm, и больше мощность значит больше ток. Частота передаётся в begin как число: 433E6 это 433 МГц, 868E6 это 868 МГц, 915E6 это 915 МГц.
Код приёмника
#include <LoRa.h>LoRa lora;void setup() { Serial.begin(9600); lora.begin(868E6); Serial.println("LoRa приёмник готов");}void loop() { int packetSize = lora.parsePacket(); if (packetSize) { Serial.print("Получено: "); while (lora.available()) Serial.write((char)lora.read()); Serial.print(" RSSI: "); Serial.println(lora.packetRssi()); } delay(100);}RSSI это уровень принятого сигнала в dBm. В документации самой библиотеки LoRa.h -50 dBm считается отличным сигналом, а значения около -100 dBm и ниже означают, что приём на грани. Чем выше скорость передачи, тем хуже чувствительность приёмника, поэтому при SF7 в одном месте связь есть, а при SF12 там же пропадает. packetSnr показывает отношение сигнал к шуму, и положительное значение означает, что пакет декодирован уверенно.
Подробнее про LoRa-связь — в нишевом лендинге. nRF24L01 — альтернатива для 2.4 ГГц на короткие дистанции.
| Параметр | LoRa SX1276 | В симуляторе |
|---|---|---|
| Частота | 433/868/915 МГц | 868 МГц (виртуально) |
| Дальность | до 15 км (открыто) | Эхо в одном скетче |
| Скорость | 0.3-50 кбит/с (SF12-SF7) | Не моделируется |
| RSSI диапазон | -50 до -120 dBm | -50 dBm (фиксированный) |
| Ток TX | 20-120 мА (при 17 dBm) | Не моделируется |
Что сначала не получилось
Первый скетч я написал по интуиции: в setup вызвал lora.begin(868E6), а частоту думал, что задаётся где-то отдельно. Пакеты не уходили, и я полчаса искал в библиотеке метод setFrequency. Оказалось, что частота задаётся именно в begin, а отдельного вызова для неё в библиотеке LoRa.h нет.
Второй затык был в том, что я читал приёмник в том же цикле, где отправлял, и ожидал увидеть в Serial и отправку, и приём. Не увидел приёма, потому что parsePacket нужно вызывать отдельным проходом. Как только я развёл отправку и чтение по разным веткам, приёмник заработал и в симуляторе, и потом на двух настоящих модулях.
Третье, что я запомнил: я выставил spreading factor 12 из-за обещаний огромной дальности, и пакеты стали приходить с задержкой в несколько секунд. Для телеметрии это оказалось слишком медленно: при SF12 скорость падает примерно до 293 бит/с, а при SF7 она в разы выше. Оптимальным для датчиков оказался SF9.
Личный опыт: проверка протокола до покупки модулей
Я готовил систему сбора данных с удалённых датчиков: там были записи в flash, счётчик пакетов и разбор входящих данных, и всё это нужно было проверить до заказа плат. В симуляторе я написал передатчик, который раз в две секунды отправляет строку с номером пакета, и приёмник, который печатает принятое и тут же сверяет счётчик.
Проверял я это по числам: за минуту передатчик отправлял 30 пакетов, и приёмник должен был принять ровно 30. Первый прогон дал 29, и я почти час искал потерю. Причина оказалась в том, что в приёмнике я читал буфер один раз за проход и не успевал вычитать всё за цикл, из-за чего последний байт пакета оставался в буфере и сдвигал следующий. Когда я переписал чтение на цикл по available(), счётчик стал совпадать ровно. После этой проверки на настоящих модулях я не потерял ни одного пакета.
Как это выглядит в реальном проекте
В настоящей системе передатчик не сидит и не шлёт пакеты непрерывно. Обычно он спит, просыпается по таймеру, читает датчик, отправляет короткий пакет и снова засыпает. Такой режим даёт главное преимущество LoRa: с передачей раз в десять минут от батарейки 18650 модуль живёт месяцами, потому что почти всё время потребление определяет не радио, а сам ESP32.
Отсюда правило: чем реже вы шлёте, тем меньше процент времени модуль находится в состоянии передачи, и тем меньше средний ток. При 120 мА в пике и 100 мс на пакет это всего около 12 мА·с в минуту, то есть примерно 0.2 мА среднего потребления модуля. Всю остальную энергию съедает Arduino, поэтому для батарейных проектов ESP32 с deep sleep здесь лучшее сочетание.
Ещё один практический совет: перед отправкой пакета вставьте в него номер и контрольную сумму. По LoRa пакет может прийти повреждённым или не прийти совсем, и без проверки вы не отличите одно от другого. Простейший вариант это добавить в конец строки два байта суммы и проверить их на приёмной стороне.
Авторская позиция: что взять новичку
Берите модули с адаптером, где выведены все выводы SPI и стоит стабилизатор на 3.3 В: Heltec или RFM95, они одинаково удобны и стоят одинаково. Начинайте с 868 МГц, если вы в России или Европе, и сразу выясните, какие правила применяются к мощности в вашей стране, чтобы не создавать помех. И не пытайтесь в симуляторе проверить дальность: это невозможно в принципе. Симулятор здесь для того, чтобы код был написан верно, а дальность вы измерите на улице с парой настоящих модулей и рулеткой.