Heltec LoRa 32 V3 nightmares

Heltec LoRa 32 V3 in the Arduino 2.0.3 environment has been a nightmare. I did a fresh install of the IDE then added only the latest (0.0.7 & 1.1.1) board manger file and library for this board.

I cannot compile anything with bluetooth all though all of the includes seem to be ok.

C:\Users\f.iorio\AppData\Local\Temp.arduinoIDE-unsaved20221129-15832-18qh65.3sa0t\SerialToSerialBT\SerialToSerialBT.ino:14:2: error: #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
*** #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.***
*** ^~~~~***

exit status 1

Compilation error: #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.

Then, the reason I purchased this board, LoRa, any basic examples with that gets hung on a call to Lora.endPacket(), searching for a solution is crazy. I tried changing the I2C speed to no avail.

Anyone have experience with this board? Thanks


V3 is a chip of S3, which is not supported in this example. You can try another Bluetooth example.

Welcome to hell !! There are so many wrong things about this board that I had to spend 2 full days just to make it work.

So let´s fix it. If you, as I am, is using Arduino Core 2.0.6 for ESP32-S3 form Espressif listed at:


Then the good thing is that the new Heltec WiFi LoRa 32(V3) board is now listed, the bad thing is that there are errors in the definition files.

On your core installation file: …\portable\packages\esp32\hardware\esp32\2.0.6\boards.txt, at line 11.800 replace/correct the following lines




At line 11.911 comment the line as follows:


Now at file:


Add/replace the following definitions:

static const uint8_t RST_OLED = 21;
static const uint8_t SCL_OLED = 18;
static const uint8_t SDA_OLED = 17;

By the following:

static const uint8_t SDA_OLED = 17;
static const uint8_t SCL_OLED = 18;
static const uint8_t RST_OLED = 21;

static const int8_t SW_LoRa = -1;
static const uint8_t SS_LoRa = 8;
static const uint8_t SCK_LoRa = 9;
static const uint8_t MOSI_LoRa = 10;
static const uint8_t MISO_LoRa = 11;
static const uint8_t RST_LoRa = 12;
static const uint8_t BUSY_LoRa = 13;
static const uint8_t DIO1_LoRa = 14;

It is also recommended to redefine Arduino default SPI-1 and I2C-1 pins to OLED & LoRa pins as follow:

static const uint8_t SDA = 17; // instead of 8;
static const uint8_t SCL = 18; // instead of 9;

static const uint8_t SS = 8; // instead of 10;
static const uint8_t MOSI = 10; // instead of 11;
static const uint8_t MISO = 11; // instead of 13;
static const uint8_t SCK = 9; // instead of 12;

The Heltec V3 at https://heltec.org/project/wifi-lora-32-v3/ @ “Docs & Resources”, AKA “Heltec_ESP32-master” DOES NOT correctly #define the V3 board, one must search & replace the following lines:

#if defined( WIFI_LoRa_32 ) || defined( WIFI_LoRa_32_V2 ) || defined( Wireless_Stick )


#if defined( WIFI_LoRa_32 ) || defined( WIFI_LoRa_32_V2 ) || defined( WIFI_LoRa_32_V3 ) || defined( Wireless_Stick )

This changes will make the OLED to work but DO NOT work with the new LoRa SX1262 module to work as the current provided Helte LoRa library only works with the old V2 LoRa SX1276/78 module, therefore I strongly recommend you to switch to excellent multi module LoRa library from “StuartsProjects” at:

Now you can use you new V3 SX1262 module as easy as:

#include <SPI.h>
#include <SX126XLT.h>


SPI.begin(SCK_LoRa, MISO_LoRa, MOSI_LoRa, SS_LoRa);

LT.begin(SS_LoRa, RST_LoRa, BUSY_LoRa, DIO1_LoRa, SW_LoRa, DEVICE_SX1262);

Same goes for the OLED display which is the same as in the V2 board but connected to:

SDA_OLED = 17; SCL_OLED = 18; RST_OLED = 21;


Thanks @macedo123 this works great. What should I use for deep sleep. I’m only getting 1ma in deep sleep for this sketch, where using the Heltec library on the V2 I could get 10ua.

#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds /
#define TIME_TO_SLEEP 5 /
Time ESP32 will go to sleep (in seconds) */

RTC_DATA_ATTR int bootCount = 0;

Method to print the reason by which ESP32
has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;

wakeup_reason = esp_sleep_get_wakeup_cause();

case ESP_SLEEP_WAKEUP_EXT0 : Serial.println(“Wakeup caused by external signal using RTC_IO”); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println(“Wakeup caused by external signal using RTC_CNTL”); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println(“Wakeup caused by timer”); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println(“Wakeup caused by touchpad”); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println(“Wakeup caused by ULP program”); break;
default : Serial.printf(“Wakeup was not caused by deep sleep: %d\n”,wakeup_reason); break;

