feat: add moonshine_NRF52_ebyte variant (Ebyte nRF52840 + E22-400M33S)
DIY Meshtastic node using an Ebyte nRF52840 MCU module with LFXO crystal and E22-400M33S LoRa module (SX1268, 433MHz, 33dBm). Pin assignments: - LED (LED_PAIRING): P0.15, LED_LORA DIO1: P1.10, BUSY: P0.28 (AIN4) - LORA_CS: P0.17, RESET: P1.13, RXEN: P1.09, SPI: P0.20/P0.22/P1.00 - VBAT_ADC: P0.03 (0.5 divider), CHAG_DET: P0.13, BUZZER: P1.11 - BUTTON: P0.24, I2C: SDA=P0.08/SCL=P0.04 (wired, no devices) PA parameters derived from E22-M UserManual V1.2 power curve (not from E22-900M33S which uses a different PA with 25dB gain): - SX126X_MAX_POWER=21, TX_GAIN_LORA=12 (chip 21dBm -> module ~33.5dBm) - DIO2_AS_RF_SWITCH with MCU-controlled RXEN, TCXO 1.8V (TCXO_OPTIONAL) USB CDC serial enabled by default (nRF52840 built-in). No GPS/screen/ I2C devices. Uses S140 v6 SoftDevice (matches nice!nano bootloader). Flashable via USB (1200bps touch DFU) or UF2 drag-and-drop.
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
; Moonshine NRF52 ebyte - DIY variant (Ebyte nRF52840 + E22-400M33S)
|
||||||
|
; Uses S140 v6 SoftDevice (matches nice!nano / Adafruit Feather factory bootloader).
|
||||||
|
; Inherits the default v6 ldscript from [nrf52840_base] (app start at 0x26000).
|
||||||
|
[env:moonshine_NRF52_ebyte]
|
||||||
|
extends = nrf52840_base
|
||||||
|
board = adafruit_feather_nrf52840
|
||||||
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-I variants/nrf52840/diy/moonshine_NRF52_ebyte
|
||||||
|
-D PRIVATE_HW
|
||||||
|
-D CONFIG_GPIO_AS_PINRESET
|
||||||
|
-D MESHTASTIC_EXCLUDE_I2C=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_INPUTBROKER=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_ACCELEROMETER=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_MAGNETOMETER=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_GPS=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_SCREEN=1
|
||||||
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/diy/moonshine_NRF52_ebyte>
|
||||||
|
debug_tool = jlink
|
||||||
|
; Upload via USB: pio run -e moonshine_NRF52_ebyte -t upload
|
||||||
|
; Uses 1200bps touch to enter DFU bootloader, then nrfutil serial DFU.
|
||||||
|
; Alternative: double-tap reset -> drag .uf2 to USB mass storage
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# Moonshine NRF52 ebyte
|
||||||
|
|
||||||
|
DIY Meshtastic node variant based on an Ebyte nRF52840 MCU module and E22-400M33S LoRa module.
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
- **MCU module**: Ebyte nRF52840 (512 KB flash / 128 KB RAM)
|
||||||
|
- **LF clock**: 32.768 kHz crystal (`USE_LFXO`)
|
||||||
|
- **LoRa**: E22-400M33S (SX1268 + 33dBm PA, 2W, 433MHz) - `SX126X_MAX_POWER=8`,
|
||||||
|
`TX_GAIN_LORA=25`. `SX126X_RXEN` (P1.09) is MCU-controlled by RadioLib; TXEN is
|
||||||
|
driven by DIO2 (`SX126X_DIO2_AS_RF_SWITCH`). TCXO voltage 1.8V with `TCXO_OPTIONAL`
|
||||||
|
fallback to XTAL.
|
||||||
|
- **LED**: Bluetooth pairing status on P0.15 (`LED_PAIRING`). Solid on = BLE
|
||||||
|
connected, slow blink = unpaired, fast blink = pairing, off after 30s idle.
|
||||||
|
- **Battery ADC**: 0.5 voltage divider (equal resistors)
|
||||||
|
- **USB CDC serial**: enabled by default (nRF52840 built-in USB-ACM). Debug output
|
||||||
|
and Meshtastic CLI communication go through the USB serial port.
|
||||||
|
- **I2C**: SDA/SCL pins wired (P0.08/P0.04) but no I2C devices connected.
|
||||||
|
|
||||||
|
## Pin map
|
||||||
|
|
||||||
|
| Function | Pin | Notes |
|
||||||
|
| ------------- | ----- | ---------------------------------- |
|
||||||
|
| LED | P0.15 | Bluetooth pairing status |
|
||||||
|
| CHARGE_DET | P0.13 | Active high (charging) |
|
||||||
|
| BUTTON | P0.24 | User button |
|
||||||
|
| BUZZER | P1.11 | PWM buzzer |
|
||||||
|
| BATTERY_ADC | P0.03 | AIN1, 0.5 divider |
|
||||||
|
| IIC_SDA | P0.08 | Wired, no device |
|
||||||
|
| IIC_SCL | P0.04 | Wired, no device |
|
||||||
|
| SPI_MISO | P1.00 | |
|
||||||
|
| SPI_MOSI | P0.22 | |
|
||||||
|
| SPI_SCK | P0.20 | |
|
||||||
|
| LORA_CS | P0.17 | |
|
||||||
|
| LORA_DIO1 | P1.10 | IRQ |
|
||||||
|
| LORA_BUSY | P0.28 | AIN4 (AI4) |
|
||||||
|
| LORA_RESET | P1.13 | |
|
||||||
|
| LORA_RXEN | P1.09 | MCU-controlled RXEN; TXEN via DIO2 |
|
||||||
|
|
||||||
|
## Build & Flash
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pio run -e moonshine_NRF52_ebyte
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses `PRIVATE_HW` (HardwareModel 255) - no protobuf or `architecture.h` changes
|
||||||
|
required.
|
||||||
|
|
||||||
|
The build links against `nrf52840_s140_v6.ld`, so the application is linked to
|
||||||
|
start at `0x26000` and requires the S140 SoftDevice v6.x to be present on the
|
||||||
|
chip at `0x0`-`0x25FFF`. The build output (`firmware-*.hex` / `.uf2`) contains
|
||||||
|
**only the application**, not the SoftDevice.
|
||||||
|
|
||||||
|
### Flash via USB (nice!nano)
|
||||||
|
|
||||||
|
The nice!nano comes pre-flashed with the S140 v6 SoftDevice and the Adafruit
|
||||||
|
UF2 bootloader. No SWD probe is needed - firmware can be uploaded over USB.
|
||||||
|
|
||||||
|
**Method 1: PlatformIO serial DFU (recommended)**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pio run -e moonshine_NRF52_ebyte -t upload
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO opens the USB CDC serial port at 1200 baud to trigger the DFU
|
||||||
|
bootloader, then uploads via `nrfutil` serial DFU. The board automatically
|
||||||
|
resets into the application after upload.
|
||||||
|
|
||||||
|
**Method 2: UF2 drag-and-drop**
|
||||||
|
|
||||||
|
1. Double-tap the Reset button to enter UF2 bootloader mode. A USB mass storage
|
||||||
|
volume will appear (e.g. `NRF52BOOT`).
|
||||||
|
2. Copy the `.uf2` file from `.pio/build/moonshine_NRF52_ebyte/firmware-*.uf2`
|
||||||
|
to the USB volume.
|
||||||
|
3. The board automatically resets into the application after the file transfer
|
||||||
|
completes.
|
||||||
|
|
||||||
|
### Flash via SWD (alternative)
|
||||||
|
|
||||||
|
If the SoftDevice or bootloader is missing or corrupted, flash via SWD with
|
||||||
|
OpenOCD (CMSIS-DAP / J-Link / ST-Link):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Full flow: recover (erase all + unlock) -> SoftDevice -> app -> reset
|
||||||
|
openocd -f interface/cmsis-dap.cfg -f target/nrf52.cfg \
|
||||||
|
-c "init; nrf52_recover; \
|
||||||
|
program bin/s140_nrf52_7.3.0_softdevice.hex verify; \
|
||||||
|
program .pio/build/moonshine_NRF52_ebyte/firmware-*.hex verify; \
|
||||||
|
reset run; exit"
|
||||||
|
```
|
||||||
|
|
||||||
|
When the SoftDevice is already on the chip and only the application changed,
|
||||||
|
skip `nrf52_recover` and the SoftDevice line:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
openocd -f interface/cmsis-dap.cfg -f target/nrf52.cfg \
|
||||||
|
-c "init; \
|
||||||
|
program .pio/build/moonshine_NRF52_ebyte/firmware-*.hex verify; \
|
||||||
|
reset run; exit"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The firmware hex filename contains a commit hash (e.g. `2.8.0.421838f`); use
|
||||||
|
the actual file produced by `pio run` or a shell glob.
|
||||||
|
- USB CDC serial is available immediately after boot for debug output and the
|
||||||
|
Meshtastic Python CLI (`meshtastic --noproto` / `meshtastic --info`).
|
||||||
|
- `MESHTASTIC_EXCLUDE_I2C=1` is set because no I2C devices are connected. Remove
|
||||||
|
this flag from `platformio.ini` if an I2C display or sensor is added later.
|
||||||
|
- No GPS, screen, accelerometer, or magnetometer is configured. Remove the
|
||||||
|
corresponding `MESHTASTIC_EXCLUDE_*` flags from `platformio.ini` if hardware
|
||||||
|
is added.
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
// Configure P0.18 as RESET pin (UICR->PSELRESET).
|
||||||
|
// nrf52_recover (ERASEALL) clears UICR to 0xFFFFFFFF, disabling reset.
|
||||||
|
// SystemInit() already handles this via CONFIG_GPIO_AS_PINRESET; this is a
|
||||||
|
// safety net that runs before SoftDevice is enabled, so NVMC is accessible.
|
||||||
|
if ((NRF_UICR->PSELRESET[0] != 18) || (NRF_UICR->PSELRESET[1] != 18)) {
|
||||||
|
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
|
||||||
|
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
|
||||||
|
NRF_UICR->PSELRESET[0] = 18;
|
||||||
|
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
|
||||||
|
NRF_UICR->PSELRESET[1] = 18;
|
||||||
|
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
|
||||||
|
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
|
||||||
|
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
|
||||||
|
NVIC_SystemReset(); // Reboot to apply PSELRESET (hardware reconfigures P0.18)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize pairing LED pin (StatusLEDModule only calls digitalWrite, not pinMode)
|
||||||
|
pinMode(LED_PAIRING, OUTPUT);
|
||||||
|
digitalWrite(LED_PAIRING, LED_STATE_ON ^ 1); // OFF
|
||||||
|
}
|
||||||
|
|
||||||
|
void variant_shutdown()
|
||||||
|
{
|
||||||
|
// Turn off pairing LED
|
||||||
|
nrf_gpio_pin_write(LED_PAIRING, LED_STATE_ON ^ 1);
|
||||||
|
|
||||||
|
nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Enable internal pull-up on the button pin
|
||||||
|
nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW; // Configure SENSE signal on low edge
|
||||||
|
nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
#ifndef _VARIANT_MOONSHINE_NRF52_EBYTE_
|
||||||
|
#define _VARIANT_MOONSHINE_NRF52_EBYTE_
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
MOONSHINE NRF52 EBYTE PIN ASSIGNMENT (Ebyte nRF52840 + E22-400M33S)
|
||||||
|
|
||||||
|
| Pin | Function | | Pin | Function |
|
||||||
|
| ----- | ----------- | ------ | ----- | ----------- |
|
||||||
|
| P0.03 | VBAT_ADC | | P0.22 | SPI_MOSI |
|
||||||
|
| P0.04 | IIC_SCL | | P0.24 | BUTTON |
|
||||||
|
| P0.08 | IIC_SDA | | P0.28 | LORA_BUSY |
|
||||||
|
| P0.13 | CHAG_DET | | P1.00 | SPI_MISO |
|
||||||
|
| P0.15 | LED | | P1.09 | LORA_RXEN |
|
||||||
|
| P0.17 | LORA_CS | | P1.10 | LORA_DIO1 |
|
||||||
|
| P0.20 | SPI_SCK | | P1.11 | BUZZER |
|
||||||
|
| | | | P1.13 | LORA_RESET |
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// No dedicated 3V3 enable pin on this board
|
||||||
|
#define PIN_3V3_EN (-1)
|
||||||
|
|
||||||
|
// Analog pins
|
||||||
|
#define BATTERY_PIN (0 + 3) // P0.03 / AIN1 Battery ADC
|
||||||
|
#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 => equal resistors divider = 0.5
|
||||||
|
#define VBAT_DIVIDER (0.5F)
|
||||||
|
// Compensation factor for the VBAT divider
|
||||||
|
#define VBAT_DIVIDER_COMP (2.0F)
|
||||||
|
// 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 (0 + 8) // P0.08
|
||||||
|
#define PIN_WIRE_SCL (0 + 4) // P0.04
|
||||||
|
|
||||||
|
// LED - Bluetooth pairing status indicator
|
||||||
|
#define LED_PAIRING (0 + 15) // P0.15
|
||||||
|
#define LED_STATE_ON 1 // State when LED is lit (active high)
|
||||||
|
|
||||||
|
// Charge detection (P0.13, active high = charging)
|
||||||
|
#define EXT_CHRG_DETECT (0 + 13)
|
||||||
|
#define EXT_CHRG_DETECT_VALUE HIGH
|
||||||
|
|
||||||
|
// Buzzer
|
||||||
|
#define PIN_BUZZER (32 + 11) // P1.11
|
||||||
|
|
||||||
|
// Button
|
||||||
|
#define BUTTON_PIN (0 + 24) // P0.24
|
||||||
|
|
||||||
|
// UART interfaces - no physical serial ports wired
|
||||||
|
#define PIN_SERIAL1_RX (-1)
|
||||||
|
#define PIN_SERIAL1_TX (-1)
|
||||||
|
#define PIN_SERIAL2_RX (-1)
|
||||||
|
#define PIN_SERIAL2_TX (-1)
|
||||||
|
|
||||||
|
// GPS - no GPS hardware
|
||||||
|
#define GPS_RX_PIN (-1)
|
||||||
|
#define GPS_TX_PIN (-1)
|
||||||
|
#define PIN_GPS_EN (-1)
|
||||||
|
#define PIN_GPS_PPS (-1)
|
||||||
|
|
||||||
|
// Serial interfaces
|
||||||
|
#define SPI_INTERFACES_COUNT 1
|
||||||
|
|
||||||
|
#define PIN_SPI_MISO (32 + 0) // P1.00
|
||||||
|
#define PIN_SPI_MOSI (0 + 22) // P0.22
|
||||||
|
#define PIN_SPI_SCK (0 + 20) // P0.20
|
||||||
|
|
||||||
|
#define LORA_MISO PIN_SPI_MISO
|
||||||
|
#define LORA_MOSI PIN_SPI_MOSI
|
||||||
|
#define LORA_SCK PIN_SPI_SCK
|
||||||
|
#define LORA_CS (0 + 17) // P0.17
|
||||||
|
|
||||||
|
// LORA MODULES
|
||||||
|
#define USE_SX1268 // E22-400M33S uses SX1268 (433MHz)
|
||||||
|
|
||||||
|
// E22-400M33S: 33dBm/2W module, PA gain varies with power (non-linear)
|
||||||
|
// Per E22-M UserManual V1.2 power curve: chip 21dBm -> module 33.5dBm (gain ~12.5dB)
|
||||||
|
// TX_GAIN_LORA=12 at max power point; SX126X_MAX_POWER + TX_GAIN_LORA = 33dBm
|
||||||
|
#define SX126X_MAX_POWER 21
|
||||||
|
#define TX_GAIN_LORA 12
|
||||||
|
|
||||||
|
// SX126X CONFIG
|
||||||
|
#define SX126X_CS (0 + 17) // P0.17 FIXME - we really should define LORA_CS instead
|
||||||
|
#define SX126X_DIO1 (32 + 10) // P1.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 + 28) // P0.28 (AIN4)
|
||||||
|
#define SX126X_RESET (32 + 13) // P1.13
|
||||||
|
#define SX126X_RXEN (32 + 9) // P1.09 - E22 RXEN, MCU controls RX/TX RF switch path
|
||||||
|
#define SX126X_TXEN RADIOLIB_NC // DIO2 controls TXEN directly
|
||||||
|
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Arduino objects - C++ only
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user