Skip to content

Commit

Permalink
new power management task for Hex
Browse files Browse the repository at this point in the history
  • Loading branch information
macphyter committed Feb 10, 2024
1 parent a246efd commit d448201
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 57 deletions.
84 changes: 55 additions & 29 deletions main/TPS546.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ static esp_err_t smb_read_block(uint8_t command, uint8_t *data, uint8_t len)
}
i2c_master_read_byte(cmd, &data[slave_len - 1], NACK_VALUE);
i2c_master_stop(cmd);
i2c_set_timeout(I2C_MASTER_NUM, 20);
ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT));
i2c_cmd_link_delete(cmd);

Expand Down Expand Up @@ -208,7 +207,6 @@ static int slinear11_2_int(uint16_t value)

// calculate result (mantissa * 2^exponent)
result = mantissa * powf(2.0, exponent);
ESP_LOGI(TAG, "result: %f", result);
return (int)result;
}

Expand Down Expand Up @@ -274,9 +272,6 @@ static uint16_t int_2_slinear11(int value)

result = ((exponent << 11) & 0xF800) + mantissa;

//ESP_LOGI(TAG, "mantissa: %d, exponent: %d", mantissa, exponent);
//ESP_LOGI(TAG, "result: %04x", result);

return result;
}

Expand Down Expand Up @@ -313,9 +308,6 @@ static uint16_t float_2_slinear11(float value)

result = (( (~exponent + 1) << 11) & 0xF800) + mantissa;

//ESP_LOGI(TAG, "mantissa: %d, exponent: -%d", mantissa, exponent);
//ESP_LOGI(TAG, "result: %04x", result);

return result;
}

Expand All @@ -339,8 +331,6 @@ static int ulinear16_2_float(uint16_t value)
exponent = (voutmode & 0x1F);
}

//ESP_LOGI(TAG, "value: %04x", value);
//ESP_LOGI(TAG, "mantissa: %d, exponent: %d", value, exponent);
result = (value * powf(2.0, exponent));
return result;
}
Expand All @@ -366,7 +356,6 @@ static uint16_t float_2_ulinear16(float value)
}

result = (value / powf(2.0, exponent));
ESP_LOGI(TAG, "result: %04x, exponent: %f", result, exponent);

return result;
}
Expand Down Expand Up @@ -430,21 +419,22 @@ int TPS546_init(void)

ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
/* Get voltage input (SLINEAR11) */
smb_read_word(PMBUS_READ_VIN, &u16_value);
vin = slinear11_2_float(u16_value);
ESP_LOGI(TAG, "Vin measured: %2.3f V", vin);
//smb_read_word(PMBUS_READ_VIN, &u16_value);
//vin = slinear11_2_float(u16_value);
//ESP_LOGI(TAG, "Vin measured: %2.3f V", vin);
TPS546_get_vin();

/* Get output current (SLINEAR11) */
smb_read_word(PMBUS_READ_IOUT, &u16_value);
iout = slinear11_2_float(u16_value);
ESP_LOGI(TAG, "Iout measured: %2.3f A", iout);
//smb_read_word(PMBUS_READ_IOUT, &u16_value);
//iout = slinear11_2_float(u16_value);
//ESP_LOGI(TAG, "Iout measured: %2.3f A", iout);
TPS546_get_iout();

/* Get voltage output (ULINEAR16) */
// This gets a timeout, don't know why. clock stretching?
// Should take about 91 uS
smb_read_word(PMBUS_READ_VOUT, &u16_value);
vout = ulinear16_2_float(u16_value);
ESP_LOGI(TAG, "Vout measured: %2.3f V", vout);
//smb_read_word(PMBUS_READ_VOUT, &u16_value);
//vout = ulinear16_2_float(u16_value);
//ESP_LOGI(TAG, "Vout measured: %2.3f V", vout);
TPS546_get_vout();

