Skip to content

Board/heltec wifi lora 32 v3 #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/ble_serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@

#include "Arduino.h"
#include "Stream.h"

#ifdef USE_NIMBLE
#include <NimBLEDevice.h>
#include <NimBLELog.h>
#else
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <DebugLog.h>
#endif



#define SERVICE_UUID "00000001-ba2a-46c9-ae49-01b0961f68bb" // KISS service UUID
#define CHARACTERISTIC_UUID_TX "00000003-ba2a-46c9-ae49-01b0961f68bb"
Expand All @@ -46,9 +54,15 @@ class BLESerial: public Stream

private:
String local_name;
#ifdef USE_NIMBLE
NimBLEServer *pServer = NULL;
NimBLEService *pService;
NimBLECharacteristic * pTxCharacteristic;
#else
BLEServer *pServer = NULL;
BLEService *pService;
BLECharacteristic * pTxCharacteristic;
#endif
bool deviceConnected = false;
uint8_t txValue = 0;

Expand Down
42 changes: 35 additions & 7 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@

// Uncomment for SX126X module usage
// #define USE_SX126X
// #define WIFI_LoRa_32_V3

// Check your module name at https://github.com/jgromes/RadioLib/wiki/Modules
#ifdef USE_SX126X
#define MODULE_NAME SX1268
#ifdef WIFI_LoRa_32_V3
#define MODULE_NAME SX1262
#else
#define MODULE_NAME SX1268
#endif
#else
#define MODULE_NAME SX1278
#endif
Expand All @@ -25,6 +30,22 @@
#define CFG_IS_CLIENT_MODE true // false - server mode (APRS-IS gate mode)
#endif

// Support for heltec_wifi_lora_32_V3 board
// https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_wireless_stick_lite_v3/pins_arduino.h
//static const uint8_t RST_LoRa = 12;
//static const uint8_t BUSY_LoRa = 13;
//static const uint8_t DIO1 = 14;



#ifdef WIFI_LoRa_32_V3
#define LORA_RST RST_LoRa //OK
#define LORA_IRQ 14
#define LED_BUILTIN 35
#define BUILTIN_LED 35
#endif


// change pinouts if not defined through native board LORA_* definitions
#ifndef LORA_RST
#pragma message("LoRa pin definitions are not found, redefining...")
Expand All @@ -33,13 +54,20 @@
#endif

// LoRa pinouts
#define CFG_LORA_PIN_SS SS
#define CFG_LORA_PIN_RST LORA_RST
#define CFG_LORA_PIN_A LORA_IRQ // (sx127x - dio0, sx126x/sx128x - dio1)
#ifdef USE_SX126X
#define CFG_LORA_PIN_B 14 // (sx127x - dio1, sx126x/sx128x - busy)
#define CFG_LORA_PIN_RXEN 32 // (sx127x - unused, sx126x - RXEN pin number)
#define CFG_LORA_PIN_TXEN 33 // (sx127x - unused, sx126x - TXEN pin number)
#ifdef WIFI_LoRa_32_V3
Copy link
Owner

@sh123 sh123 Mar 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would refactor to pass all device specific configuration parameters from platformio.ini to avoid ifdefs, it could easily become a mess in the future when will need to add more boards.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good Idea! I won't to break your project with my PR.

Copy link
Owner

@sh123 sh123 Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, so no need to add #ifdef WIFI_LoRa_32_V3, instead just pass required board specific defines through platformio.ini and for default values add #ifndef check, so they will be set to default values if not passed from outside, for example

#ifndef CFG_LORA_PIN_B
#define CFG_LORA_PIN_B    14 
#endif

