Big ESP32 + SX127x topic part 3

A node’s antenna performance is determined by several factors:

  • The RF circuitry and impedance matching on the board.
  • The type, RF characteristics, quality and position of the antenna.
  • If monopole antenna the inclusion of a good ground plane in the design is essential.
  • The quality and characteristics of the antenna cabling and connectors.

A monopole antenna is actually the half of a dipole antenna. The other half is formed by the ground plane. Without a good ground plane a monopole antenna will have suboptimal to bad performance.
A good ground plane is determined by several factors and designing good antennas is not simple.

Often the quality of these (Chinese) quarter-wave-length monopole antennas is not very high and not optimal for the frequency used. Together with the ground plane this has significant impact on the antenna’s performance. Another aspect is that the IPEX/U.FL antenna connectors have a specified lifetime of rather limited number of insertions and removals. These connectors must be inserted and removed with care, but in practice are often handled worse which lowers their quality and lifetime.

Your setup initially lacked a (good) ground plane and you have now added some ground plane, which makes your antenna more like a real dipole. The two halves of true dipoles are normally positioned in the same axis opposite of each other (not in 90 degree angle). For best results a node’s antenna should be positioned upright (which is related to its radiation pattern).

1 Like

Let’s start with a huge thank you for this thread. I have been at it for a few days and need some help. My TTGO LoRa 32 v2 won’t properly join TTN in OTAA. My D1 is jumpered over to pin 33. I was getting the unknown response error so I mapped 20 - EV_JOIN_TXCOMPLETE.

My DeviceEUI and AppEUI were taken from TTN with the ‘lsb’ string showing.

My App Key was entered as is.

My serial monitor shows:
21978561: EV_TXSTART
22862112: EV_TXSTART
23300886: EV_TXSTART

The gateway traffic shows Join Request and Join Accept messages.