ESP_LOGI(TAG, "-----------TIMING---------------------");
smb_read_word(PMBUS_TON_DELAY, &u16_value);
Expand Down Expand Up @@ -530,12 +520,16 @@ void TPS546_write_entire_config(void)
smb_write_word(PMBUS_VOUT_COMMAND, float_2_ulinear16(TPS546_INIT_VOUT_COMMAND));
ESP_LOGI(TAG, "VOUT_MAX");
smb_write_word(PMBUS_VOUT_MAX, float_2_ulinear16(TPS546_INIT_VOUT_MAX));
ESP_LOGI(TAG, "VOUT_MAX_OV_FAULT_LIMIT");
ESP_LOGI(TAG, "VOUT_OV_FAULT_LIMIT");
smb_write_word(PMBUS_VOUT_OV_FAULT_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_FAULT_LIMIT));
ESP_LOGI(TAG, "VOUT_OV_WARN_LIMIT");
//smb_write_word(PMBUS_VOUT_OV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_WARN_LIMIT));
smb_write_word(PMBUS_VOUT_OV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_WARN_LIMIT));
ESP_LOGI(TAG, "VOUT_MARGIN_HIGH");
smb_write_word(PMBUS_VOUT_MARGIN_HIGH, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_HIGH));
ESP_LOGI(TAG, "VOUT_MARGIN_LOW");
smb_write_word(PMBUS_VOUT_MARGIN_LOW, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_LOW));
ESP_LOGI(TAG, "VOUT_UV_WARN_LIMIT");
//smb_write_word(PMBUS_VOUT_UV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_WARN_LIMIT));
smb_write_word(PMBUS_VOUT_UV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_WARN_LIMIT));
ESP_LOGI(TAG, "VOUT_UV_FAULT_LIMIT");
smb_write_word(PMBUS_VOUT_UV_FAULT_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_FAULT_LIMIT));
ESP_LOGI(TAG, "VOUT_MIN");
Expand Down Expand Up @@ -572,9 +566,6 @@ void TPS546_write_entire_config(void)
//ESP_LOGI(TAG, "COMPENSATION");
//smb_write_block(PMBUS_COMPENSATION_CONFIG, COMPENSATION_CONFIG, 5);

/* Slave address */
//smb_write_byte(PMBUS_SLAVE_ADDRESS, TPS546_I2CADDR);

/* configure the bootup behavior regarding pin detect values vs NVM values */
ESP_LOGI(TAG, "Setting PIN_DETECT_OVERRIDE");
smb_write_word(PMBUS_PIN_DETECT_OVERRIDE, INIT_PIN_DETECT_OVERRIDE);
Expand All @@ -589,7 +580,7 @@ void TPS546_write_entire_config(void)

/* store configuration in NVM */
ESP_LOGI(TAG, "---Saving new config---");
//smb_write_byte(PMBUS_STORE_USER_ALL, 0xFF);
smb_write_byte(PMBUS_STORE_USER_ALL, 0x98);

}

Expand Down Expand Up @@ -635,6 +626,41 @@ int TPS546_get_temperature(void)
return temp;
}

float TPS546_get_vin(void)
{
uint16_t u16_value;
float vin;

/* Get voltage input (ULINEAR16) */
smb_read_word(PMBUS_READ_VIN, &u16_value);
vin = slinear11_2_float(u16_value);
ESP_LOGI(TAG, "Got Vin: %2.3f V", vin);
return vin;
}

float TPS546_get_iout(void)
{
uint16_t u16_value;
float iout;

/* Get current output (SLINEAR11) */
smb_read_word(PMBUS_READ_IOUT, &u16_value);
iout = slinear11_2_float(u16_value);
ESP_LOGI(TAG, "Got Iout: %2.3f V", iout);
return iout;
}

float TPS546_get_vout(void)
{
uint16_t u16_value;
float vout;

/* Get voltage output (ULINEAR16) */
smb_read_word(PMBUS_READ_VOUT, &u16_value);
vout = ulinear16_2_float(u16_value);
ESP_LOGI(TAG, "Got Vout: %2.3f V", vout);
return vout;
}

