You can try https://github.com/fantasticdonkey/uLoRa .
Only ABP is supported.
Heltec Wifi LoRa 32 V2 - I2C issues
While checking the board’s pinout diagram and its pin definitions (defined in the ESP32 Arduino Core) I noticed that the default SDA and SCL (I2C) pins are defined incorrectly which can cause problems.
This is explained below.
ESP32 by default uses GPIO21 and GPIO22 pins for I2C but also has the possibility to remap the I2C interface to different pins. Heltec Wifi Lora 32 V2 does not use the standard I2C pins for its OLED display and uses GPIO4 and GPIO15 instead. The values of SDA and SCL should be defined correspondingly but they are not. The values of SDA and SCL are incorrect.
SDA and SCL are defined as pin 21 (GPIO21) and pin 22 (GPIO22), which is common for ESP32.
But for connecting the display they used pins GPIO4 and GPIO15 instead.
Vext (which is actually ‘Vext control’) controls (enables/disables) Vext external power.
Like SDA, Vext is defined as GPIO21 which is weird because it conflicts with SDA.
The following is defined in the board’s pins_arduino.h
file (part of ESP32 Arduino Core):
static const uint8_t SDA = 21; /* CONFLICT! */
static const uint8_t SCL = 22;
static const uint8_t SDA_OLED = 4;
static const uint8_t SCL_OLED = 15;
static const uint8_t Vext = 21; /* CONFLICT! */
When using the Arduino Wire (I2C) library, the ‘Wire’ object (which controls the I2C hardware interface) is initialized with Wire.begin()
. Without parameters, this will initialize the I2C interface using the pins defined by SDA and SCL. To use different pins for I2C, the pins have to be explicitly specified: Wire.begin(sda_pin, scl_pin)
.
Vext and SDA are mutually exclusive. One GPIO cannot be used to control both Vext external power and SDA at the same time, but unfortunately that is how the pins are defined! The values of SDA and SCL cannot be changed in application code because they are defined in the ESP32 Arduino Core as const int
.
During I2C communication the SDA and SCL interface pins will switch between HIGH/LOW with a frequency of 100+ kHz. If GPIO21 is used for SDA then Vext power will also switch with 100+ kHz accordingly. This is not good and the Vext voltage regulator is not designed for that.
Therefore GPIO21 must not be used for SDA but unfortunately that is exactly what happens if Wire.begin() is called without parameters.
To use pins GPIO4 and GPIO15 for I2C instead (which is how the on-board display is wired) use:
Wire.begin(/*sda*/ 4, /*scl*/ 15);
Note:
The ESP32 Wire library will remember the sda_pin and scl_pin parameters that were specified in the first Wire.begin(…) call. If any 3rd-party library later calls Wire.begin() (without parameters) that luckily does not cause the pins used for I2C to be reset to the default SDA and SCL pins.
Wire.begin(sda_pin, scl_pin)
must be called before calling any third-party library initialization code (e.g. bme280.begin()
).
The ESP32 supports two separate I2C hardware interfaces. The second interface is accessible via the Wire1 object which can be initialized as follows:
Wire1.begin(alternate_sda_pin, alternate_scl_pin)
I2C is a shared bus that can be shared by many peripherals/sensors. In most cases a single I2C interface will be sufficient and the second I2C bus will not be needed.
About calling Wire.begin() from within third party library code
The I2C interface is a shared bus that can be used by many peripherals. Different types of peripherals will require different (third party) libraries. Initializing a shared bus is therefore the responsibility of the application and not the responsibility of third party libraries, which should therefore not try to initialize it (i.e. should not call Wire.begin()
).
In the early Arduino days only Atmel 8-bit MCU’s were supported. These only had a single I2C interface on fixed pins. But when Arduino matured, the framework was ported to other MCU architectures like ESP32 which supports 2 hardware I2C interfaces that can be mapped to different pins. If third party libraries then call Wire.begin() without parameters this can introduce problems.
Unfortunately, many libraries (including from Adafruit) call Wire.begin() (without parameters) from library code and do not provide a mechanism for specifying which pins to use for I2C so they will always use the pins defined by SDA and SCL - unless the application initializes the Wire object (I2C interface) first. If the real (mapped) I2C pins are different from what is defined by SDA and SCL the application has to call Wire.begin(sda_pin, scl_pin)
before any third party library initialization code is called.
@chote yeah know you have an good ground to this antenna.
The most important thing is a ground plane to the antenna and only the SMA connector makes this not.
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).
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
22360457: EV_JOIN_TXCOMPLETE
22862112: EV_TXSTART
23265406: EV_JOIN_TXCOMPLETE
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,
.rxtx = LMIC_UNUSED_PIN,
.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):
- Product low power design
- Optimize LORA RF circuit
- 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?
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).
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.
@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
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:
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
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.
I’m using this code for paxcounter:
class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {
public:
MyHalConfig_t(){};
// set SPI pins to board configuration, pins may come from pins_arduino.h
virtual void begin(void) override {
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
}
// 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,
.rst = LORA_RST == NOT_A_PIN ? LMIC_UNUSED_PIN : LORA_RST,
.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