From 8a3af0c9433869c23f5d369f27b1f80ff99f741f Mon Sep 17 00:00:00 2001 From: metrafonic Date: Thu, 20 Nov 2025 16:35:05 +0100 Subject: [PATCH 1/3] Update Power.h with RAK4631 config from liberatedsystems build --- Power.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/Power.h b/Power.h index 7ce6d8a..cfe2149 100644 --- a/Power.h +++ b/Power.h @@ -68,6 +68,26 @@ float pmu_temperature = PMU_TEMP_MIN-1; bool bat_voltage_dropping = false; float bat_delay_v = 0; float bat_state_change_v = 0; +#elif BOARD_MODEL == BOARD_RAK4631 + #include "nrfx_power.h" + #define BAT_C_SAMPLES 7 + #define BAT_D_SAMPLES 2 + #define BAT_V_MIN 2.75 + #define BAT_V_MAX 4.2 + #define BAT_V_FLOAT 4.22 + #define BAT_SAMPLES 5 + #define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12 - bit ADC resolution = 3000mV / 4096 + #define VBAT_DIVIDER_COMP (1.73) // Compensation factor for the VBAT divider + #define VBAT_MV_PER_LSB_FIN (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) + #define PIN_VBAT WB_A0 + float bat_p_samples[BAT_SAMPLES]; + float bat_v_samples[BAT_SAMPLES]; + uint8_t bat_samples_count = 0; + int bat_discharging_samples = 0; + int bat_charging_samples = 0; + int bat_charged_samples = 0; + bool bat_voltage_dropping = false; + float bat_delay_v = 0; #elif BOARD_MODEL == BOARD_T3S3 #define BAT_V_MIN 3.15 #define BAT_V_MAX 4.217 @@ -387,6 +407,75 @@ void measure_battery() { else { battery_ready = false; } + #elif BOARD_MODEL == BOARD_RAK4631 + battery_installed = true; + battery_indeterminate = false; + + bat_v_samples[bat_samples_count%BAT_SAMPLES] = (float)(analogRead(PIN_VBAT)) * VBAT_MV_PER_LSB_FIN; + + if (bat_v_samples[bat_samples_count%BAT_SAMPLES] < 3300) { + bat_p_samples[bat_samples_count%BAT_SAMPLES] = 0; + } + else if (bat_v_samples[bat_samples_count%BAT_SAMPLES] < 3600) + { + bat_v_samples[bat_samples_count%BAT_SAMPLES] -= 3300; + bat_p_samples[bat_samples_count%BAT_SAMPLES] = bat_v_samples[bat_samples_count%BAT_SAMPLES] / 30; + } else { + bat_v_samples[bat_samples_count%BAT_SAMPLES] -= 3600; + } + bat_p_samples[bat_samples_count%BAT_SAMPLES] = 10 + (bat_v_samples[bat_samples_count%BAT_SAMPLES] * 0.15F); + + bat_samples_count++; + if (!battery_ready && bat_samples_count >= BAT_SAMPLES) { + battery_ready = true; + } + + battery_percent = 0; + for (uint8_t bi = 0; bi < BAT_SAMPLES; bi++) { + battery_percent += bat_p_samples[bi]; + } + battery_percent = battery_percent/BAT_SAMPLES; + + battery_voltage = 0; + for (uint8_t bi = 0; bi < BAT_SAMPLES; bi++) { + battery_voltage += bat_v_samples[bi]; + } + battery_voltage = battery_voltage/BAT_SAMPLES; + + if (bat_delay_v == 0) bat_delay_v = battery_voltage; + if (battery_percent > 100.0) battery_percent = 100.0; + if (battery_percent < 0.0) battery_percent = 0.0; + + if (bat_samples_count%BAT_SAMPLES == 0) { + if (battery_voltage < bat_delay_v && battery_voltage < BAT_V_FLOAT) { + bat_voltage_dropping = true; + } else { + bat_voltage_dropping = false; + } + bat_samples_count = 0; + } + + nrfx_power_usb_state_t usbstate = nrfx_power_usbstatus_get(); + if (usbstate == NRFX_POWER_USB_STATE_CONNECTED || usbstate == NRFX_POWER_USB_STATE_READY) { + // charging + battery_state = BATTERY_STATE_CHARGING; + } else { + battery_state = BATTERY_STATE_DISCHARGING; + } + + if (battery_percent >= 98) { + battery_state = BATTERY_STATE_CHARGED; + } + + #if HAS_BLE + if ((bt_state == BT_STATE_ON) || bt_state == BT_STATE_CONNECTED) { + if (battery_state != BATTERY_STATE_CHARGING) { + blebas.write(battery_percent); + } else { + blebas.write(100); + } + } + #endif #endif if (battery_ready) { @@ -564,6 +653,21 @@ bool init_pmu() { PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S); return true; + #elif BOARD_MODEL == BOARD_RAK4631 + // board doesn't have PMU but we can measure batt voltage + + // prep ADC for reading battery level + analogReference(AR_INTERNAL_3_0); + + // Set the resolution to 12-bit (0..4095) + analogReadResolution(12); + + // Let the ADC settle + delay(1); + + // Get a single ADC sample and throw it away + float raw = analogRead(PIN_VBAT); + return true; #elif BOARD_MODEL == BOARD_TBEAM_S_V1 Wire1.begin(I2C_SDA, I2C_SCL); From bbaddfbb6636522aca08bed9fe93ee811c145059 Mon Sep 17 00:00:00 2001 From: metrafonic Date: Thu, 20 Nov 2025 17:36:33 +0100 Subject: [PATCH 2/3] Enable PMU on RAK and set user button to exposed pin --- Boards.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Boards.h b/Boards.h index eaee2d5..d39f03c 100644 --- a/Boards.h +++ b/Boards.h @@ -715,7 +715,7 @@ #define HAS_BLUETOOTH false #define HAS_BLE true #define HAS_CONSOLE false - #define HAS_PMU false + #define HAS_PMU true #define HAS_NP false #define HAS_SD false #define HAS_TCXO true @@ -731,7 +731,7 @@ #define BLE_MANUFACTURER "RAK Wireless" #define BLE_MODEL "RAK4640" - const int pin_btn_usr1 = 9; + const int pin_btn_usr1 = 31; // Following pins are for the sx1262 const int pin_rxen = 37; From e7491b1eff9527ab6ae99374b033f1f81d8600d5 Mon Sep 17 00:00:00 2001 From: metrafonic Date: Fri, 21 Nov 2025 19:51:25 +0100 Subject: [PATCH 3/3] Enable sleep on RAK4631 --- Boards.h | 6 +++++- RNode_Firmware.ino | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Boards.h b/Boards.h index d39f03c..9b05536 100644 --- a/Boards.h +++ b/Boards.h @@ -710,6 +710,7 @@ #elif MCU_VARIANT == MCU_NRF52 #if BOARD_MODEL == BOARD_RAK4631 + #define _PINNUM(port, pin) ((port) * 32 + (pin)) #define HAS_EEPROM false #define HAS_DISPLAY true #define HAS_BLUETOOTH false @@ -722,6 +723,7 @@ #define HAS_RF_SWITCH_RX_TX true #define HAS_BUSY true #define HAS_INPUT true + #define HAS_SLEEP true #define DIO2_AS_RF_SWITCH true #define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_QUEUE_SIZE 6144 @@ -731,7 +733,9 @@ #define BLE_MANUFACTURER "RAK Wireless" #define BLE_MODEL "RAK4640" - const int pin_btn_usr1 = 31; + #define PIN_VEXT_EN _PINNUM(1, 2) + + const int pin_btn_usr1 = _PINNUM(0, 31); // Following pins are for the sx1262 const int pin_rxen = 37; diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 111f171..82fed9e 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -88,6 +88,11 @@ void setup() { pinMode(PIN_LED_GREEN, OUTPUT); pinMode(PIN_LED_BLUE, OUTPUT); delay(200); + #elif BOARD_MODEL == BOARD_RAK4631 + delay(200); + pinMode(PIN_VEXT_EN, OUTPUT); + digitalWrite(PIN_VEXT_EN, HIGH); + delay(200); #endif if (!eeprom_begin()) { Serial.write("EEPROM initialisation failed.\r\n"); } @@ -1773,6 +1778,12 @@ void sleep_now() { delay(2000); analogWrite(PIN_VEXT_EN, 0); delay(100); + #elif BOARD_MODEL == BOARD_RAK4631 + #if HAS_DISPLAY + display_intensity = 0; + update_display(true); + #endif + analogWrite(PIN_VEXT_EN, 0); #endif sd_power_gpregret_set(0, 0x6d); nrf_gpio_cfg_sense_input(pin_btn_usr1, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);