/**
* @brief Sets the core voltage
Expand Down
21 changes: 13 additions & 8 deletions main/TPS546.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@

/* vout voltage */
#define TPS546_INIT_SCALE_LOOP 0xC808 /* 0.125 */
#define TPS546_INIT_VOUT_MAX 5.00 /* V */
#define TPS546_INIT_VOUT_OV_FAULT_LIMIT 1.20 /* V relative to VOUT_COMMAND */
#define TPS546_INIT_VOUT_OV_WARN_LIMIT 0.90 /* V relative to VOUT_COMMAND */
#define TPS546_INIT_VOUT_COMMAND 3.60 /* V absolute value */
#define TPS546_INIT_VOUT_UV_WARN_LIMIT 0.50 /* V relative to VOUT_COMMAND */
#define TPS546_INIT_VOUT_UV_FAULT_LIMIT 0.60 /* V relative to VOUT_COMMAND */
#define TPS546_INIT_VOUT_MIN 3.00 /* v */
#define TPS546_INIT_VOUT_MAX 4.50 /* V */
#define TPS546_INIT_VOUT_OV_FAULT_LIMIT 1.25 /* %/100 above VOUT_COMMAND */
#define TPS546_INIT_VOUT_OV_WARN_LIMIT 1.1 /* %/100 above VOUT_COMMAND */
#define TPS546_INIT_VOUT_MARGIN_HIGH 1.1 /* %/100 above VOUT */
#define TPS546_INIT_VOUT_COMMAND 3.60 /* V absolute value */
#define TPS546_INIT_VOUT_MARGIN_LOW 0.90 /* %/100 below VOUT */
#define TPS546_INIT_VOUT_UV_WARN_LIMIT 0.90 /* %/100 below VOUT_COMMAND */
#define TPS546_INIT_VOUT_UV_FAULT_LIMIT 0.75 /* %/100 below VOUT_COMMAND */
#define TPS546_INIT_VOUT_MIN 2.5 /* v */

/* iout current */
#define TPS546_INIT_IOUT_OC_WARN_LIMIT 25.00 /* A */
#define TPS546_INIT_IOUT_OC_WARN_LIMIT 25.00 /* A */
#define TPS546_INIT_IOUT_OC_FAULT_LIMIT 30.00 /* A */
#define TPS546_INIT_IOUT_OC_FAULT_RESPONSE 0xC0 /* shut down, no retries */

Expand Down Expand Up @@ -73,6 +75,9 @@ void TPS546_write_entire_config(void);
int TPS546_get_frequency(void);
void TPS546_set_frequency(int);
int TPS546_get_temperature(void);
float TPS546_get_vin(void);
float TPS546_get_iout(void);
float TPS546_get_vout(void);
void TPS546_set_vout(int millivolts);
void TPS546_show_voltage_settings(void);

Expand Down
12 changes: 11 additions & 1 deletion main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,18 @@ void app_main(void)
GLOBAL_STATE.SYSTEM_MODULE.startup_done = true;

xTaskCreate(USER_INPUT_task, "user input", 8192, (void *) &GLOBAL_STATE, 5, NULL);
xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL);

if (strcmp(GLOBAL_STATE.board_version, "302") == 0) {
// this is a HEX board
ESP_LOGI(TAG, "Starting HEX power management");
xTaskCreate(POWER_MANAGEMENT_HEX_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL);
} else {
// this is NOT a HEX board
ESP_LOGI(TAG, "Starting BITAXE power management");
xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL);
}

ESP_LOGI(TAG, "Starting init functions");
if (GLOBAL_STATE.ASIC_functions.init_fn != NULL) {
wifi_softap_off();

Expand Down
115 changes: 98 additions & 17 deletions main/tasks/power_management_task.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "DS4432U.h"
#include "EMC2101.h"
#include "INA260.h"
#include "TPS546.h"
#include "TMP1075.h"
#include "bm1397.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
Expand All @@ -17,6 +19,8 @@
#define THROTTLE_TEMP 75.0
#define THROTTLE_TEMP_RANGE (MAX_TEMP - THROTTLE_TEMP)

#define TPS546_THROTTLE_TEMP 105.0

#define VOLTAGE_START_THROTTLE 4900
#define VOLTAGE_MIN_THROTTLE 3500
#define VOLTAGE_RANGE (VOLTAGE_START_THROTTLE - VOLTAGE_MIN_THROTTLE)
Expand All @@ -33,9 +37,29 @@ static float _fbound(float value, float lower_bound, float upper_bound)
return value;
}

void POWER_MANAGEMENT_task(void * pvParameters)
// Set the fan speed between 20% min and 100% max based on chip temperature as input.
// The fan speed increases from 20% to 100% proportionally to the temperature increase from 50 and THROTTLE_TEMP
static void automatic_fan_speed(float chip_temp)
{
double result = 0.0;
double min_temp = 50.0;
double min_fan_speed = 20.0;

if (chip_temp < min_temp) {
result = min_fan_speed;
} else if (chip_temp >= THROTTLE_TEMP) {
result = 100;
} else {
double temp_range = THROTTLE_TEMP - min_temp;
double fan_range = 100 - min_fan_speed;
result = ((chip_temp - min_temp) / temp_range) * fan_range + min_fan_speed;
}

EMC2101_set_fan_speed((float) result / 100);
}

