diff --git a/Boards.h b/Boards.h index ef2b8c5..0a47653 100644 --- a/Boards.h +++ b/Boards.h @@ -712,18 +712,20 @@ #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 #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 #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 @@ -733,7 +735,9 @@ #define BLE_MANUFACTURER "RAK Wireless" #define BLE_MODEL "RAK4640" - const int pin_btn_usr1 = 9; + #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/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); diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 5649206..d90e1bb 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"); } @@ -1796,6 +1801,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);