This commit is contained in:
Thomas Göttgens 2025-06-07 23:09:19 +02:00 committed by GitHub
commit d24e11cd43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 225 additions and 23 deletions

View File

@ -26,6 +26,7 @@ build_flags = -Wno-missing-field-initializers
-DUSE_THREAD_NAMES -DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS -DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1 -DPB_ENABLE_MALLOC=1
-DRADIOLIB_LOW_LEVEL=1
-DRADIOLIB_EXCLUDE_CC1101=1 -DRADIOLIB_EXCLUDE_CC1101=1
-DRADIOLIB_EXCLUDE_NRF24=1 -DRADIOLIB_EXCLUDE_NRF24=1
-DRADIOLIB_EXCLUDE_RF69=1 -DRADIOLIB_EXCLUDE_RF69=1

View File

@ -193,6 +193,8 @@ bool pauseBluetoothLogging = false;
bool pmu_found; bool pmu_found;
uint8_t pa_fan_percentage = 50;
#if !MESHTASTIC_EXCLUDE_I2C #if !MESHTASTIC_EXCLUDE_I2C
// Array map of sensor types with i2c address and wire as we'll find in the i2c scan // Array map of sensor types with i2c address and wire as we'll find in the i2c scan
std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {}; std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {};
@ -1227,11 +1229,31 @@ void setup()
mqttInit(); mqttInit();
#endif #endif
#ifdef RF95_FAN_EN #ifdef RADIO_FAN_EN
// Ability to disable FAN if PIN has been set with RF95_FAN_EN. // Ability to disable FAN if PIN has been set with RADIO_FAN_EN.
// Make sure LoRa has been started before disabling FAN. // Make sure LoRa has been started before disabling FAN.
if (config.lora.pa_fan_disabled) #ifdef RADIO_FAN_PWM
digitalWrite(RF95_FAN_EN, LOW ^ 0); #if defined(ARCH_ESP32)
// Set up PWM at Channel 1 at 25KHz, using 8-bit resolution
// Turn ON/OFF fan to the specified value if enabled by config.
// code by https://github.com/gjelsoe/
if (ledcSetup(1, 25000, 8)) {
ledcAttachPin(RADIO_FAN_EN, 1);
LOG_INFO("PWM init C1 P%d\n", RADIO_FAN_EN);
// Set PWM duty cycle based on fan disabled state
ledcWrite(1, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
} else {
LOG_WARN("PWM init fail P%d\n", RADIO_FAN_EN);
}
#elif defined(ARCH_NRF52)
pinMode(RADIO_FAN_EN, OUTPUT);
analogWrite(RADIO_FAN_EN, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#endif
#else
// Set up as ON/OFF switch of fan
pinMode(RADIO_FAN_EN, OUTPUT);
digitalWrite(RADIO_FAN_EN, LOW ^ 0);
#endif
#endif #endif
#ifndef ARCH_PORTDUINO #ifndef ARCH_PORTDUINO

View File

@ -77,6 +77,8 @@ extern uint32_t shutdownAtMsec;
extern uint32_t serialSinceMsec; extern uint32_t serialSinceMsec;
extern uint8_t pa_fan_percentage;
// If a thread does something that might need for it to be rescheduled ASAP it can set this flag // If a thread does something that might need for it to be rescheduled ASAP it can set this flag
// This will suppress the current delay and instead try to run ASAP. // This will suppress the current delay and instead try to run ASAP.
extern bool runASAP; extern bool runASAP;

View File

@ -3,6 +3,7 @@
#include "Throttle.h" #include "Throttle.h"
#include "configuration.h" #include "configuration.h"
#include "error.h" #include "error.h"
#include "main.h"
#include "mesh/NodeDB.h" #include "mesh/NodeDB.h"
#ifdef LR11X0_DIO_AS_RF_SWITCH #ifdef LR11X0_DIO_AS_RF_SWITCH
#include "rfswitch.h" #include "rfswitch.h"
@ -54,6 +55,8 @@ template <typename T> bool LR11x0Interface<T>::init()
digitalWrite(LR11X0_POWER_EN, HIGH); digitalWrite(LR11X0_POWER_EN, HIGH);
#endif #endif
enableFan();
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
// FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE // FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE

View File

@ -157,10 +157,7 @@ bool RF95Interface::init()
digitalWrite(RF95_TXEN, 0); digitalWrite(RF95_TXEN, 0);
#endif #endif
#ifdef RF95_FAN_EN enableFan();
pinMode(RF95_FAN_EN, OUTPUT);
digitalWrite(RF95_FAN_EN, 1);
#endif
#ifdef RF95_RXEN #ifdef RF95_RXEN
pinMode(RF95_RXEN, OUTPUT); pinMode(RF95_RXEN, OUTPUT);
@ -333,10 +330,7 @@ bool RF95Interface::sleep()
// put chipset into sleep mode // put chipset into sleep mode
setStandby(); // First cancel any active receiving/sending setStandby(); // First cancel any active receiving/sending
lora->sleep(); lora->sleep();
disableFan();
#ifdef RF95_FAN_EN
digitalWrite(RF95_FAN_EN, 0);
#endif
return true; return true;
} }