void POWER_MANAGEMENT_task(void * pvParameters)
{
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;

PowerManagementModule * power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE;
Expand Down Expand Up @@ -183,23 +207,80 @@ void POWER_MANAGEMENT_task(void * pvParameters)
}
}

// Set the fan speed between 20% min and 100% max based on chip temperature as input.
// The fan speed increases from 20% to 100% proportionally to the temperature increase from 50 and THROTTLE_TEMP
static void automatic_fan_speed(float chip_temp)

void POWER_MANAGEMENT_HEX_task(void * pvParameters)
{
double result = 0.0;
double min_temp = 50.0;
double min_fan_speed = 20.0;
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;

if (chip_temp < min_temp) {
result = min_fan_speed;
} else if (chip_temp >= THROTTLE_TEMP) {
result = 100;
} else {
double temp_range = THROTTLE_TEMP - min_temp;
double fan_range = 100 - min_fan_speed;
result = ((chip_temp - min_temp) / temp_range) * fan_range + min_fan_speed;
}
PowerManagementModule * power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE;

EMC2101_set_fan_speed((float) result / 100);
power_management->frequency_multiplier = 1;

char * board_version = nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "unknown");
power_management->HAS_POWER_EN =
(strcmp(board_version, "202") == 1 || strcmp(board_version, "203") == 1 || strcmp(board_version, "204") == 1);
power_management->HAS_PLUG_SENSE = strcmp(board_version, "204") == 1;
free(board_version);

int last_frequency_increase = 0;

uint16_t frequency_target = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);

uint16_t auto_fan_speed = nvs_config_get_u16(NVS_CONFIG_AUTO_FAN_SPEED, 1);

// turn on ASIC core voltage (three domains in series)
TPS546_set_vout(3600);

vTaskDelay(3000 / portTICK_PERIOD_MS);

while (1) {

// use TPS546_get_vin() for input voltage

power_management->voltage = TPS546_get_vout();
power_management->current = TPS546_get_iout();
// calculate ASIC power consumed (in milliwatts)
power_management->power = (power_management->voltage * power_management->current) / 1000;

// TODO fix fan driver
//power_management->fan_speed = EMC2101_get_fan_speed();

// Two board temperature sensors
ESP_LOGI(TAG, "Board Temp: %d, %d", TMP1075_read_temperature(0), TMP1075_read_temperature(1));

// get regulator internal temperature
power_management->chip_temp = (float)TPS546_get_temperature();
ESP_LOGI(TAG, "TPS546 Temp: %f", power_management->chip_temp);

// TODO figure out best way to detect overheating on the Hex
if (power_management->chip_temp > TPS546_THROTTLE_TEMP &&
(power_management->frequency_value > 50 || power_management->voltage > 1000)) {
ESP_LOGE(TAG, "OVERHEAT");

// Turn off core voltage
TPS546_set_vout(0);

nvs_config_set_u16(NVS_CONFIG_ASIC_VOLTAGE, 990);
nvs_config_set_u16(NVS_CONFIG_ASIC_FREQ, 50);
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, 100);
nvs_config_set_u16(NVS_CONFIG_AUTO_FAN_SPEED, 0);
exit(EXIT_FAILURE);
}

// TODO fix fan driver
//if (auto_fan_speed == 1) {
// automatic_fan_speed(power_management->chip_temp);
//} else {
// EMC2101_set_fan_speed((float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100) / 100);
//}

ESP_LOGI(TAG, "TPS546 VIN: %f, VOUT: %f, IOUT: %f", TPS546_get_vin(), TPS546_get_vout(), TPS546_get_iout());
ESP_LOGI(TAG, "Regulator power: %f mW", power_management->power);

//ESP_LOGI(TAG, "Frequency target %f, Freq %f", target_frequency, power_management->frequency_value);
ESP_LOGI(TAG, "Frequency %d", TPS546_get_frequency());

vTaskDelay(POLL_RATE / portTICK_PERIOD_MS);
}
}

4 changes: 2 additions & 2 deletions main/tasks/power_management_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ typedef struct

static void automatic_fan_speed(float chip_temp);
void POWER_MANAGEMENT_task(void * pvParameters);

#endif
void POWER_MANAGEMENT_HEX_task(void * pvParameters);
#endif

0 comments on commit d448201

Please sign in to comment.