This way if new board will be added there won't be any need to add additonal if blocks, but rather define different set of pinouts in platformio.ini.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will fix on next commit, I want to see your "small refactoring" commit before. During these bank holidays I've spent time to performed tests with 2 devices (heltec wireless stick lite v3) and 2 phones (android 11 and android 15) and with my last commit on my branch it works!
Do you have seen this project: https://github.com/nakhonthai/ESP32APRS_LoRa
This firmware is similar to yours ant it has a lot of features (save setup on flash, web interface, modem/gate runtime setup) and supports many board .. adding KISS command Extensions and BLE (I've to check..seems support only classic BT) it should be used with codec2talkie. What you think about?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there will be other compatible true KISS AX.25 APRS lora devices usable with codec2talkie or aprsdroid or perhaps linux ax25 tools it will be really nice. In this project I'm focusing on headless modem without controls, which is usable with the phone. Having separate device with controls is nice, too, but GUI and controls are limited.

Copy link
Owner

@sh123 sh123 Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And about "small refactoring", there is no much to do, you can just augment variables, which are passed from platform io with #ifndef, block, so that they will not be set to default values if passed from outside for your board and that's it, this way it will be possible to add new boards without code modification, but purely from platformio.ini file. When it is there, I'll just click "merge" and that's it.

#define CFG_LORA_PIN_B BUSY_LoRa
#define CFG_LORA_PIN_RXEN RADIOLIB_NC // (sx1262 unused)
#define CFG_LORA_PIN_TXEN RADIOLIB_NC // (sx1262 unused)
#define CFG_LORA_PIN_SS 8 // NSS_LoRa
#else
#define CFG_LORA_PIN_B 14 // (sx127x - dio1, sx126x/sx128x - busy)
#define CFG_LORA_PIN_RXEN 32 // (sx127x - unused, sx126x - RXEN pin number)
#define CFG_LORA_PIN_TXEN 33 // (sx127x - unused, sx126x - TXEN pin number)
#define CFG_LORA_PIN_SS SS
#endif
#else
#define CFG_LORA_PIN_B RADIOLIB_NC
#define CFG_LORA_PIN_RXEN RADIOLIB_NC
Expand Down Expand Up @@ -90,13 +118,13 @@

// Bluetooth
#define CFG_BT_NAME "loraprs" // set to empty to disable Bluetooth
#define CFG_BT_USE_BLE false // set to true to use bluetooth low energy (for ios devices)
#define CFG_BT_USE_BLE true // set to true to use bluetooth low energy (for ios devices)
Copy link
Owner

@sh123 sh123 Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be passed from platfromio.ini, but here it needs to be defined as

#ifndef CFG_BT_USE_BLE
#define CFG_BT_USE_BLE false
#endif


// USB serial
#define CFG_USB_SERIAL_ENABLE false // true - enable KISS communication over USB Serial (e.g. with APRSDroid over USB-OTG), disables USB logging

// KISS protocol options
#define CFG_KISS_EXTENSIONS false // true - enable modem control from application with KISS commands and signal reports
#define CFG_KISS_EXTENSIONS true // true - enable modem control from application with KISS commands and signal reports
#define CFG_KISS_TCP_IP false // true - run as KISS TCP/IP server, no bluetooth operations performed

// APRS-IS options, valid in when CFG_IS_CLIENT_MODE = false
Expand Down
4 changes: 4 additions & 0 deletions include/loraprs_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
#include <endian.h>
#include <arduino-timer.h>

#ifndef USE_NIMBLE
#include "BluetoothSerial.h"
#endif
#include "ble_serial.h"
#include "ax25_payload.h"
#include "kiss_processor.h"
Expand Down Expand Up @@ -187,7 +189,9 @@ class Service : virtual public Kiss::Processor
std::shared_ptr<MODULE_NAME> rig_;

// bluetooth, wifi
#ifndef USE_NIMBLE
BluetoothSerial serialBt_;
#endif
BLESerial serialBLE_;
WiFiClient aprsisConnection_;

Expand Down
42 changes: 42 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,83 @@ lib_deps =
contrem/arduino-timer @ 3.0.1
jgromes/RadioLib @ 6.2.0
rlogiacco/CircularBuffer @ 1.3.3
h2zero/NimBLE-Arduino @1.4.1

check_tool = cppcheck
check_flags =
cppcheck: --suppress=*:*.pio\* --inline-suppr -DCPPCHECK
check_skip_packages = yes

[env:esp32dev_sx126x_modem]
lib_ignore =
NimBLE-Arduino
Copy link
Owner

@sh123 sh123 Mar 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it makes sense to switch all project to NimBLEDevice library instead of having lots of ifdefs?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's yor choice. If you won't support old mobile devices who does't support BLE, it has sense. Take in account that codec2_talkie app work on android 11 until v1.71, it means that old phone with no BLE (and probably with android < 11) can't run app.
I think that support of Android 11 (last version with kenel 3.10 than is possible to find custom rom) is important to re-use old phones for HAM-radio purpose (sorry for OT).

Copy link
Owner

@sh123 sh123 Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codec2 talkie should run since Android 7.0 (API 24 or higher), target SDK is not the same as minimum supported version, if you are getting "App is not installed" error you need to uninstall previous version before installing new one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've uninstalled previous, installed new -> App is not installed, I've tried again -> App installed. It's a strange behavior.

Copy link
Owner

@sh123 sh123 Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started publishing release binaries built from Android git workflow, they are signed with different set of keys from some point and built on github machines, also previously there was debug version, it also might cause this issue. In this case installation over previous version is not possible and need to uninstall previous version first. Installing next versions after uninstall-install should work without uninstall.

board = esp32dev
build_flags =
-D CFG_IS_CLIENT_MODE=true
-D USE_SX126X

[env:esp32dev_sx126x_igate]
lib_ignore =
NimBLE-Arduino
board = esp32dev
board_build.f_cpu = 240000000L
build_flags =
-D CFG_IS_CLIENT_MODE=false
-D USE_SX126X

[env:esp32dev_sx127x_modem]
lib_ignore =
NimBLE-Arduino
board = esp32dev
build_flags =
-D CFG_IS_CLIENT_MODE=true

[env:esp32dev_sx127x_igate]
lib_ignore =
NimBLE-Arduino
board = esp32dev
board_build.f_cpu = 240000000L
build_flags =
-D CFG_IS_CLIENT_MODE=false

[env:ttgo-lora32-v1_modem]
lib_ignore =
NimBLE-Arduino
board = ttgo-lora32-v1
build_flags =
-D CFG_IS_CLIENT_MODE=true

[env:ttgo-lora32-v2_modem]
lib_ignore =
NimBLE-Arduino
board = ttgo-lora32-v2
build_flags =
-D CFG_IS_CLIENT_MODE=true

[env:heltec-lora32-v3_modem]
lib_ignore =
ESP32 BLE Arduino
BluetoothSerial
board = heltec_wifi_lora_32_V3
board_build.f_cpu = 240000000L
Copy link
Owner

@sh123 sh123 Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be set to 80MHz for lower power consumption 240 MHz is not needed here for the modem mode or just do not set it so it will use default one which is already set to 80MHz.

board_build.mcu = esp32s3
build_flags =
-D CFG_IS_CLIENT_MODE=true
-D USE_SX126X
-D CFG_BT_USE_BLE=true
-D USE_NIMBLE
Copy link
Owner

@sh123 sh123 Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can pass pinouts here so it will be possible to avoid #ifdef in config.h, but in this case need to add #ifndef block for pinout definition, so default ones will be defined only if not already defined.

-D WIFI_LoRa_32_V3

[env:heltec-lora32-v3_igate]
lib_ignore =
ESP32 BLE Arduino
BluetoothSerial
board = heltec_wifi_lora_32_V3
board_build.f_cpu = 240000000L
board_build.mcu = esp32s3
build_flags =
-D CFG_IS_CLIENT_MODE=false
-D USE_SX126X
-D CFG_BT_USE_BLE=true
-D USE_NIMBLE
-D WIFI_LoRa_32_V3
79 changes: 74 additions & 5 deletions src/ble_serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,35 @@
// limitations under the License.

#include "ble_serial.h"
#ifdef USE_NIMBLE
static const char* LOG_TAG = "[NimBLE]";

class BLESerialServerCallbacks: public BLEServerCallbacks {
friend class BLESerial;
BLESerial* bleSerial;

void onConnect(NimBLEServer* pServer) {
// do anything needed on connection
NIMBLE_LOGI(LOG_TAG , "BLE client connected");
delay(1000); // wait for connection to complete or messages can be lost
};

void onDisconnect(NimBLEServer* pServer) {
pServer->startAdvertising(); // restart advertising
NIMBLE_LOGI(LOG_TAG, "BLE client disconnected, started advertising");
}
};

class BLESerialCharacteristicCallbacks: public NimBLECharacteristicCallbacks {
friend class BLESerial;
BLESerial* bleSerial;

void onWrite(NimBLECharacteristic *pCharacteristic) {
bleSerial->receiveBuffer += pCharacteristic->getValue();
}

};
#else

class BLESerialServerCallbacks: public BLEServerCallbacks {
friend class BLESerial;
Expand All @@ -35,16 +64,18 @@ class BLESerialCharacteristicCallbacks: public BLECharacteristicCallbacks {
BLESerial* bleSerial;

void onWrite(BLECharacteristic *pCharacteristic) {
bleSerial->receiveBuffer = bleSerial->receiveBuffer + pCharacteristic->getValue();
bleSerial->receiveBuffer += pCharacteristic->getValue();
}

};

#endif

// Constructor

BLESerial::BLESerial()
: pService(NULL)
, pTxCharacteristic(NULL)
: pService(nullptr)
, pTxCharacteristic(nullptr)
, receiveBuffer("")
{
}
Expand All @@ -60,13 +91,23 @@ BLESerial::~BLESerial(void)

bool BLESerial::begin(const char* localName)
{
#ifdef USE_NIMBLE
// Create the BLE Device
NimBLEDevice::init(localName);

// Create the BLE Server
pServer = NimBLEDevice::createServer();
if (pServer == nullptr)
return false;
#else
// Create the BLE Device
BLEDevice::init(localName);

// Create the BLE Server
pServer = BLEDevice::createServer();
if (pServer == nullptr)
return false;
#endif

BLESerialServerCallbacks* bleSerialServerCallbacks = new BLESerialServerCallbacks();
bleSerialServerCallbacks->bleSerial = this;
Expand All @@ -77,26 +118,53 @@ bool BLESerial::begin(const char* localName)
if (pService == nullptr)
return false;

#ifdef USE_NIMBLE
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
NIMBLE_PROPERTY::NOTIFY
);
if (pTxCharacteristic == nullptr)
return false;

NimBLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
NIMBLE_PROPERTY::WRITE |
NIMBLE_PROPERTY::WRITE_NR
);
#else
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
if (pTxCharacteristic == nullptr)
return false;
pTxCharacteristic->addDescriptor(new BLE2902());

BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR
);
);
#endif

if (pRxCharacteristic == nullptr)
return false;

BLESerialCharacteristicCallbacks* bleSerialCharacteristicCallbacks = new BLESerialCharacteristicCallbacks();
bleSerialCharacteristicCallbacks->bleSerial = this;
pRxCharacteristic->setCallbacks(bleSerialCharacteristicCallbacks);
#ifdef USE_NIMBLE
// Start the service
pService->start();
NIMBLE_LOGI(LOG_TAG , "BLE started service");

// Start advertising
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(pService->getUUID());
pAdvertising->setScanResponse(true);
pAdvertising->start();
NIMBLE_LOGI(LOG_TAG ,"BLE started advertising and waiting for client connection...");
return true;
#else
// Start the service
pService->start();
LOG_INFO("BLE started service");
Expand All @@ -109,6 +177,7 @@ bool BLESerial::begin(const char* localName)
pServer->getAdvertising()->start();
LOG_INFO("BLE started advertising and waiting for client connection...");
return true;
#endif
}

int BLESerial::available(void)
Expand Down
Loading