Signed-off-by: 吴文峰 <kevin@lmve.net>

This commit is contained in:
2026-03-06 16:29:48 +08:00
parent afdd525324
commit ff19e9c6a4
3110 changed files with 8 additions and 523962 deletions
@@ -1,13 +0,0 @@
; Promicro + E22900M30S
[env:WashTastic]
extends = nrf52840_base
board = promicro-nrf52840
board_level = extra
build_flags = ${nrf52840_base.build_flags}
-I variants/nrf52840/diy/nrf52_promicro_diy_tcxo
-D PRIVATE_HW
-D EBYTE_E22_900M30S
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/diy/nrf52_promicro_diy_tcxo>
lib_deps =
${nrf52840_base.lib_deps}
debug_tool = jlink
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

@@ -1,62 +0,0 @@
# Simplifies DIY InkHUD builds, with presets for several common E-Ink displays
# - build using custom task in Platformio's "Project Tasks" panel
# - build with `pio run -e <variant> -t build_weact_154` (or similar)
# Silence trunk's objections to the import statements
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821)
from SCons.Script import COMMAND_LINE_TARGETS
Import("env")
Import("projenv")
# Custom targets
# These wrappers just run the normal build task under a different target name
# We intercept the build later on, based on the target name
env.AddTarget(
name="build_weact_154",
dependencies=["buildprog"],
actions=None,
title='Build (WeAct 1.54")',
)
env.AddTarget(
name="build_weact_213",
dependencies=["buildprog"],
actions=None,
title='Build (WeAct 2.13")',
)
env.AddTarget(
name="build_weact_290",
dependencies=["buildprog"],
actions=None,
title='Build (WeAct 2.9")',
)
env.AddTarget(
name="build_weact_420",
dependencies=["buildprog"],
actions=None,
title='Build (WeAct 4.2")',
)
# Check whether a build was started via one of our custom targets above
if "build_weact_154" in COMMAND_LINE_TARGETS:
print('Building for WeAct 1.54" Display')
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "ZJY200200_0154DAAMFGN"))
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
elif "build_weact_213" in COMMAND_LINE_TARGETS:
print('Building for WeAct 2.13" Display')
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "HINK_E0213A289"))
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "10"))
elif "build_weact_290" in COMMAND_LINE_TARGETS:
print('Building for WeAct 2.9" Display')
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "ZJY128296_029EAAMFGN"))
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
elif "build_weact_420" in COMMAND_LINE_TARGETS:
print('Building for WeAct 4.2" Display')
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "HINK_E042A87"))
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
@@ -1,95 +0,0 @@
#pragma once
#include "configuration.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
// InkHUD-specific components
// ---------------------------
#include "graphics/niche/InkHUD/InkHUD.h"
// Applets
#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h"
#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h"
#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h"
#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h"
#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h"
#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h"
// Shared NicheGraphics components
// --------------------------------
#include "graphics/niche/Drivers/EInk/HINK_E0213A289.h" // WeAct 2.13"
#include "graphics/niche/Drivers/EInk/HINK_E042A87.h" // WeAct 4.2"
#include "graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.h" // WeAct 2.9"
#include "graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h" // WeACt 1.54"
#include "graphics/niche/Inputs/TwoButton.h"
#if !defined(INKHUD_BUILDCONF_DRIVER) || !defined(INKHUD_BUILDCONF_DISPLAYRESILIENCE)
#error If not using a DIY preset, display model and resilience must be set manually
#endif
void setupNicheGraphics()
{
using namespace NicheGraphics;
// SPI
// -----------------------------
SPI.begin();
// Driver
// -----------------------------
// Use E-Ink driver
Drivers::EInk *driver = new Drivers::INKHUD_BUILDCONF_DRIVER;
driver->begin(&SPI, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES);
// InkHUD
// ----------------------------
InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance();
// Set the driver
inkhud->setDriver(driver);
// Set how many FAST updates per FULL update.
inkhud->setDisplayResilience(INKHUD_BUILDCONF_DISPLAYRESILIENCE); // Suggest roughly ten
// Select fonts
InkHUD::Applet::fontLarge = FREESANS_12PT_WIN1252;
InkHUD::Applet::fontMedium = FREESANS_9PT_WIN1252;
InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252;
// Init settings, and customize defaults
// Values ignored individually if found saved to flash
inkhud->persistence->settings.rotation = (driver->height > driver->width ? 1 : 0); // Rotate 90deg to landscape, if needed
inkhud->persistence->settings.userTiles.maxCount = 4;
inkhud->persistence->settings.optionalFeatures.batteryIcon = true;
// Pick applets
// Note: order of applets determines priority of "auto-show" feature
inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet);
inkhud->addApplet("DMs", new InkHUD::DMApplet, true, false, 3); // Default on tile 3
inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0), true, false, 2); // Default on tile 2
inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1));
inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true, false, 1); // Default on tile 1
inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet, true, false, 0); // Default on tile 0
inkhud->addApplet("Heard", new InkHUD::HeardApplet, true); // Background
// Start running InkHUD
inkhud->begin();
// Buttons
// --------------------------
Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component
// Setup the main user button
buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin(), true); // Internal pull up
buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); });
buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); });
buttons->start();
}
#endif
@@ -1,32 +0,0 @@
; Promicro + E22(0)-xxxM / HT-RA62 modules board variant - DIY - with TCXO
[env:nrf52_promicro_diy_tcxo]
extends = nrf52840_base
board = promicro-nrf52840
build_flags = ${nrf52840_base.build_flags}
-I variants/nrf52840/diy/nrf52_promicro_diy_tcxo
-D NRF52_PROMICRO_DIY
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/diy/nrf52_promicro_diy_tcxo>
lib_deps =
${nrf52840_base.lib_deps}
debug_tool = jlink
; NRF52 ProMicro w/ E-Ink display
[env:nrf52_promicro_diy-inkhud]
board_level = extra
extends = nrf52840_base, inkhud
board = promicro-nrf52840
build_flags =
${nrf52840_base.build_flags}
${inkhud.build_flags}
-I variants/nrf52840/diy/nrf52_promicro_diy_tcxo
-D NRF52_PROMICRO_DIY
build_src_filter =
${nrf52_base.build_src_filter}
${inkhud.build_src_filter}
+<../variants/nrf52840/diy/nrf52_promicro_diy_tcxo>
lib_deps =
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
${nrf52840_base.lib_deps}
extra_scripts =
${env.extra_scripts}
variants/nrf52840/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py ; Add to PIO's Project Tasks pane: preset builds for common displays
@@ -1,120 +0,0 @@
<!-- trunk-ignore-all(markdownlint/MD059) -->
# Notes
## General
The pinout is contained in the variant.h file, and a [generic schematic](./Schematic_Pro-Micro_Pinouts.pdf) is located in this directory.
This variant is suitable for both TCXO and XTAL types of modules. The old XTAL variant has been removed to reduce confusion.
### Note on DIO2, RXEN, TXEN, and RF switching
Several modules require external switching between transmit (Tx) and receive (Rx). This can be achieved using several methods:
1. Link the TXEN pin on the radio module to DIO2 on the same module, and then connect RXEN on the radio module to pin 0.17 on the Pro-Micro.
2. Use DIO2 to drive a logic inverter, so that when DIO2 is `high`, RXEN is `low`, and vice versa.
3. Use DIO2 to drive a pair of MOSFETs or transistors to supply the same function.
RXEN is not required to be connected if the selected module already has internal RF switching, or if external RF switching logic is already applied.
Also worth noting that the Seeed WIO SX1262 in particular only has RXEN exposed (marked RF_SW) and has the DIO2-TXEN link internally.
## Making a node based on this variant
Making your own node based on this design is straightforward. There are various open source and free to use PCB design files available, or you can solder wires directly from a module to the pro-micro.
<details>
<summary> < Click to expand > The table of known modules is at the bottom of the variant.h, and reproduced here for convenience. </summary>
| Mfr | Module | TCXO | RF Switch | Notes |
| ------------ | ---------------- | ---- | --------- | ------------------------------------- |
| Ebyte | E22-900M22S | Yes | Ext | |
| Ebyte | E22-900MM22S | No | Ext | |
| Ebyte | E22-900M30S | Yes | Ext | |
| Ebyte | E22-900M33S | Yes | Ext | MAX_POWER must be set to 8 for this |
| Ebyte | E220-900M22S | No | Ext | LLCC68, looks like DIO3 not connected |
| AI-Thinker | RA-01SH | No | Int | SX1262 |
| Heltec | HT-RA62 | Yes | Int | |
| NiceRF | Lora1262 | yes | Int | |
| Waveshare | Core1262-HF | yes | Ext | |
| Waveshare | LoRa Node Module | yes | Int | |
| Seeed | Wio-SX1262 | yes | Ext | Cute! DIO2/TXEN are not exposed |
| Seeed | Wio-LR1121 | yes | Int | LR1121, needs alternate rfswitch.h |
| AI-Thinker | RA-02 | No | Int | SX1278 **433mhz band only** |
| RF Solutions | RFM95 | No | Int | Untested |
| Ebyte | E80-900M2213S | Yes | Int | LR1121 radio |
</details>
## LR1121 modules - E80 is the default
The E80 from CDEbyte is the most obtainable module at present, and has been selected as the default option.
Naturally, CDEbyte have chosen to ignore the generic Semtech impelementation of the RF switching logic and have supplied confusing and contradictory documentation, which is explained below.
tl;dr: The E80 is chosen as the default. **If you wish to use another module, the table in `rfswitch.h` must be adjusted accordingly.**
### E80 switching - the saga
The CDEbyte implementation of the LR1121 is contained in their E80 module. As stated above, CDEbyte have chosen to ignore the generic Semtech implementation of the RF switching logic and have their own table, which is located at the bottom of the page [here](https://www.cdebyte.com/products/E80-900M2213S/2#Pin), and reflected on page 6 of their user manual, and reproduced below:
| DIO5/RFSW0 | DIO6/RFSW1 | RF status |
| ---------- | ---------- | ----------------------------- |
| 0 | 0 | RX |
| 0 | 1 | TX (Sub-1GHz low power mode) |
| 1 | 0 | TX (Sub-1GHz high power mode) |
| 1 | 1 | TX2.4GHz |
However, looking at the sample code they provide on page 9, the values would be:
| DIO5/RFSW0 | DIO6/RFSW1 | RF status |
| ---------- | ---------- | ----------------------------- |
| 0 | 1 | RX |
| 1 | 1 | TX (Sub-1GHz low power mode) |
| 1 | 0 | TX (Sub-1GHz high power mode) |
| 0 | 0 | TX2.4GHz |
The Semtech default, the values are (taken from [here](https://github.com/Lora-net/SWSD006/blob/v2.6.1/lib/app_subGHz_config_lr11xx.c#L145-L154)):
<details>
<summary> < Click to expand >
</summary>
```cpp
.rfswitch = {
.enable = LR11XX_SYSTEM_RFSW0_HIGH | LR11XX_SYSTEM_RFSW1_HIGH | LR11XX_SYSTEM_RFSW2_HIGH,
.standby = 0,
.rx = LR11XX_SYSTEM_RFSW0_HIGH,
.tx = LR11XX_SYSTEM_RFSW0_HIGH | LR11XX_SYSTEM_RFSW1_HIGH,
.tx_hp = LR11XX_SYSTEM_RFSW1_HIGH,
.tx_hf = 0,
.gnss = LR11XX_SYSTEM_RFSW2_HIGH,
.wifi = 0,
},
```
</details>
| DIO5/RFSW0 | DIO6/RFSW1 | RF status |
| ---------- | ---------- | ----------------------------- |
| 1 | 0 | RX |
| 1 | 1 | TX (Sub-1GHz low power mode) |
| 0 | 1 | TX (Sub-1GHz high power mode) |
| 0 | 0 | TX2.4GHz |
It is evident from the tables above that there is no real consistency to those provided by Ebyte.
#### An experiment
Tests were conducted in each of the three configurations between a known-good SX1262 and an E80, passing packets in both directions and recording the reported RSSI. The E80 was set at 22db and 14db to activate the high and low power settings respectively. The results are shown in the chart below.
![Chart showing RSSI readings in each configuration and setting](./E80_RSSI_per_case.webp)
## Conclusion
The RF switching is based on the code example given. Logically, this shows the DIO5 and DIO6 are swapped compared to the reference design.
If future DIYers wish to use an alternative module, the table in `rfswitch.h` must be adjusted accordingly.
@@ -1,20 +0,0 @@
#include "RadioLib.h"
// This is rewritten to match the requirements of the E80-900M2213S
// The E80 does not conform to the reference Semtech switches(!) and therefore needs a custom matrix.
// See footnote #3 in "https://www.cdebyte.com/products/E80-900M2213S/2#Pin"
// RF Switch Matrix SubG RFO_HP_LF / RFO_LP_LF / RFI_[NP]_LF0
// DIO5 -> RFSW0_V1
// DIO6 -> RFSW1_V2
// DIO7 -> not connected on E80 module - note that GNSS and Wifi scanning are not possible.
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7, RADIOLIB_NC,
RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6 DIO7
{LR11x0::MODE_STBY, {LOW, LOW, LOW}}, {LR11x0::MODE_RX, {LOW, HIGH, LOW}},
{LR11x0::MODE_TX, {HIGH, HIGH, LOW}}, {LR11x0::MODE_TX_HP, {HIGH, LOW, LOW}},
{LR11x0::MODE_TX_HF, {LOW, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, HIGH}},
{LR11x0::MODE_WIFI, {LOW, LOW, LOW}}, END_OF_MODE_TABLE,
};
@@ -1,38 +0,0 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// P0
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
void initVariant()
{
// 3V3 Power Rail
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
}
@@ -1,202 +0,0 @@
#ifndef _VARIANT_PROMICRO_DIY_
#define _VARIANT_PROMICRO_DIY_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
// #define USE_LFXO // Board uses 32khz crystal for LF
#define USE_LFRC // Board uses RC for LF
#define PROMICRO_DIY_TCXO
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/*
NRF52 PRO MICRO PIN ASSIGNMENT
| Pin   | Function   |   | Pin     | Function     | RF95 |
| ----- | ----------- | --- | -------- | ------------ | ----- |
| Gnd   |             |   | vbat     |             | |
| P0.06 | Serial2 RX |   | vbat     |             | |
| P0.08 | Serial2 TX |   | Gnd     |             | |
| Gnd   |             |   | reset   |             | |
| Gnd   |             |   | ext_vcc | *see 0.13   | |
| P0.17 | RXEN       |   | P0.31   | BATTERY_PIN | |
| P0.20 | GPS_RX     |   | P0.29   | BUSY         | DIO0 |
| P0.22 | GPS_TX     |   | P0.02   | MISO | MISO |
| P0.24 | GPS_EN     |   | P1.15   | MOSI         | MOSI |
| P1.00 | BUTTON_PIN |   | P1.13   | CS           | CS   |
| P0.11 | SCL         |   | P1.11   | SCK         | SCK |
| P1.04 | SDA         |   | P0.10   | DIO1/IRQ     | DIO1 |
| P1.06 | Free pin   |   | P0.09   | RESET       | RST |
|       |             |   |         |             | |
|       | Mid board   |   |         | Internal     | |
| P1.01 | Free pin   |   | 0.15     | LED         | |
| P1.02 | Free pin   |   | 0.13     | 3V3_EN       | |
| P1.07 | Free pin   |   |         |             | |
*/
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (1)
#define NUM_ANALOG_OUTPUTS (0)
// Pin 13 enables 3.3V periphery. If the Lora module is on this pin, then it should stay enabled at all times.
#define PIN_3V3_EN (0 + 13) // P0.13
// Analog pins
#define BATTERY_PIN (0 + 31) // P0.31 Battery ADC
#define ADC_CHANNEL ADC1_GPIO4_CHANNEL
#define ADC_RESOLUTION 14
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
#define VBAT_MV_PER_LSB (0.73242188F)
// Voltage divider value => 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
#define VBAT_DIVIDER (0.6F)
// Compensation factor for the VBAT divider
#define VBAT_DIVIDER_COMP (1.73)
// Fixed calculation of milliVolt from compensation value
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER VBAT_DIVIDER_COMP // REAL_VBAT_MV_PER_LSB
#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
// WIRE IC AND IIC PINS
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (32 + 4) // P1.04
#define PIN_WIRE_SCL (0 + 11) // P0.11
// LED
#define PIN_LED1 (0 + 15) // P0.15
#define LED_BUILTIN PIN_LED1
// Actually red
#define LED_BLUE PIN_LED1
#define LED_STATE_ON 1 // State when LED is lit
// Button
#define BUTTON_PIN (32 + 0) // P1.00
// GPS
#define PIN_GPS_TX (0 + 22) // P0.22
#define PIN_GPS_RX (0 + 20) // P0.20
#define PIN_GPS_EN (0 + 24) // P0.24
#define GPS_UBLOX
// define GPS_DEBUG
// UART interfaces
#define PIN_SERIAL1_RX PIN_GPS_TX
#define PIN_SERIAL1_TX PIN_GPS_RX
#define PIN_SERIAL2_RX (0 + 6) // P0.06
#define PIN_SERIAL2_TX (0 + 8) // P0.08
// Serial interfaces
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (0 + 2) // P0.02
#define PIN_SPI_MOSI (32 + 15) // P1.15
#define PIN_SPI_SCK (32 + 11) // P1.11
#define LORA_MISO PIN_SPI_MISO
#define LORA_MOSI PIN_SPI_MOSI
#define LORA_SCK PIN_SPI_SCK
#define LORA_CS (32 + 13) // P1.13
// LORA MODULES
#define USE_LLCC68
#define USE_SX1262
#define USE_RF95
#define USE_SX1268
#define USE_LR1121
// RF95 CONFIG
#define LORA_DIO0 (0 + 29) // P0.29 BUSY
#define LORA_DIO1 (0 + 10) // P0.10 IRQ
#define LORA_RESET (0 + 9) // P0.09 NRST
// RX/TX for RFM95/SX127x
#define RF95_RXEN (0 + 17) // P0.17
#define RF95_TXEN RADIOLIB_NC // Assuming that DIO2 is connected to TXEN pin. If not, TXEN must be connected.
// SX126X CONFIG
#define SX126X_CS (32 + 13) // P1.13 FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (0 + 10) // P0.10 IRQ
#define SX126X_DIO2_AS_RF_SWITCH // Note for E22 modules: DIO2 is not attached internally to TXEN for automatic TX/RX switching,
// so it needs connecting externally if it is used in this way
#define SX126X_BUSY (0 + 29) // P0.29
#define SX126X_RESET (0 + 9) // P0.09
#define SX126X_RXEN (0 + 17) // P0.17
#define SX126X_TXEN RADIOLIB_NC // Assuming that DIO2 is connected to TXEN pin. If not, TXEN must be connected.
// LR1121
#ifdef USE_LR1121
#define LR1121_IRQ_PIN (0 + 10) // P0.10 IRQ
#define LR1121_NRESET_PIN LORA_RESET // P0.09 NRST
#define LR1121_BUSY_PIN (0 + 29) // P0.29 BUSY
#define LR1121_SPI_NSS_PIN LORA_CS // P1.13
#define LR1121_SPI_SCK_PIN LORA_SCK
#define LR1121_SPI_MOSI_PIN LORA_MOSI
#define LR1121_SPI_MISO_PIN LORA_MISO
#define LR11X0_DIO3_TCXO_VOLTAGE 1.8
#define LR11X0_DIO_AS_RF_SWITCH
#endif
// #define SX126X_MAX_POWER 8 set this if using a high-power board!
/*
On the SX1262, DIO3 sets the voltage for an external TCXO, if one is present. If one is not present, use TCXO_OPTIONAL to try both
settings.
| Mfr | Module | TCXO | RF Switch | Notes |
| ------------ | ---------------- | ---- | --------- | ------------------------------------- |
| Ebyte | E22-900M22S | Yes | Ext | |
| Ebyte | E22-900MM22S | No | Ext | |
| Ebyte | E22-900M30S | Yes | Ext | |
| Ebyte | E22-900M33S | Yes | Ext | MAX_POWER must be set to 8 for this |
| Ebyte | E220-900M22S | No | Ext | LLCC68, looks like DIO3 not connected |
| AI-Thinker | RA-01SH | No | Int | SX1262 |
| Heltec | HT-RA62 | Yes | Int | |
| NiceRF | Lora1262 | yes | Int | |
| Waveshare | Core1262-HF | yes | Ext | |
| Waveshare | LoRa Node Module | yes | Int | |
| Seeed | Wio-SX1262 | yes | Ext | Cute! DIO2/TXEN are not exposed |
| Seeed | Wio-LR1121 | yes | Int | LR1121, needs alternate rfswitch.h |
| AI-Thinker | RA-02 | No | Int | SX1278 **433mhz band only** |
| RF Solutions | RFM95 | No | Int | Untested |
| Ebyte | E80-900M2213S | Yes | Int | LR1121 radio |
*/
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL
// E-Ink DIY
#define PIN_EINK_CS (32 + 7)
#define PIN_EINK_DC (32 + 2)
#define PIN_EINK_RES (32 + 1)
#define PIN_EINK_BUSY (32 + 6)
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
@@ -1,43 +0,0 @@
# XIAO nRF52840 + XIAO Wio SX1262
For a mere doubling in price you too can swap out the XIAO ESP32C3 for a XIAO nRF52840, stack the Wio SX1262 radio board either above or underneath the nRF52840, solder the pins, and achieve a massive improvement in battery life!
I'm not really sure why else you would want to as the ESP32C3 is perfectly cromulent, easily connects to the Wio SX1262 via the B2B connector and has an onboard IPEX connector for the included Bluetooth antenna. So you'll also lose BT range, but you will also have working ADC for the battery in Meshtastic and also have an ESP32C3 to use for something else!
If you're still reading you are clearly gonna do it anyway, so...mount the Wio SX1262 either on top or underneath depending on your preference. The `variant.h` will work with either configuration though it does map the Wio SX1262's button to nRF52840 Pin `D5` as it can still be used as a user button and it's nice to be able to gracefully shutdown a node by holding it down for 5 seconds.
If you do decide to wire up the button, orient it so looking straight-down at the Wio SX1262 the radio chip is at the bottom, button in the middle and the hole is at the top - the **left** side of the button should be soldered to `GND` (e.g. the 2nd pin down the top on the **right** row of pins) and the **right** side of the button should be soldered to `D5` (e.g. the 2nd pin up from the button on the **left** row of pins.). This mirrors the original wiring and wiring it in reverse could end up connecting GND to voltage and that's no beuno.
Serial Pins remain available on `D6` (TX) and `D7` (RX) should you want to use them, The same pins could be repurposed for `i2c` if you would like to have that instead of serial, in `variant.h` you would just need to change:
```c++
// RX and TX pins
#define PIN_SERIAL1_RX (6)
#define PIN_SERIAL1_TX (7)
```
to
```c++
// RX and TX pins
#define PIN_SERIAL1_RX (-1)
#define PIN_SERIAL1_TX (-1)
```
and
```c++
#define PIN_WIRE_SDA (-1)
#define PIN_WIRE_SCL (-1)
// #define PIN_WIRE_SDA (6)
// #define PIN_WIRE_SCL (7)
```
to
```c++
#define PIN_WIRE_SDA (6)
#define PIN_WIRE_SCL (7)
```
If you wanted both serial and i2c you could even go so far as to use the pads for the PDM mic which is missing on the non-sense board (`P1.00` / `P0.16`)... or move up to the nRF52840 Plus which has even more pins available but hasn't been checked/confirmed if it follows the same pin mapping as the non-plus.
@@ -1,15 +0,0 @@
; Seeed XIAO nRF52840 + XIAO Wio SX1262 DIY
[env:seeed-xiao-nrf52840-wio-sx1262]
board = xiao_ble_sense
extends = nrf52840_base
board_level = extra
build_flags = ${nrf52840_base.build_flags}
-Ivariants/nrf52840/diy/seeed-xiao-nrf52840-wio-sx1262
-D PRIVATE_HW
-Isrc/platform/nrf52/softdevice
-Isrc/platform/nrf52/softdevice/nrf52
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/diy/seeed-xiao-nrf52840-wio-sx1262>
lib_deps =
${nrf52840_base.lib_deps}
debug_tool = jlink
@@ -1,62 +0,0 @@
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// D0 .. D13
2, // D0 is P0.02 (A0)
3, // D1 is P0.03 (A1)
28, // D2 is P0.28 (A2)
29, // D3 is P0.29 (A3)
4, // D4 is P0.04 (A4,SDA)
5, // D5 is P0.05 (A5,SCL)
43, // D6 is P1.11 (TX)
44, // D7 is P1.12 (RX)
45, // D8 is P1.13 (SCK)
46, // D9 is P1.14 (MISO)
47, // D10 is P1.15 (MOSI)
// LEDs
26, // D11 is P0.26 (LED RED)
6, // D12 is P0.06 (LED BLUE)
30, // D13 is P0.30 (LED GREEN)
14, // D14 is P0.14 (READ_BAT)
// LSM6DS3TR
40, // D15 is P1.08 (6D_PWR)
27, // D16 is P0.27 (6D_I2C_SCL)
7, // D17 is P0.07 (6D_I2C_SDA)
11, // D18 is P0.11 (6D_INT1)
// MIC
42, // 17,//42, // D19 is P1.10 (MIC_PWR)
32, // 26,//32, // D20 is P1.00 (PDM_CLK)
16, // 25,//16, // D21 is P0.16 (PDM_DATA)
// BQ25100
13, // D22 is P0.13 (HICHG)
17, // D23 is P0.17 (~CHG)
//
21, // D24 is P0.21 (QSPI_SCK)
25, // D25 is P0.25 (QSPI_CSN)
20, // D26 is P0.20 (QSPI_SIO_0 DI)
24, // D27 is P0.24 (QSPI_SIO_1 DO)
22, // D28 is P0.22 (QSPI_SIO_2 WP)
23, // D29 is P0.23 (QSPI_SIO_3 HOLD)
// NFC
9, // D30 is P0.09 (NFC1)
10, // D31 is P0.10 (NFC2)
// VBAT
31, // D32 is P0.10 (VBAT)
};
void initVariant()
{
// Set BQ25101 ISET to 100mA instead of 50mA
pinMode(HICHG, OUTPUT);
digitalWrite(HICHG, LOW);
}
@@ -1,187 +0,0 @@
// basically xiao_ble with pins remapped for:
// Seeed XIAO nRF52840 : https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html
// Seeed Wio SX1626 : https://www.seeedstudio.com/Wio-SX1262-with-XIAO-ESP32S3-p-5982.html
#ifndef _SEEED_XIAO_NRF52840_SENSE_H_
#define _SEEED_XIAO_NRF52840_SENSE_H_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define PINS_COUNT (33)
#define NUM_DIGITAL_PINS (33)
#define NUM_ANALOG_INPUTS (8) // A6 is used for battery, A7 is analog reference
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
// ----
#define LED_RED 11
#define LED_BLUE 12
#define LED_GREEN 13
#define PIN_LED1 LED_GREEN
#define PIN_LED2 LED_BLUE
#define PIN_LED3 LED_RED
#define PIN_LED PIN_LED1
#define LED_PWR (PINS_COUNT)
#define LED_BUILTIN PIN_LED
#define LED_STATE_ON 1 // State when LED is lit
// XIAO Wio-SX1262 Shield User button
#define PIN_BUTTON1 5
#define BUTTON_NEED_PULLUP
// Digital Pins
// ------------
#define D0 (0ul)
#define D1 (1ul)
#define D2 (2ul)
#define D3 (3ul)
#define D4 (4ul)
#define D5 (5ul)
#define D6 (6ul)
#define D7 (7ul)
#define D8 (8ul)
#define D9 (9ul)
#define D10 (10ul)
// Analog Pins
// -----------
#define PIN_A0 (0)
#define PIN_A1 (1)
#define PIN_A2 (2)
#define PIN_A3 (3)
#define PIN_A4 (4)
#define PIN_A5 (5)
#define PIN_VBAT (32)
#define VBAT_ENABLE (14)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
#define ADC_RESOLUTION 12
// Other Pins
// ----------
#define PIN_NFC1 (30)
#define PIN_NFC2 (31)
// RX and TX pins
#define PIN_SERIAL1_RX (-1)
#define PIN_SERIAL1_TX (-1)
// complains if not defined
#define PIN_SERIAL2_RX (-1)
#define PIN_SERIAL2_TX (-1)
// 4 is used as RF_SW and 5 for USR button so...
#define PIN_WIRE_SDA (6)
#define PIN_WIRE_SCL (7)
static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;
// SPI SX1262
// ----------
#define SPI_SX1262
#ifdef SPI_SX1262
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (9)
#define PIN_SPI_MOSI (10)
#define PIN_SPI_SCK (8)
static const uint8_t SS = D3;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
// supported modules list
#define USE_SX1262
// common pinouts for SX126X modules
#define SX126X_CS D3
#define SX126X_DIO1 D0
#define SX126X_BUSY D1
#define SX126X_RESET D2
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_RXEN 38
#define SX126X_TXEN RADIOLIB_NC
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
// Wire Interfaces
// -------------------
#define WIRE_INTERFACES_COUNT 1 // 2
// Sense version has IMU and PDM Mic
// #define XIAO_SENSE
#ifndef XIAO_SENSE
// 6 DoF IMU
#define PIN_LSM6DS3TR_C_POWER (15)
#define PIN_LSM6DS3TR_C_INT1 (18)
// PDM Interfaces
// ---------------
#define PIN_PDM_PWR (19)
#define PIN_PDM_CLK (20)
#define PIN_PDM_DIN (21)
#endif
// QSPI Pins
// ---------
#define PIN_QSPI_SCK (24)
#define PIN_QSPI_CS (25)
#define PIN_QSPI_IO0 (26)
#define PIN_QSPI_IO1 (27)
#define PIN_QSPI_IO2 (28)
#define PIN_QSPI_IO3 (29)
// On-board QSPI Flash
// -------------------
#define EXTERNAL_FLASH_DEVICES P25Q16H
#define EXTERNAL_FLASH_USE_QSPI
// Battery
// -------
// P0_14 = 14 Reads battery voltage from divider on signal board.
// PIN_VBAT is reading voltage divider on XIAO and is program pin 32 / or P0.31
#define ADC_CTRL VBAT_ENABLE
#define ADC_CTRL_ENABLED LOW
#define BATTERY_SENSE_RESOLUTION_BITS 10
#define CHARGE_LED 23 // P0_17 = 17 D23 YELLOW CHARGE LED
#define HICHG 22 // P0_13 = 13 D22 Charge-select pin for Lipo for 100 mA instead of default 50mA charge
// The battery sense is hooked to pin A0 (5)
#define BATTERY_PIN PIN_VBAT // PIN_A0
// ratio of voltage divider = 3.0 (R17=1M, R18=510k)
#define ADC_MULTIPLIER 3 // 3.0 + a bit for being optimistic
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
@@ -1,19 +0,0 @@
; Seeed XIAO nRF52840 + EBYTE E22-900M30S - Pinout matching Wio-SX1262 (SKU 113010003)
[env:seeed_xiao_nrf52840_e22_900m30s]
extends = env:seeed_xiao_nrf52840_kit
board_level = extra
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags}
-D PRIVATE_HW
-DEBYTE_E22
-DEBYTE_E22_900M30S
build_unflags = -DGPS_L76K
; Seeed XIAO nRF52840 + EBYTE E22-900M33S - Pinout matching Wio-SX1262 (SKU 113010003)
[env:seeed_xiao_nrf52840_e22_900m33s]
extends = env:seeed_xiao_nrf52840_kit
board_level = extra
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags}
-D PRIVATE_HW
-DEBYTE_E22
-DEBYTE_E22_900M33S
build_unflags = -DGPS_L76K
@@ -1,168 +0,0 @@
# XIAO nrf52840/nrf52840 Sense + Ebyte E22-900M30S
_A step-by-step guide for macOS and Linux._
## Introduction
This guide will walk you through everything needed to get the XIAO nrf52840 (or XIAO nrf52840 Sense) running Meshtastic using an Ebyte E22-900M30S LoRa module. The combination of the E22 with an nRF52840 MCU is desirable because it allows for both very low idle (Rx) power draw _and_ high transmit power.
The XIAO nrf52840 is a small but surprisingly well-appointed nRF52840 board, with enough GPIO for most Meshtastic applications and a built-in LiPo charger.
The E22, on the other hand, is a famously inscrutable and mysterious beast. It is one of the more readily available LoRa modules capable of transmitting at 30 dBm, and includes an LNA to boost its Rx sensitivity a few dB beyond that of the SX1262.
However, its documentation is relatively sparse overall, and seems to merely hint at (or completely omit) several key details regarding its functionality. Thus, much of what follows is a synthesis of my observations and inferences over the course of many hours of trial and error.
### Acknowledgement and Friendly Disclaimer
Huge thanks to those in the community who have forged the way with the E22, without whose hard work none of this would have been possible! (thebentern, riddick, rainer_vie, beegee-tokyo, geeksville, caveman99, Der_Bear, PlumRugOfDoom, BigCorvus, and many others.)
Please take the conclusions here as a tentative work in progress, representing my current (and fairly limited) understanding of the E22 when paired with this particular MCU. It is my hope that this guide will be helpful to others who are interested in trying a DIY Meshtastic build, and also be subject to revision by folks with more experience and better test equipment.
### Obligatory Liability Disclaimer
This guide and all associated content is for informational purposes only. The information presented is intended for consumption only by persons having appropriate technical skill and judgement, to be used entirely at their own discretion and risk. The authors of this guide in no way provide any warranty, express or implied, toward the content herein, nor its correctness, safety, or suitability to any particular purpose. By following the instructions in this guide in part or in full, you assume all responsibility for all potential risks, including but not limited to fire, property damage, bodily injury, and death.
## 1. Wire the board
Connecting the E22 to the XIAO nrf52840 is straightforward, but there are a few gotchas to be mindful of.
### On the XIAO nrf52840
- Pins D4 and D5 are currently mapped to `PIN_WIRE_SDA` and `PIN_WIRE_SCL`, respectively. If you are not using I²C and would like to free up pins D4 and D5 for use as GPIO, `PIN_WIRE_SDA` and `PIN_WIRE_SCL` can be reassigned to any two other unused pin numbers.
- Pins D6 and D7 were originally mapped to the TX and RX pins for serial interface 1 (`PIN_SERIAL1_RX` and `PIN_SERIAL1_TX`) but are currently set to -1 in `variant.h`. If you need to expose a serial interface, you can restore these pins and move e.g. `SX126X_RXEN` to pin 4 or 5 (the opposite should work too).
### On the E22
- There are two options for the E22's `TXEN` pin:
1. It can be connected to the MCU on the pin defined as `SX126X_TXEN` in `variant.h`. In this configuration, the MCU will control Tx/Rx switching "manually". As long as `SX126X_TXEN` and `SX126X_RXEN` are both defined in `variant.h` (and neither is set to `RADIOLIB_NC`), `SX126xInterface.cpp` will initialize the E22 correctly for this mode.
2. Alternately, it can be connected to the E22's `DIO2` pin only, with neither `TXEN` nor `DIO2` being connected to the MCU. In this configuration, the E22 will control Tx/Rx switching automatically. In `variant.h`, as long as `SX126X_TXEN` is defined as `RADIOLIB_NC`, and `SX126X_RXEN` is defined and connected to the E22's `RXEN` pin, and `E22_TXEN_CONNECTED_TO_DIO2` is defined, `SX126xInterface.cpp` will initialize the E22 correctly for this mode. This configuration frees up a GPIO, and presents no drawbacks that I have found.
- Note that any combination other than the two described above will likely result in unexpected behavior. In my testing, some of these other configurations appeared to "work" at first glance, but every one I tried had at least one of the following flaws: weak Tx power, extremely poor Rx sensitivity, or the E22 overheating because TXEN was never pulled low, causing its PA to stay on indefinitely.
- Along the same lines, it is a good idea to check the E22's temperature frequently by lightly touching the shield. If you feel the shield getting hot (i.e. approaching uncomfortable to touch) near pins 1, 2, and 3, something is probably misconfigured; disconnect both the XIAO nrf52840 and E22 from power and double check wiring and pin mapping.
- Whether you opt to let the E22 control Rx and Tx or handle this manually, **the E22's `RXEN` pin must always be connected to the MCU** on the pin defined as `SX126X_RXEN` in `variant.h`.
#### Note
The default pin mapping in `variant.h` uses "Automatic Tx/Rx switching" mode.
If you wire your board for Manual Tx/Rx Switching Mode, `SX126X_TXEN` must be defined (`#define #define SX126X_TXEN D6`) in `variants/seeed_xiao_nrf52840_kit/variant.h` in the code block following:
```c
#ifdef XIAO_BLE_LEGACY_PINOUT
// Legacy xiao_ble variant pinout for third-party SX126x modules e.g. EBYTE E22
```
### Example Wiring for Automatic Tx/Rx Switching Mode
#### MCU -> E22 Connections
| XIAO nrf52840 pin | variant.h definition | E22 pin | Notes |
| :---------------- | :------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------- |
| D0 | SX126X_CS | 19 (NSS) | |
| D1 | SX126X_DIO1 | 13 (DIO1) | |
| D2 | SX126X_BUSY | 14 (BUSY) | |
| D3 | SX126X_RESET | 15 (NRST) | |
| D7 | SX126X_RXEN | 6 (RXEN) | These pins must still be connected, and `SX126X_RXEN` defined in `variant.h`, otherwise Rx sensitivity will be poor. |
| D8 | PIN_SPI_SCK | 18 (SCK) | |
| D9 | PIN_SPI_MISO | 16 (MISO) | |
| D10 | PIN_SPI_MOSI | 17 (MOSI) | |
#### E22 -> E22 Connections
| E22 pin | E22 pin | Notes |
| :------ | :------ | :------------------------------------------------------------------------ |
| TXEN | DIO2 | These must be physically connected for automatic Tx/Rx switching to work. |
#### Note
The schematic (`xiao-ble-e22-schematic.png`) in the `eagle-project` directory uses this wiring.
### Example Wiring for Manual Tx/Rx Switching Mode
#### MCU -> E22 Connections
| XIAO nrf52840 pin | variant.h definition | E22 pin | Notes |
| :---------------- | :------------------- | :-------- | :---- |
| D0 | SX126X_CS | 19 (NSS) | |
| D1 | SX126X_DIO1 | 13 (DIO1) | |
| D2 | SX126X_BUSY | 14 (BUSY) | |
| D3 | SX126X_RESET | 15 (NRST) | |
| D6 | SX126X_TXEN | 7 (TXEN) | |
| D7 | SX126X_RXEN | 6 (RXEN) | |
| D8 | PIN_SPI_SCK | 18 (SCK) | |
| D9 | PIN_SPI_MISO | 16 (MISO) | |
| D10 | PIN_SPI_MOSI | 17 (MOSI) | |
#### E22 -> E22 connections
_(none)_
## 2. Build Meshtastic
1. Follow the [Building Meshtastic Firmware](https://meshtastic.org/docs/development/firmware/build/) documentation, stop after **Build****Step 2**
2. For **Build****Step 3**, select `xiao_ble` as your target
3. Adjust source code if you:
- Wired your board for Manual Tx/Rx Switching Mode: see [Wire the Board](#1-wire-the-board)
- Used an E22-900M33S module
(this step is important to avoid **damaging the power amplifier** in the M33S module and **transmitting power above legal limits**!):
1. Open `variants/diy/platformio.ini`
2. Search for `[env:xiao_ble]`
3. In the line starting with `build_flags` within this section, change `-DEBYTE_E22_900M30S` to `-DEBYTE_E22_900M33S`
4. Follow **Build****Step 4** to build the firmware
5. Stop here, because the **PlatformIO: Upload** step does not work for factory-fresh XIAO nrf52840 (the automatic reset to bootloader only works if Meshtastic firmware is already running)
6. The built `firmware.uf2` binary can be found in the folder `.pio/build/xiao_ble/firmware.uf2` (relative to where you cloned the Git repository to), we will need it for [flashing the firmware](#3-flash-the-firmware-to-the-xiao-nrf52840) (manually)
## 3. Flash the Firmware to the XIAO nrf52840
1. Double press the XIAO nrf52840's `reset` button to put it in bootloader mode, and a USB volume named `XIAO SENSE` will appear
2. Copy the `firmware.uf2` file to the `XIAO SENSE` volume (refer to the last step of [Build Meshtastic](#2-build-meshtastic))
3. The XIAO nrf52840's red LED will flash for several seconds as the firmware is copied
4. Once Meshtastic firmware succesfully boots, the:
1. Green LED will turn on
2. Red LED will flash several times to indicate flash memory writes during initial settings file creation
3. Green LED will blink every second once the firmware is running normally
5. If you do not see the above LED patters, proceed to [Troubleshooting](#4-troubleshooting)
## 4. Troubleshooting
- If after flashing Meshtastic, the XIAO is bootlooped, look at the serial output (you can see this by running `meshtastic --noproto` with the device connected to your computer via USB).
- If you see that the SX1262 init result was -2, this likely indicates a wiring problem; double check your wiring and pin mapping in `variant.h`.
- If you see an error mentioning tinyFS, this may mean you need to reformat the XIAO's storage:
1. Open the [Meshtastic web flasher](https://flasher.meshtastic.org/)
2. Select the **_Seeed XIAO NRF52840 Kit_**
3. Click the **_trash can icon_** to the right of **_Flash_**
4. Follow the instructions on the screen
**Do not flash the Seeed XIAO NRF52840 Kit firmware** if you have wired the LoRa module according to this variant, as the Seeed XIAO NRF52840 Kit uses different wiring for the SX1262 LoRa chip
- If you don't see any specific error message, but the boot process is stuck or not proceeding as expected, this might also mean there is a conflict in `variant.h`. If you have made any changes to the pin mapping, ensure they do not result in a conflict. If all else fails, try reverting your changes and using the known-good configuration included here.
- The above might also mean something is wired incorrectly. Try reverting to one of the known-good example wirings in section 4.
- If the E22 gets hot to the touch:
- The power amplifier is likely running continually. Disconnect it and the XIAO from power immediately, and double check wiring and pin mapping. In my experimentation this occurred in cases where TXEN was inadvertenly high (usually due to a pin mapping conflict).
## 5. Notes
- **Transmit Power**
- There is a power amplifier after the SX1262's Tx, so the actual Tx power is just over 7 dB greater than the SX1262's set Tx power (the E22-900M30S actually tops out just over 29dB at 5V according to the datasheet)
- Meshtastic firmware is aware of the gain of the E22-900M30S module, so the Meshtastic clients' Tx power setting reflects the actual output power, i.e. setting 30 dBm in the Meshtastic app programs the E22 module to correctly output 30 dBm, setting 24 dBm will output 24 dBm, etc.
- **Adequate 5V Power Supply to the E22 Module**
- Have a bypass capacitor from its 5V supply to ground; 100 µF works well
- Voltage must be between 5V5.5V, lower supply voltage results in less output power; for example, with a fully charged LiPo at 4.2V, Tx power appears to max out around 26-27 dBm
### Additional Reading
- [S5NC/CDEBYTE_Modules](https://github.com/S5NC/CDEBYTE_Modules) has additional information about EBYTE E22 modules' internal workings, including photographs
- [RadioLib High power Radio Modules Guide](https://github.com/jgromes/RadioLib/wiki/High-power-Radio-Modules-Guide)
## 6. Testing Methodology
During what became a fairly long trial-and-error process, I did a lot of careful testing of Tx power and Rx sensitivity. My methodology in these tests was as follows:
- All tests were conducted between two nodes:
1. The XIAO nrf52840 + E22 coupled with an [Abracon ARRKP4065-S915A](https://www.digikey.com/en/products/detail/abracon-llc/ARRKP4065-S915A/8593263") ceramic patch antenna
2. A RAK 5005/4631 coupled with a [Laird MA9-5N](https://www.streakwave.com/laird-technologies-ma9-5n-55dbi-900mhz-mobile-omni-select-mount) antenna via a 4" U.FL to Type N pigtail.
- No other nodes were powered up onsite or nearby.
- Each node and its antenna was kept in exactly the same position and orientation throughout testing.
- Other environmental factors (e.g. the location and resting position of my body in the room while testing) were controlled as carefully as possible.
- Each test comprised at least five (and often ten) runs, after which the results were averaged.
- All testing was done by sending single-character messages between nodes and observing the received RSSI reported in the message acknowledgement. Messages were sent one by one, waiting for each to be acknowledged or time out before sending the next.
- The E22's Tx power was observed by sending messages from the RAK to the XIAO nrf52840 + E22 and recording the received RSSI.
- The opposite was done to observe the E22's Rx sensitivity: messages were sent from the XIAO nrf52840 + E22 to the RAK, and the received RSSI was recorded.
While this cannot match the level of accuracy achievable with actual test equipment in a lab setting, it was nonetheless sufficient to demonstrate the (sometimes very large) differences in Tx power and Rx sensitivity between various configurations.
@@ -1,10 +0,0 @@
; Seeed Xiao BLE: https://www.digikey.com/en/products/detail/seeed-technology-co-ltd/102010448/16652893
[env:xiao_ble]
extends = env:seeed_xiao_nrf52840_kit
board_level = extra
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags}
-D PRIVATE_HW
-DXIAO_BLE_LEGACY_PINOUT
-DEBYTE_E22
-DEBYTE_E22_900M30S
build_unflags = -DGPS_L76K