Big ESP32 + SX127x topic part 2


Heltec Wifi LoRa 32 birdseye 500x366

For the first part of this topic see: BIG ESP32 / SX127x topic part 1

The ESP32 microcontroller and SX127x / RFM9x LoRa transceivers

The ESP32 has built-in support for Wifi and Bluetooth communication but not for LoRa. A SX127x or RFM9x LoRa transceiver adds support for LoRa and the LoRaWAN protocol that are needed for The Things Network.

Semtech SX127x LoRa transceivers and HopeRF RFM9x LoRa transceivers are identical. They come in different variants, depending on the targeted frequency band (433, 868 and 915 MHz). Which frequencies are used depends on the geographic region and local ISM band regulations. (HopeRF module numbers usually end with W which stands for ‘international version’.)

The ESP32 and the LoRa transceivers come in several forms:

  • On modules.
    Modules contain additional components required for making the chips work. The modules use 1.27mm or 2mm pin spacing. For use with breadboards and prototyping PCB with 2.54mm spacing adapters are required. Examples: ESP-WROOM-32 ESP32 module, SX1276 and RFM95 LoRa modules.
  • On development boards.
    Development boards (often) convert to 2.54mm spacing and add additional functionality like power converter, buttons and LEDs. Development boards use either standard modules or separate components. Examples: ESP32 Dev board, Lolin32 and NodeMCU-32S. A pure adapter is the HopeRF RFM95 adapter.
  • On custom boards which combine ESP32 with a LoRa transceiver.
    Custom boards can use standard modules, separate components or a combination of both.
    Examples: Heltec Wifi LoRa 32 and TTGO LoRa32.


In addition to the hardware, software is needed for implementing the LoRaWAN protocol. The SX127x LoRa tranceiver provides LoRa radio modulation but it does not implement the LoRaWAN protocol. The protocol has to be implemented in software that needs to run on the ESP32.

The following library implements a LoRaWAN protocol stack that can be used with ESP32: LMIC-Arduino.
The LMIC-Arduino library can be found here:
The library contains examples for implementing a Things Network node for both ABP and OTAA activation.

Try to get the ttn-abp.ino example working first. If that works continue with the ttn-otaa.ino example. When both these examples work then the LoRaWAN part of your setup works. From there you can start adding additional features (e.g. temperature sensor) but get the basics working first.
ABP and OTAA require different settings. See TTN Console and remarks in the sketches for more information.

A nice library for (on-board) (OLED) monochrome displays is: U8g2
The U8g2 library can be found here:
(U8g2 includes U8x8 which is lower on resources.)

ESP32 + SX127x/RFM9x can also be used for implementing a Single Channel Gateway. Information about the Single Channel Gateway software can be found in the following topic: Single Channel Gateway part 3
(See ‘List of single channel gateway implementations / For ESP32’.)

Popular ESP32 LoRa boards

The following boards are popular for prototyping because they combine an ESP32, a LoRa tranceiver, an OLED 128x64 display and LiPo/Li-Ion battery support with charging in one small package that can be used on a breadboard:

  • Heltec Wifi LoRa 32
  • TTGO LoRa32

These boards come in different versions and there are separate versions for 433/470MHz and 868/915MHz.

LoRa antenna: external, connected via cable with I-PEX connector; 868MHz have 5cm external whip antenna with SMA connector; 433MHz have a helical wire antenna.
WiFi/Bluetooth antenna: single on-board antenna (performance is sub-optimal).
Battery connector: 2-pin Molex PicoBlade (1.25mm spacing). Compatible connectors: ‘JST 1.25mm’ sold on AliExpress and eBay (sold as JST-PH 1.25mm but it is not PH because PH uses 2.0mm spacing).
Be careful with cables that were not included with the board: check first if the colors match the polarity of the board, reversing battery polarity may destroy the board.

There is a dedicated LED (non-programmable) for the battery. It is on when the battery is charged. When no battery is connected: it is off when powered via 3.3V pin but flashes when powered via USB or 5V pin.
A second LED (white on Heltec, blue on TTGO) (programmable) is connected to pin 25, on TTGO V2 the LED is connected to pin 22 but it is useless (see below).

There have been issues with some pigtail cables and some TTGO boards where components were not properly soldered. For more information about these issues check part 1 of this topic.