View File

@ -532,3 +532,36 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
return res == RADIOLIB_ERR_NONE; return res == RADIOLIB_ERR_NONE;
} }
} }
void RadioLibInterface::enableFan()
{
#ifdef RADIO_FAN_EN
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
ledcWrite(1, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#elif defined(ARCH_NRF52)
analogWrite(RADIO_FAN_EN, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#endif
#else
pinMode(RADIO_FAN_EN, OUTPUT);
digitalWrite(RADIO_FAN_EN, 1);
#endif
#endif
}
void RadioLibInterface::disableFan()
{
#ifdef RADIO_FAN_EN
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
ledcWrite(1, 0);
#elif defined(ARCH_NRF52)
analogWrite(RADIO_FAN_EN, 0);
#endif
#else
pinMode(RADIO_FAN_EN, OUTPUT);
digitalWrite(RADIO_FAN_EN, 0);
#endif
#endif
}

View File

@ -146,6 +146,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
/** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */ /** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */
virtual bool findInTxQueue(NodeNum from, PacketId id) override; virtual bool findInTxQueue(NodeNum from, PacketId id) override;
void enableFan();
void disableFan();
private: private:
/** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually /** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually
* doing the transmit */ * doing the transmit */

View File

@ -52,6 +52,8 @@ template <typename T> bool SX126xInterface<T>::init()
pinMode(SX126X_POWER_EN, OUTPUT); pinMode(SX126X_POWER_EN, OUTPUT);
#endif #endif
enableFan();
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) { if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) {

View File

@ -35,10 +35,7 @@ template <typename T> bool SX128xInterface<T>::init()
digitalWrite(SX128X_POWER_EN, HIGH); digitalWrite(SX128X_POWER_EN, HIGH);
#endif #endif
#ifdef RF95_FAN_EN enableFan();
pinMode(RF95_FAN_EN, OUTPUT);
digitalWrite(RF95_FAN_EN, 1);
#endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (settingsMap[rxen_pin] != RADIOLIB_NC) {

View File

@ -650,13 +650,21 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
requiresReboot = false; requiresReboot = false;
} }
#ifdef RF95_FAN_EN #ifdef RADIO_FAN_EN
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
ledcWrite(1, c.payload_variant.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#elif defined(ARCH_NFR52)
analogWrite(RADIO_FAN_EN, c.payload_variant.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#endif
#else
// Turn PA off if disabled by config // Turn PA off if disabled by config
if (c.payload_variant.lora.pa_fan_disabled) { if (c.payload_variant.lora.pa_fan_disabled) {
digitalWrite(RF95_FAN_EN, LOW ^ 0); digitalWrite(RADIO_FAN_EN, LOW ^ 0);
} else { } else {
digitalWrite(RF95_FAN_EN, HIGH ^ 0); digitalWrite(RADIO_FAN_EN, HIGH ^ 0);
} }
#endif
#endif #endif
config.lora = c.payload_variant.lora; config.lora = c.payload_variant.lora;
// If we're setting region for the first time, init the region // If we're setting region for the first time, init the region

View File

@ -12,7 +12,7 @@
#define LORA_MISO 19 #define LORA_MISO 19
#define LORA_MOSI 23 #define LORA_MOSI 23
#define LORA_CS 5 #define LORA_CS 5
#define RF95_FAN_EN 17 #define RADIO_FAN_EN 17
// #define LED_PIN 16 // This is a LED_WS2812 not a standard LED // #define LED_PIN 16 // This is a LED_WS2812 not a standard LED
#define HAS_NEOPIXEL // Enable the use of neopixels #define HAS_NEOPIXEL // Enable the use of neopixels

View File

@ -46,7 +46,8 @@
FAN is active at 250mW on it's ExpressLRS Firmware. FAN is active at 250mW on it's ExpressLRS Firmware.
This FAN has TACHO signal on Pin 27 for use with PWM. This FAN has TACHO signal on Pin 27 for use with PWM.
*/ */
#define RF95_FAN_EN 2 #define RADIO_FAN_EN 2
#define RADIO_FAN_PWM
/* /*
LED PIN setup and it has a NeoPixel LED. LED PIN setup and it has a NeoPixel LED.

View File

@ -32,7 +32,7 @@
This unit has a FAN built-in. This unit has a FAN built-in.
FAN is active at 250mW on it's ExpressLRS Firmware. FAN is active at 250mW on it's ExpressLRS Firmware.
*/ */
#define RF95_FAN_EN 2 #define RADIO_FAN_EN 2
/* /*
LED PIN setup. LED PIN setup.

View File

@ -0,0 +1,20 @@
[env:radiomaster_nomad_gemini]
extends = esp32_base
board = esp32doit-devkit-v1
build_flags =
${esp32_base.build_flags}
-DRADIOMASTER_NOMAD_GEMINI
-DPRIVATE_HW
-DVTABLES_IN_FLASH=1
-DCONFIG_DISABLE_HAL_LOCKS=1
-O2
-Ivariants/radiomaster_nomad_gemini
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
-DMESHTASTIC_EXCLUDE_I2C=1
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_SX126X=1
board_build.f_cpu = 240000000L
upload_protocol = esptool
lib_deps =
${esp32_base.lib_deps}

View File

@ -0,0 +1,56 @@
#include "RadioLib.h"
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7,
RADIOLIB_LR11X0_DIO8, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6 DIO7 DIO8
{LR11x0::MODE_STBY, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_RX, {LOW, LOW, HIGH, LOW}},
{LR11x0::MODE_TX, {LOW, LOW, LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, LOW, LOW, HIGH}},
{LR11x0::MODE_TX_HF, {LOW, HIGH, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, LOW, LOW}},
{LR11x0::MODE_WIFI, {HIGH, LOW, LOW, LOW}}, END_OF_MODE_TABLE,
};
/*
DIO5: RXEN 2.4GHz
DIO6: TXEN 2.4GHz
DIO7: RXEN 900MHz
DIO8: TXEN 900MHz
"radio_dcdc": true,
"radio_rfo_hf": true,
"power_apc2": 26,
"power_min": 0,
"power_high": 6,
"power_max": 6,
"power_default": 3,
"power_control": 3, POWER_OUTPUT_DACWRITE // use internal dacWrite function to set value on GPIO_PIN_RFamp_APC2
[0, 1, 2, 3, 4, 5, 6 ] // 0-6
"power_values": [120, 120, 120, 120, 120, 120, 95] // DAC Value
"power_values2": [-17, -16, -14, -11, -7, -3, 5 ] // 900M
"power_values_dual": [-18, -14, -8, -6, -2, 3, 5 ] // 2.4G
// default value 0 means direct!
#define POWER_OUTPUT_DACWRITE (hardware_int(HARDWARE_power_control)==3)
#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values)
#define POWER_OUTPUT_VALUES_COUNT hardware_int(HARDWARE_power_values_count)
#define POWER_OUTPUT_VALUES2 hardware_i16_array(HARDWARE_power_values2)
#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual)
#define POWER_OUTPUT_VALUES_DUAL_COUNT hardware_int(HARDWARE_power_values_dual_count)
#define GPIO_PIN_FAN_EN hardware_pin(HARDWARE_misc_fan_en)
case PWR_10mW: return 10;
case PWR_25mW: return 14;
case PWR_50mW: return 17;
case PWR_100mW: return 20;
case PWR_250mW: return 24;
case PWR_500mW: return 27;
case PWR_1000mW: return 30;
95 -> +25dBm
120 -> +24dBm
*/

View File

@ -0,0 +1,60 @@
#define HAS_SCREEN 0
#define HAS_WIRE 0
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define PIN_SPI_MISO 33
#define PIN_SPI_MOSI 32
#define PIN_SPI_SCK 25
#define PIN_SPI_NSS 27
#define LORA_RESET 15
#define LORA_DIO1 37
#define LORA_DIO2 36
#define LORA_SCK PIN_SPI_SCK
#define LORA_MISO PIN_SPI_MISO
#define LORA_MOSI PIN_SPI_MOSI
#define LORA_CS PIN_SPI_NSS
// supported modules list
#define USE_LR1121
#define LR1121_IRQ_PIN LORA_DIO1
#define LR1121_NRESET_PIN LORA_RESET
#define LR1121_BUSY_PIN LORA_DIO2
#define LR1121_SPI_NSS_PIN LORA_CS
#define LR1121_SPI_SCK_PIN LORA_SCK
#define LR1121_SPI_MOSI_PIN LORA_MOSI
#define LR1121_SPI_MISO_PIN LORA_MISO
// this is correct and sets the cap for the Sub-GHz part
#define LR1110_MAX_POWER 5
// 2.4G Part
#define LR1120_MAX_POWER 5
#define POWER_SHIFT -20
// not yet implemented
#define JANUS_RADIO
#define LR1121_IRQ2_PIN 34
#define LR1121_NRESET2_PIN 21
#define LR1121_BUSY2_PIN 39
#define LR1121_SPI_NSS2_PIN 13
// TODO: check if this is correct
// #define LR11X0_DIO3_TCXO_VOLTAGE 1.6
#define LR11X0_DIO_AS_RF_SWITCH
#define HAS_NEOPIXEL // Enable the use of neopixels
#define NEOPIXEL_COUNT 2 // How many neopixels are connected
#define NEOPIXEL_DATA 22 // GPIO pin used to send data to the neopixels
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // Type of neopixels in use
#define ENABLE_AMBIENTLIGHTING // Turn on Ambient Lighting
#define BUTTON_PIN 34
#define BUTTON_NEED_PULLUP
#undef EXT_NOTIFY_OUT
#define RADIO_FAN_EN 2