void setup(){
delay(1000); //Take some time to open up the Serial Monitor

//Increment boot number and print it every reboot
Serial.println("Boot number: " + String(bootCount));

//Print the wakeup reason for ESP32

First we configure the wake up source
We set our ESP32 to wake up every 5 seconds
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println(“Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
" Seconds”);

Next we decide what all peripherals to shut down/keep on
By default, ESP32 will automatically power down the peripherals
not needed by the wakeup source, but if you want to be a poweruser
this is for you. Read in detail at the API docs
Left the line commented as an example of how to configure peripherals.
The line below turns off all RTC peripherals in deep sleep.
//esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
//Serial.println(“Configured all RTC Peripherals to be powered down in sleep”);

Now that we have setup a wake cause and if needed setup the
peripherals state in deep sleep, we can now start going to
deep sleep.
In the case that no wake up sources were provided but deep
sleep was started, it will sleep forever unless hardware
reset occurs.
Serial.println(“Going to sleep now”);
Serial.println(“This will never be printed”);

void loop(){
//This is not going to be called

My best guess is that OLED is being kept energized by Vext (kind of impossible, but who knows) and/or LoRa antenna SW (DIO2) and/or LoRa module itself (wich is directly powered by 3.3V) may be the cuplrit of this consumption. You may try to explicitly turning them off/sleep before ESP32 sleep and check if it helps, I am not sure at all, I rarely use sleep in my applications.

ill give it a go. to turn DIO2 off just do
digitalWrite(DIO2, LOW); ?
I don’t have any OLED’s so guessing it is the lora module.

The SX126x antenna module is controled by its DIO2 pin, however the correspondent ESP32 pin is not defined at the diagram neither in the arduino pins file so I do not know how Heletec wired it, you may try to use the above Stuart library (setMode(MODE_SLEEP)) to put the LoRa SX126x to sleep just after boot as the module migth be in stand-by after power-on as reported by other users of this module. The SX1276, used on the V2 board, did not behave this way going to deep sleep by itself just after boot. But be aware, I did not tested any of this theories.

Is there an update of this guidance with using Arduino Core 2.0.7? I’m just starting to use these Heltec Lora 32 V3 boards and running into the various issues that have been mentioned here and a few other posts. I’m using Arduino IDE 2.0.4. It appears the 2.0.7 Arduino Core version has corrected the boards.txt file as mentioned above and changed the arduino.h file though not exactly in the same way. Is there a new recipe or does 2.0.7 fix it all?
Unlike the original nightmares, I’m at least able to upload a very simple sketch. I’ve gotten the simple chipID sketch in the examples to work and my own very simple wifi connection example to work.

The LoRa examples though are giving me the run around. Are all the Heltec LoRa examples useless for the V3? For me, at first they wouldn’t compile. Then they compiled when I placed #define WIFI_LoRa_32 a head of the #include “heltec.h” statement in the WiF-_Lora_32FactoryTest example sketch. The resulting compiled sketch would upload but continually crashed during execution. As I try to debug that, for some reason now I can’t get them to compile again. Can someone provide a hint or should the examples not be used?

I’m but not sure where best to turn next. I’m guessing over to the SturartsProjects??. Ironically I chose to start my LoRa journey with heltec because of all the examples, just my luck I picked to start during the V2 to V3 transition.

On the LoRa front, if there’s an #include “Heltec.h” statement in the sketch, it’s the wrong version. The only includes in the correct WiFi_LoRa_32_V3_FactoryTest.ino sketch are:

#include “Arduino.h”
#include “WiFi.h”
#include “images.h”
#include “LoRaWan_APP.h”
#include <Wire.h>
#include “HT_SSD1306Wire.h”

Note that the V3 modules use a different LoRa Node chip (SX1262 vs the old SX127x) and none of the old [WiFi LoRa 32] LoRa support libraries support this new chip—it’s the same as the one used in the CubeCells, so the radio is now set up the way that it is on the CubeCell boards.

The situation is better with Arduino Core 2.0.7 but it does not fix all the problems yet.

2.0.7 contained updated board definitions. And if you are using platformio you can use the board heltec_wifi_lora_32_V3. But there are still some updates to the arduino core pin definitions here, and there are updates needed to the heltec library here. Until those are merged, it won’t be possible to #include "heltec.h". I documented my findings here.

Even with those changes, LoRa has a totally different chip, and will need to use another library such as radiolib or the StuartsProjects one.

Thanks UniquePete and platypii. Looks like I have some work cut out for me.

For folks who search and find their way here…I solved my ‘get something’ going problem by using the RadioLib by jgromes. It doesn’t get me the “factory” sketch going but it does have me doing LoRa transmitting and receiving on these V3 boards now. Nice thing is their example has a simple pin override line so you avoid some of the concern with finding the correct pin definitions. I simply used SX1262 radio = new Module(8, 14, 12, 13); and I was up and running. Still looking forward for Heltec examples to work, but at least I can play a bit with LoRa.


Deleted question…Seems my latest problem is my router not the device.

Thank you to mostly everyone that posted in this thread. You have helped me and saved me quite some time to get my recently acquired V3 stick running.
I was also able to get it working with my older V2 sticks. I use the sandeep mistry lora library for those devices and the mentioned RadioLib for the V3 stick.

Assuming you did not change the default settings on your V2 Stick with the mentioned library, I used the following settings on the V3 Stick with RadioLib, to get communication working. (Its just a very simple message I have to send, so I do not use any LoRaWan or similar stuff)

  int state = lora.begin(866.0,125.0,7,5,0x12,10,8,1.6,false);

This is for for european frequency. To get an explanation for the other parts, see SX1262.h:

\brief Initialization method for LoRa modem.
  \param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
  \param bw LoRa bandwidth in kHz. Defaults to 125.0 kHz.
  \param sf LoRa spreading factor. Defaults to 9.
  \param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
  \param syncWord 1-byte LoRa sync word. Defaults to RADIOLIB_SX126X_SYNC_WORD_PRIVATE (0x12).
  \param power Output power in dBm. Defaults to 10 dBm.
  \param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
  \param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
  \param useRegulatorLDO Whether to use only LDO regulator (true) or DC-DC regulator (false). Defaults to false.

begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);

I hope this helps someone with the same problem.