Device Data - Application
“time”: “2020-03-03T01:22:36.97466618Z”,
“frequency”: 904.6,
“modulation”: “LORA”,
“data_rate”: “SF8BW500”,
“coding_rate”: “4/5”,
“gateways”: [
“gtw_id”: “eui-b827ebfffe8486bd”,
“timestamp”: 3731584794,
“time”: “”,
“channel”: 8,
“rssi”: -58,
“snr”: 10

Gateway Data - Join Request
“gw_id”: “eui-b827ebfffe8486bd”,
“payload”: “ALSdAtB+1bNwOT14/v+oxWA+GpBa4Cw=”,
“dev_eui”: “60C5A8FFFE783D39”,
“lora”: {
“spreading_factor”: 10,
“bandwidth”: 125,
“air_time”: 370688000
“coding_rate”: “4/5”,
“timestamp”: “2020-03-03T00:17:24.979Z”,
“rssi”: -38,
“snr”: 12.5,
“app_eui”: “70B3D57ED0029DB4”,
“frequency”: 905300000

Gateway Data - Join Accept
“gw_id”: “eui-b827ebfffe8486bd”,
“payload”: “IDkOaXuYgIFoMBlZJAjJNdw=”,
“lora”: {
“spreading_factor”: 10,
“bandwidth”: 500,
“air_time”: 82432000
“coding_rate”: “4/5”,
“timestamp”: “2020-03-03T00:17:28.980Z”,
“frequency”: 927500000

Do I need to configure the Device Downlink information? Any help establishing a connection would be much appreciated.

It may be useful to provide some additional information like:

  • What LoRaWAN library are you using and which version?
    (Based on EV_JOIN_TXCOMPLETE apparently you are using some version of MCCI LoRaWAN LMIC library).

  • Which sketch are you using? Is it one of the standard examples or a custom sketch?

  • Have the pin mappings been set correctly in the sketch? And has this been double checked?
    Also verify that DIO1 is truly wired to GPIO33.
    If pin mapping for DIO1 is set incorrectly, downlink messages will not be received (successfully). When downlink messages cannot be received the node will fail to receive/handle the join accept.

  • Have you double checked the correct format of the keys and ID’s required for OTAA, in the sketch? See: Format of Keys and ID's for Arduino LMIC library [HowTo]

  • What is your region and have you correctly configured the LoRaWAN library for your region?
    (Based on the logs this should be one of the 915MHz regions).

  • Did you follow ‘get the basics working first’ in the topic start? If so did you get uplink message to work correctly when using ABP?

Using OTAA you may try to power up the node and leave it trying to join for 20 minutes or so and at the same time watch the Gateway Traffic on the TTN Console and observe when join requests and join accepts are transmitted, what SF/BW they are using and if it will finally join after multiple join attempts.

@bluejedi Thanks for the quick reply! I have to be super close, just missing a pin number or a check mark somewhere in the gateway or ttn config.

Using the MCCI LoRaWAN LMIC library version 3.1.0.

Using the ttn-otaa.ino sketch from the library examples.

I added a case to the event handler switch to catch the EV_JOIN_TXCOMPLETE
Previously that was giving an unknown event error : 20

DIO1 is indeed wired to GPIO33

My pin mapping is:
const lmic_pinmap lmic_pins = {
.nss = 18,
.rst = 14,
.dio = {26, 33, LMIC_UNUSED_PIN},

My keys are entered as (not sure if they are secret):
DEVEUI = { 0xF7, 0x61, 0xXX, 0xXX, 0xXX, 0xXX, 0xED, 0x00 };
APPEUI = { 0x8B, 0xB9, 0xXX, 0xXX, 0xXX, 0xXX, 0xB3, 0x70 };
APPKEY = { 0xDB, 0xFB, 0x38, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0x23, 0xA0, 0x19, 0xDE };

My lmic_project_config:
// project-specific definitions
#define CFG_us915 1
#define CFG_sx1276_radio 1

With a long soak doing OTAA the device still doesn’t connect.

When using ABP I get see the following in the serial monitor:
Packet queued
140332: EV_TXCOMPLETE (includes waiting for RX windows)
3890356: EV_TXSTART

I’m interested in what the gateway traffic log looks like the first 15 to 20 minutes from the moment just before the node is powered on.

I would expect to see multiple join requests (‘retries’) with longer pauses in between.

I’m only familiar with eu868 so I’m not sure how these retries will occur on 915MHz and on what SF (sequence).

(The keys/IDs should be treated as secrets, not as public.)

Prior to powering up my node, there is no gateway traffic. I would hope all the data is the same regardless of frequency.

Are there settings I should be making in my gateway to play nice with TTN or do you think this is a Node problem? I am using the rak7246 and have followed the Setup Guide

Should I make edits to the Edit packet-forwarder config?

This is related to the join process only. If the node is unable to join at a lower spreading factor/higher data rate, then it normally will try at a higher spreading factor with lower data rate which can reach more far. That is at least LMIC’s behavior for eu868.
In your case the gateway is near but it is still interesting to see what exactly happens in the first 15 to 0 minutes after powering on the node.

The minimal distance between node and gateway should be 3m at minimum. If not this can have impact on proper operation. So if the distance between your node and gateways is less than 3m, you could try to increase the distance.

As said, I’m not sure how the join retry sequence for us915 should exactly behave when the first join attempt(s) fail.

“OTAA doesn’t work” won’t give any hints of what could possibly go wrong. Some possible causes are mentioned above already. For further analysis additional information is preferred, like the traffic log of those first 15 to 20 minutes.

That depends on the steps in the setup guide and RAK’s installer software.
For proper configuration of your gateway I suggest to search the forum for relevant topics/threads for the RAK7246 (not this thread).

It will be useful to test if the gateway is working correctly. Maybe you can check it with a different node which is known to be working correctly and/or try your node with a gateway that is known to be working correctly.

Yes, that bug in ttn-otaa.ino has not yet been fixed unfortunately.

According to issue 487 this should have been fixed in v3.1.0 already but it appears that ttn-otaa.ino was forgotten in the fix.

Turns out my issues were in the gateway configuration. I am able to join with my RAK811s and my ESP32s. Now it is time to write some apps.

More info here:

TTGO LoRa V1.3 (is actually TTGO LoRa32 V1.3?)

I noticed a (relatively) new board: TTGO LoRa V1.3
It appears to be an upgraded version of TTGO LoRa32 V1 but the ‘32’ has been removed from its name. I’m not aware if there have been any changes in pin layout.

Comparison between Lora V1.3 and Lora V1.0 (source: LilyGO):

  1. Product low power design
  2. Optimize LORA RF circuit
  3. Add battery voltage detection Pin IO35

The board is labeled LORA_V1.3, 20190614.
Dated June 2019 so V1.x boards apparently are still manufactured.
I wonder why they are still producing the V1.x series boards because its WiFi antenna is located inefficiently and the board was already superseded by the V2.x series.
Why an improved V1.0 and not an improved V2.0 instead? Because V1.x has more available GPIOs and almost nobody is using the compact flash slot of the V2.0?

TTGO LoRa V1.3

Unfortunately LilyGO again adds confusion with the name of this new board:
The original TTGO LoRa is SX1278 based and not available for 868/915MHz. The TTGO LoRa32 V1 and V2.x models are SX1276 based and are available in models for 433MHz and 868/915MHz.
LilyGO has recently introduced the TTGO LoRa V1.3 which is SX1276 based. This appears to be an upgraded TTGO LoRa32 V1 so it actually is ‘TTGO LoRa32 V1.3’ (with ‘32’ in the name). Why this naming inconsistency and confusion?

TTGO LoRaxx models currently available in LilyGO’s shop on AliExpress:

  • TTGO LoRa V1 (SX1278 based)
  • TTGO LoRa32 V1 - they don’t show ‘V1’ in the descriptions
  • TTGO LoRa V1.3 - be aware that this is actually a TTGO LoRa32 V1.3 (SX1276 based)
  • TTGO LoRa32 V2.0 with Compact Flash slot (CF)
  • TTGO LoRa32 V2.1 release 1.6 (aka V2.1.6) with CF and SMA connector for the LoRa antenna

If you are interested in one of these boards, take care that you order the correct model and version and for the correct frequency band (LilyGO has not made it easy with their naming).

1 Like

two paxcounter users complained for a “TTGO V1” board LMIC is running only when DIO2 pin is set to GPIO32.

With LMIC DIO2 should be relevant for FSK only, not for LoRa modulation. Thus, i’m wondering what happened here.

That’s rather cyptic and could mean several boards.

TTGO LoRa (V1) and TTGO LoRa32 V1 have DIO2 hard wired to GPIO32 so there is nothing wrong in mapping it in LMIC but indeed should be relevant for FSK only and not for LoRa.

1 Like

@Verkehrsrot I noticed your PR for Lopy and Lopy4 support for arduino-esp32.
In pins_arduino.h it is noted that LoRa DIO0, DIO1 and DIO2 are are all wired via diode to a single GPIO (GPIO23).

Does this require any changes to the LMIC library source code to work or does it require any special settings other than specifying the same GPIO for DIO0, DIO1 and DIO2?
Will this work with both classic ‘LMIC-Arduino’ and ‘MCCI LoRaWAN LMIC library’ ?

Are there any other attention points for Lopy and Lopy4 development with C++ and LMIC?

That’s exactly what i thought. Thanks for confirmation.

I can confirm that paxcounter code runs on LoPy4 with ‘MCCI LoRaWAN LMIC library’ with settings from pins_arduino.h (of arduino-esp32) and additional setting

#define LORA_RST LMIC_UNUSED_PIN // reset pin of lora chip is not wired on LoPy4

1 Like

Thanks. I already noted that on Lopy4 LoRa Reset is not connected to a GPIO (but is on Lopy) and this should indeed be configured in the pin mappings.

So if I understand correctly using LMIC with Lopy4 requires the following settings:

  • LMIC Pin Mappings:
    // Set LoRa module pin mappings:
    const lmic_pinmap lmic_pins = {
      .nss = LORA_CS,
      .rxtx = LMIC_UNUSED_PIN,
      .rst = LMIC_UNUSED_PIN,
      .dio = { LORA_IRQ, LORA_IRQ, LORA_IRQ }
  • Add to setup() explicit initializion of the standard SPI instance:
    Because the standard SPI pins are defined for different GPIOs than the GPIOs used for the SX1276 SPI interface and because LMIC can only use the standard SPI instance (which by default uses the standard SPI pins).
    // In setup, before initializing the LMIC library initialize SPI with:

Pycom is not very clear about the SX1276 connections in their Lopy4 specification sheet and pinout diagram. Apparently they do not like to see the boards getting used with other LoRaWAN libraries and languages other than Python, probably because using a different runtime environment will invalidate the board’s LoRaWAN certification.

1 Like

I’m using this code for paxcounter:

class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {



  // set SPI pins to board configuration, pins may come from pins_arduino.h

  virtual void begin(void) override {



  // virtual void end(void) override

  // virtual ostime_t setModuleActive(bool state) override


static MyHalConfig_t myHalConfig{};

// LMIC pin mapping for Hope RFM95 / HPDtek HPD13A transceivers

static const lmic_pinmap myPinmap = {

    .nss = LORA_CS,

    .rxtx = LMIC_UNUSED_PIN,


    .dio = {LORA_IRQ, LORA_IO1,

            LORA_IO2 == NOT_A_PIN ? LMIC_UNUSED_PIN : LORA_IO2},

    .rxtx_rx_active = LMIC_UNUSED_PIN,

    .rssi_cal = 10,

    .spi_freq = 8000000, // 8MHz

    .pConfig = &myHalConfig};

// setup LMIC stack

  os_init_ex(&myPinmap); // initialize lmic run-time environment
1 Like

I have the LoPy4 working with LMIC now.

My experiences with LoPy4:

The board is well designed but is unsuitable as a development board for C++ development:

  • There is no USB port so uploading firmware requires a separate USB to serial adapter. This lacks the convenience of automatic firmware upload and automatic reset after upload.
    Pycom has several extension boards that add a USB port and serial to USB adapter but they do not solve the issue and also do not provide auto upload and auto reset (not with standard ESP32 tooling at least).

  • Firmware upload via serial port requires a GPIO0 and Reset sequence to put the ESP32 in firmware download mode but the Lopy4 only has a reset button. This makes firmware uploading very impractical because GPIO0 must be manually wired to ground before each upload and disconnected before manual reset after firmware upload.

  • Firmware upload therefore requires at least use of a breadboard or Pycom’s Expansion Board.
    The Expansion Board has a user button but it is not connected to GPIO0 so it still requires to do the wiring ceremony for each firmware upgrade.

  • The pins of the LoPy4 are (about 25%) shorter than normal and so are the female connectors on the Expansion Board. Dupont connectors do not fit well in the female connectors on the Expansion Board. The male cable connectors do not go all in and are wobbly. This is not a pleasant experience and it does not feel reliable.

  • Only one of the available extension boards (the ‘Expansion Board’) has (half-high female Dupont) connectors for accessing the LoPy4 pins (e.g. GPIO0 and GND). Firmware upload is not possible with the other extension boards (which renders them useless for C++ development).

The firmware upload issues do not exist when programming the LoPy4 with Python (for which the board is designed) because that uses a different way of uploading code to the board. The Python code is interpreted at runtime instead of being compiled before upload.
The short pins (Expansion Board) issue also exist when developing in Python however.

That’s right, i ran into the same issue. But if it’s possible to autoflash the board with the original python code / bootloader, it should be possible to enhance to do the same?

Yes that should be possible.

It is possible to flash new device firmware to the LoPy4 with a Pysense, Pytrack, Pyscan or ‘Expansion Board V3.x’ automatically without doing the manual ‘wiring ceremony’.
I had not reflashed the Python device firmware before so I didn’t know that was possible.

I noticed that they use a PIC16LF1459 MCU as USB to serial controller on the extension boards, which has its own firmware. The Pycom Firmware Update tool probably communicates with the PIC to upload firmware to the ESP32. The GPIO0/Reset sequence will have to be generated by the PIC which then automatically puts the ESP32 in firmware download mode.

So yes technically it should be possible to enhance the esptool to automatically upload firmware to a LoPy4 (and other Pycom boards) with a Pycom extension board, but you need to know how to instruct the PIC controller firmware to do this. This may either be simple or more complex.

1 Like