Note: Sometimes new revisions of boards are released. It is often not be possible to determine the specific revision from the outside of the board. It is possible that a new revision may use different GPIO port(s) for an existing feature. In which case, at first, the board may look defective.
In that case check this article for possible updates and please share your findings when you detect any new changes.

LoRa Performance

The LoRa performance of the Heltec and TTGO boards has shown to be sub-optimal. Important factors are the quality of the RF circuitry (design) and the antennas. The TTGO LoRa32 V2 uses a separate (and shielded) LoRa module which is better than the other models. For a review where the LoRa performance is measured with a spectral analyzer see this ESP32 + LoRa video from Andreas Spiess.

Heltec Wifi LoRa 32

Have a white PCB and come in two different versions (the version numbers are not used by Heltec):

  • V1: with on-board PCB WiFi/Bluetooth antenna. Appears to be available for 433MHz only.
  • V2: with small on-board helical antenna (has a PCB antenna on the bottom but that is not connected).
    Heltec Wifi LoRa 32 pinout diagram.

TTGO LoRa and TTGO LoRa32

Have a black PCB and come in several different versions:

  • LoRa with on-board PCB Wifi/Bluetooth antenna on top. Appears to be available for 433MHz only(?). Also available without the display.

  • LoRa32 V1: with on-board metal Wifi/Bluetooth antenna on bottom. I-Pex connector located on top.

  • LoRa32 V2: with on-board metal Wifi/Bluetooth antenna on bottom (in a different location).
    Uses ESP32-Pico-D4 (with integrated flash memory) instead of ESP32, uses a (shielded) LoRa module, I-Pex connector located on the bottom, micro-USB connector is rotated 90 degrees, in addition has a microSD card slot on the bottom and an on/off switch for the battery next to the micro-USB connector. Switches the battery only so not possible to switch the board off when connected to USB for charging the battery.
    ‘Programmable’ LED on pin 22 instead of pin 25 but useless because wired to SCL and all three LEDs are on the bottom side where you cannot see them. DIO1 and DIO2 each have a separate board pin but neither of them is connected to a GPIO port so must be explicitly wired. This also means that the TTGO V2 has two GPIO ports less that could otherwise have been used for other purposes.
    The microSD card slot can be used as a regular SD card reader/writer. The LoRa modules are HPD13A and HPD14A from HPDTek.
    New updated pinout diagram v3.0 is available here: TTGO LoRa32 V2.0 Pinout v3.0.pdf (2.3 MB)

  • LoRa32 V2.1: Like V2.0 with several changes and improvements (e.g. SMA LoRa antenna connector, different battery charging chip, different switch). Some changes in use of pins / GPIO’s. Different versions of this board exist (some differences in GPIO/pin mappings between versions).
    TTGO LoRa32 V2.1 pinout diagram possibly not up to date. Do not use this pinout for LoRa32 V2.1 with PCB marked V1.6 because it is incompatible.

PIN Mappings

Heltec Wifi LoRa 32, TTGO LoRa and TTGO LoRa32 V1:

ESP32          LoRa (SPI)      Display (I2C)  LED
-----------    ----------      -------------  ------------------
GPIO18 SS      NSS
GPIO14         RST
GPIO26         DIO0
GPIO33         DIO1
GPIO32         DIO2
GPIO15                         SCL
GPIO4                          SDA
GPIO16                         RST
GPIO25                                        Heltec, TTGO LoRa32
GPIO2                                         TTGO LoRa

TTGO LoRa32 V2:

ESP32          LoRa (SPI)      Display (I2C)  LED
-----------    ----------      -------------  ------------------
GPIO18 SS      NSS
EN     RST     RST
GPIO26         DIO0
GPIO33         DIO1 (see #1)
GPIO32         DIO2 (see #2)
GPIO22 SCL                     SCL
GPIO21 SDA                     SDA
GPIO22                                        useless (see #3)
  1. Required (used by LMIC for LoRa).
    Not on-board wired to any GPIO. Must be manually wired.
  2. Optional (used by LMIC for FSK but not for LoRa).
    Not on-board wired to any GPIO. When needed: must be manually wired.
  3. GPIO22 is already used for SCL therefore LED cannot be used without conflicting with I2C and display.

Board definitions

Currently the only board type defined (in ESP32 Arduino Core) is ‘Heltec Wifi LoRa 32’. Select this board type for both Heltec and TTGO boards. Check Pin Mappings above for differences / inconsistencies with a specific board.

Default definitions for board type 'Heltec Wifi LoRa 32':
(Numbers represent GPIO ports)

SCK         =  5
MOSI        = 27
MISO        = 19
SS          = 18
SCL         = 22
SDA         = 21

How to setup the software

How to configure LMIC with the ESP32 pins used for the LoRa module:

//LMIC LoRa module pin configuration

//For Heltec Wifi LoRa 32, TTGO LoRa and TTGO LoRa32 V1 use:
const lmic_pinmap lmic_pins = {
    .nss = 18, 
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 14,
    .dio = {/*dio0*/ 26, /*dio1*/ 33, /*dio2*/ 32}
//For TTGO LoRa32 V2 use:
//Note: LoRa32 V2 DIO1 and DIO2 are not on-board wired to any GPIO.
//These need to be wired manually.

const lmic_pinmap lmic_pins = {
    .nss = 18, 
    .rxtx = LMIC_UNUSED_PIN,
    .rst = LMIC_UNUSED_PIN,
    //If DIO2 is not connected use:
    .dio = {/*dio0*/ 26, /*dio1*/ 33, /*dio2*/ LMIC_UNUSED_PIN} 
    //If DIO2 is connected use:
    //.dio = {/*dio0*/ 26, /*dio1*/ 33, /*dio2*/ 32} 
//For TTGO LoRa32 V2.1:
//The first revision(s) does not have LoRa RST connected to GPIO, use as V2 above.
//Revision V1.5 (V1.5 marked on PCB) uses GPIO12 for LoRa RST.
//Revision(s) newer than V1.5 use GPIO19 for LoRa RST.
//Note: On first revision(s) DIO1 and DIO2 are not on-board wired to any GPIO and have to be wired manually.
//Later revisions may have these wired on-board already.

const lmic_pinmap lmic_pins = {
    .nss = 18, 
    .rxtx = LMIC_UNUSED_PIN,

    //For board revision V1.5 use GPIO12 for LoRa RST
    .rst = 12,
    //For board revision(s) newer than V1.5 use GPIO19 for LoRa RST
    //.rst = 19,

    //If DIO2 is not connected use:
    .dio = {/*dio0*/ 26, /*dio1*/ 33, /*dio2*/ LMIC_UNUSED_PIN} 
    //If DIO2 is connected use:
    //.dio = {/*dio0*/ 26, /*dio1*/ 33, /*dio2*/ 32} 

How to setup U8g2/U8x8 with the ESP32 pins used for the OLED display:

//U8x8 display library configuration
//See U8g2/U8x8 documentation for available display write functions

#include <U8x8lib.h>

//For Heltec Wifi LoRa 32, TTGO LoRa and TTGO LoRa32 V1 use:
U8X8_SSD1306_128X64_NONAME_HW_I2C display(/*rst*/ 16, /*scl*/ 15, /*sda*/ 4);

//For TTGO LoRa32 V2 use:
U8X8_SSD1306_128X64_NONAME_HW_I2C display(/*rst*/ U8X8_PIN_NONE);

//Add to setup():
display.setFont(u8x8_font_victoriamedium8_r);   //Optional, more fonts are available.

Example hardware

Below pictures show an overview of available hardware and their appearance. All pictures have the same size ratio for a realistic comparison.

ESP32 modules / boards

ESP32 modules and boards

LoRa Tranceiver modules

LoRa transceiver modules 690x126

Heltec boards

Heltec boards 1 test 690x368
Heltec boards 2 690x183

TTGO boards

TTGO boards 1 690x236
TTGO boards 1 test 690x384

Smart city sensors
BIG ESP32 / SX127x topic part 1
Connecting bluetooth device to LoRa node
ESP32 Lora 800 + DRAGINO LG01P gateway
3D Printing

great topic start !

(Ezequiel Falcón) #3

Great topic indeed!

I’ve made a question in the previous topic, so I will ask again:
I can’t make my ESP32 to join my TTN gateway, but in ABP mode, the Arduino sketch says EV_TXCOMPLETE… does this means that my module is correctly wired? (I’m using a ESP32 dev kit wired with a HopeRF RFM95W

Thanks in advance!

(T Kroenert) #7

For the TTGO LoRa32 v2.0:


U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(/* clock=/ 22, / data=*/ 21, U8X8_PIN_NONE);
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/rst/ 16) ;


#define SS 18 // ESP32 GPIO18 (Pin18) – SX1276 NSS (Pin19) SPI Chip Select Input
#define MOSI 27 // ESP32 GPIO27 (Pin27) – SX1276 MOSI (Pin18) SPI Data Input
#define MISO 19 // ESP32 GPIO19 (Pin19) – SX1276 MISO (Pin17) SPI Data Output
#define SCK 5 // ESP32 GPIO5 (Pin5) – SX1276 SCK (Pin16) SPI Clock Input
#define RST 14 // ESP32 GPIO14 (Pin14) – SX1276 NRESET (Pin7) Reset Trigger Input
#define DIO0 26 // ESP32 GPIO26 (Pin15) – SX1276 DIO0 (Pin8) used by LMIC for IRQ RX_Done & TX_Done
DIO1 and DIO2 are connected to the pins labeled 11/12 (see pinmapping).

LiPo Charger:

Chargecurrent: 0,35A (measured with USB-“CHARGER-DOCTOR”)
LED (blue): randomly flickers, if no battery is connected. Lights blue during charging.
Charger-IC marked with LTH7 (could be this one: )

On/Off Switch:

disconnects the battery. the board is always powered over usb.
but there is at least a diode in the path: Battery(+) —|>|—switch—LDO

LED (red):

on if powered by usb or battery.

LED (green) programmable:

#define BUILTIN_LED 22
digitalWrite(BUILTIN_LED, LOW); // ON

open issues:

  • which pin is DIO1, DIO2 ?
  • Datasheet / Pinout of the LoRa-module is still unclear (shielded module without text or logo)
  • pinmapping (I have my doubts with the image from Alibaba e.g. SCL/SDA swapped, GPIO35/34, LoRa_RST, …)

Democode and pinmapping (pay attention to the updated versions in the pullrequests !)

edit: outdated informations removed, updates, gitHub link

(Verkehrsrot) #8

Great wrap-up, thank you!

It should be mentioned, at this time, that both boards seem to show up with several quality issues like broken or bad RF path and broken cabling.

For the Heltec boards i can state that they show up with different ESP32 chips in Revision 0 and Revision 1.

I got 4 Heltec boards total so far, from 2 different sellers. 2 boards work fine, 2 have unknown defects causing issues when LoRa packets are sent, and 1 board has broken battery LED (very dim).


indeed… what are the recommended boards @ this moment ?


The LoRa module on the TTGO V2 is very likely from HPDTek:
HPD13A-868S (SX1276) and HPD14A-433S (SX1278).

The layout and pins are compatible with SX127x and HopeRF9x modules. Uses a 4-layer PCB instead of the 2-layer PCB from the HopeRF modules, so the layout will be different (thanks @rocketscream).

The HPD13 (without A, no shield) is discussed in this Rocket Scream article: The SX1276 Modules Shootout

@rocketscream Have you also tested any HPDTek HPD13A modules with the shield?

HPDTek HPD13A-868S module front and back 500x238

(Phang Moh) #11

@bluejedi yes tested. If you look at the range mapping on the map, I added the HPD13A plot too. 4-layer board compared to 2-layer boards of RFM95W and NiceRF SX1276-C1. Surprisingly more or less same range achieved but not sure about other aspect like EMI performance and how much easier to obtain FCC/CE with the shield.


So they are using the standard I2C pins now for the TTGO LoRa32 V2 OLED display.
The SPI pins that you list are the same as for the other boards.

If you use the ‘Heltec Wifi LoRa 32’ board definition the I2C (SCL, SDA), SPI (SCK, MOSI, MISO, SS) and LED (LED_BUILTIN) pins are already correctly defined, no need to redefine them.

I see you that you specified no reset pin for the OLED. While many I2C OLED modules don’t use a reset pin the Heltec boards are using a reset pin for the display (not sure about the other TTGO boards).
I would be surprised if they would have dropped the display reset pin on the TTGO LoRa32 V2.

The display on the TTGO LoRa32 V2 is definitely a SSD1306 128x64 not 128x32.
You should be able to use the following instead:

//U8X8_SSD1306_128X64_NONAME_HW_I2C display([reset [, clock, data]])

//When using Heltec Wifi LoRa 32 board definition and reset on pin 16:
U8X8_SSD1306_128X64_NONAME_HW_I2C display(/*rst*/ 16) ;

//When using Heltec Wifi LoRa 32 board definition without reset:
U8X8_SSD1306_128X64_NONAME_HW_I2C display() ;

@TKroenert Could you verify this so I can add it to the topic start?


From a purely specs based perspective the TTGO LoRa32 V2 because:


  • Uses a known LoRa module instead of a custom configuration.
    Less that can go wrong. The antenna trace looks clean with only a few components.
  • Uses ESP32-Pico-D4 instead of ESP32.
    “ESP32-PICO-D4 integrates all peripheral components seamlessly, including a crystal oscillator, flash, filter capacitors and RF matching links in one single package.” So less that can go wrong.
  • Has an on/off switch.
  • Has a micro-SD card slot (its practical use has yet to be determined).


  • Slightly larger than the the other boards. Not a big issue, but it seems to leave less room on the sides for wires on a breadboard.


  • Quality of the HPDTek LoRa module.
  • Overall quality of the board.
  • How does performance of the WiFi antenna (and its location) compare to Heltec V2?


tnx… there are so many ‘lookalikes’ out there :sunglasses:


A problem on AliExpress and possibly eBay is that sellers show pictures from different boards for one product.
It took me a while before I saw the forest for the trees.
The TTGO LoRa32 V2 is sold by only a few sellers on AliExpress (e.g. Lily GO).


Nice map!

Can you explain that? I only see a much smaller range on the map for the HPD13A (yellow) than for the RFM95W (green) and HPD13 (orange, must enable in menu first). The furthest point that I see for the HPD13A is only 700m from base station.


You may check if your wiring is correct, sometimes tweaking the wires a bit can help (especially on a breadboard). Could be one of the DIO pins, misconfiguration of pins in the software or possibly not having correctly entered the OTAA ID’s/keys (DEVEUI and APPEUI should be in lsb first order, APPKEY in msb first).

(Phang Moh) #18

I think I didn’t manage to complete it on that day because it started to rain heavily. But, from the plots, they are more consistent within that shorter distance.

(T Kroenert) #19

I had to slightly modify your code snippet ( U8X8_PIN_NONE ) but it works with and without the reset pin and in FullHD^W 128x64 :blush: :

//When using Heltec Wifi LoRa 32 board definition and reset on pin 16:
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/rst/ 16) ;

//When using Heltec Wifi LoRa 32 board definition and reset on pin 16:
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/rst/ U8X8_PIN_NONE);

I also found the green onboard LED connected to pin 22 and LOW == ON (!):

#define BUILTIN_LED 22

digitalWrite(BUILTIN_LED, LOW); // ON
digitalWrite(BUILTIN_LED, HIGH); // OFF



You are correct. One has to specify at least one parameter to U8X8_SSD1306_128X64_NONAME_HW_I2C’s constructor (and the first is the reset pin). This appears to be a bug because all constructor parameters have a default value. (I bumped into it before but had forgotten to mention it.)

FYI: BUILTIN_LED is old school. LED_BUILTIN is the new way to go. BUILTIN_LED is (still) supported for backwards compatibility.

FYI: English version of the LTC4054-4.2 Datasheet

(Phang Moh) #21

As pointed out by @LoRaTracker here, I will redo the test when time permits. We should see a significant increase of range on all 4 modules.


(Somehow) contradicts with / is unclear: “LoRa_DIO1 and LoRa_DIO2 (NOT CONNECTED TO GPIO11/GPIO12)” because pin numbers refer to/are GPIO ports.

Do you mean that GPIO11 and GPIO12 are not available as pins, but DIO1 and DIO2 are available as pins instead and DIO1/DIO2 are not connected to GPIO11/GPIO12?

What made you think that DIO1/DIO2 should be connected to GPIO11/GPIO12 (the other boards use GPIO33/GPIO32)?

(Don Hege) #23

Looks like I got the TTGO LoRa32 v1 yesterday. By now I can only say that it has a pretty strong connection if it’s within the same room with the gateway. :joy: Maybe I have some time for a walk through the neighborhood this evening.