diff --git a/main/EMC2302.c b/main/EMC2302.c index 3f361ff89..f59a9a692 100644 --- a/main/EMC2302.c +++ b/main/EMC2302.c @@ -41,38 +41,81 @@ static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) // run this first. sets up the PWM polarity register void EMC2302_init(bool invertPolarity) { + uint8_t read_byte; + uint8_t fan_config1; - if (invertPolarity) { - ESP_ERROR_CHECK(register_write_byte(EMC2302_PWM_POLARITY, 0b00011111)); - } + // Read the manufacturer ID + ESP_ERROR_CHECK(register_read(EMC2302_MANUFACTURER_ID, &read_byte, 1)); + ESP_LOGI(TAG, "Manufacturer ID = %02x", read_byte); + + // Read the product ID + ESP_ERROR_CHECK(register_read(EMC2302_PRODUCT_ID, &read_byte, 1)); + ESP_LOGI(TAG, "Product ID = %02x", read_byte); + + // Read the + ESP_ERROR_CHECK(register_read(EMC2302_SILICON_REVISION, &read_byte, 1)); + ESP_LOGI(TAG, "Silicon Revision = %02x", read_byte); + + fan_config1 = 0x98; // 10011000 + ESP_ERROR_CHECK(register_write_byte(EMC2302_FAN1_CONFIG1, fan_config1)); + ESP_ERROR_CHECK(register_write_byte(EMC2302_FAN2_CONFIG1, fan_config1)); + + //if (invertPolarity) { + // ESP_ERROR_CHECK(register_write_byte(EMC2302_PWM_POLARITY, 0b00011111)); + //} } // Sets the fan speed to a given percent void EMC2302_set_fan_speed(uint8_t devicenum, float percent) { - uint8_t speed; - uint8_t FAN_SETTING_REG = EMC2302_FAN1_SETTING + (devicenum * 0x10); - - speed = (uint8_t) (63.0 * percent); - ESP_ERROR_CHECK(register_write_byte(FAN_SETTING_REG, speed)); + int max_rpm = 2400; + int req_rpm = max_rpm * (percent / 100); + uint16_t tach_counts; + uint8_t TACH_MSB_REG = EMC2302_TACH1_TARGET_MSB + (devicenum * 0x10); + uint8_t TACH_LSB_REG = EMC2302_TACH1_TARGET_LSB + (devicenum * 0x10); + uint8_t tach_counts_MSB; + uint8_t tach_counts_LSB; + + int poles = 4; // motor poles + int edges = 9; // motor edges + int ftach = 32768; // tach clock frequency + + //ESP_LOGI(TAG, "SET-Fan RPM requested (%d%%) %d", (int)percent, req_rpm); + + tach_counts = (uint16_t) ((edges - 1)/poles * (1.0f/req_rpm) * ftach * 60); + tach_counts_MSB = tach_counts >> 5; + tach_counts_LSB = (tach_counts & 0x001F) << 3; + + ESP_ERROR_CHECK( register_write_byte(TACH_MSB_REG, tach_counts_MSB )); + ESP_ERROR_CHECK( register_write_byte(TACH_LSB_REG, tach_counts_LSB )); } // Gets the fan speed uint16_t EMC2302_get_fan_speed(uint8_t devicenum) { uint8_t tach_lsb, tach_msb; - uint16_t RPM; + uint16_t tach_counts = 1; + uint16_t rpm; uint8_t TACH_LSB_REG = EMC2302_TACH1_LSB + (devicenum * 0x10); uint8_t TACH_MSB_REG = EMC2302_TACH1_MSB + (devicenum * 0x10); - ESP_ERROR_CHECK(register_read(TACH_LSB_REG, &tach_lsb, 1)); + int poles = 4; // motor poles + int edges = 9; // motor edges + int ftach = 32768; // tach clock frequency + ESP_ERROR_CHECK(register_read(TACH_MSB_REG, &tach_msb, 1)); + ESP_ERROR_CHECK(register_read(TACH_LSB_REG, &tach_lsb, 1)); + //ESP_LOGI(TAG, "GET-Tach counts reg: %02x %02x", tach_msb, tach_lsb); - ESP_LOGI(TAG, "Raw Fan Speed[%d] = %02X %02X", devicenum, tach_msb, tach_lsb); - RPM = (tach_msb << 5) + ((tach_lsb >> 3) & 0x1F); - ESP_LOGI(TAG, "Fan Speed[%d] = %d RPM", devicenum, RPM); + if ((tach_msb == 0xff) && (tach_msb == 0xF8)) { + rpm = 0; + } else { + tach_counts = (tach_msb << 5) + ((tach_lsb >> 3) & 0x1F); + rpm = (uint16_t) ((edges - 1)/poles * (1.0f/tach_counts) * ftach * 60); + } + ESP_LOGI(TAG, "GET-Fan Speed[%d] = %d RPM", devicenum, rpm); - return RPM; + return rpm; } float EMC2302_get_external_temp(void) diff --git a/main/EMC2302.h b/main/EMC2302.h index 0cfce2955..7ecb1e3cc 100644 --- a/main/EMC2302.h +++ b/main/EMC2302.h @@ -31,8 +31,8 @@ #define EMC2302_FAN1_DRV_FAIL_HIGH 0x3B ///< Fan 1 drive fail band high byte #define EMC2302_TACH1_TARGET_LSB 0x3C ///< Tach 1 target low byte #define EMC2302_TACH1_TARGET_MSB 0x3D ///< Tach 1 target high byte -#define EMC2302_TACH1_LSB 0x3E ///< Tach 1 reading low byte -#define EMC2302_TACH1_MSB 0x3F ///< Tach 1 reading high byte +#define EMC2302_TACH1_MSB 0x3E ///< Tach 1 reading low byte +#define EMC2302_TACH1_LSB 0x3F ///< Tach 1 reading high byte #define EMC2302_FAN2_SETTING 0x40 ///< Fan 2 setting #define EMC2302_PWM2_DIVIDE 0x41 ///< PWM 2 divider @@ -47,8 +47,14 @@ #define EMC2302_FAN2_DRV_FAIL_HIGH 0x4B ///< Fan 2 drive fail band high byte #define EMC2302_TACH2_TARGET_LSB 0x4C ///< Tach 2 target low byte #define EMC2302_TACH2_TARGET_MSB 0x4D ///< Tach 2 target high byte -#define EMC2302_TACH2_LSB 0x4E ///< Tach 2 reading low byte -#define EMC2302_TACH2_MSB 0x4F ///< Tach 2 reading high byte +#define EMC2302_TACH2_MSB 0x4E ///< Tach 2 reading low byte +#define EMC2302_TACH2_LSB 0x4F ///< Tach 2 reading high byte + +#define EMC2302_SOFTWARE_LOCK 0xEF +#define EMC2302_PRODUCT_FEATURES 0xFC +#define EMC2302_PRODUCT_ID 0xFD +#define EMC2302_MANUFACTURER_ID 0xFE +#define EMC2302_SILICON_REVISION 0xFF #define EMC2302_FAN_RPM_NUMERATOR 5400000 ///< Conversion unit to convert LSBs to fan RPM #define _TEMP_LSB 0.125 ///< single bit value for internal temperature readings @@ -76,6 +82,7 @@ void EMC2302_init(bool); void EMC2302_set_fan_speed(uint8_t, float); uint16_t EMC2302_get_fan_speed(uint8_t); +/* EMC2302 doesn't have temperature sensors, so these are dummy functions */ float EMC2302_get_external_temp(void); uint8_t EMC2302_get_internal_temp(void); diff --git a/main/system.c b/main/system.c index f7b306729..33eb2b6e7 100644 --- a/main/system.c +++ b/main/system.c @@ -95,9 +95,13 @@ static void _init_system(GlobalState * global_state, SystemModule * module) // Initialize the core voltage regulator TPS546_init(); // Fan config - Hex has two fans - //EMC2302_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1)); + EMC2302_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1)); + EMC2302_get_fan_speed(0); + EMC2302_get_fan_speed(1); + //EMC2302_set_fan_speed(0, (float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100) / 100); //EMC2302_set_fan_speed(1, (float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100) / 100); + // temperature sensors - Hex has two sensors if (TMP1075_installed(0)) { ESP_LOGI(TAG, "Temperature sensor 0: %d", TMP1075_read_temperature(0)); diff --git a/main/tasks/power_management_task.c b/main/tasks/power_management_task.c index fa6f84124..20623211b 100644 --- a/main/tasks/power_management_task.c +++ b/main/tasks/power_management_task.c @@ -1,5 +1,6 @@ #include "DS4432U.h" #include "EMC2101.h" +#include "EMC2302.h" #include "INA260.h" #include "TPS546.h" #include "TMP1075.h" @@ -271,8 +272,9 @@ void POWER_MANAGEMENT_HEX_task(void * pvParameters) // calculate regulator power (in milliwatts) power_management->power = (TPS546_get_vout() * power_management->current) / 1000; - // TODO fix fan driver - //power_management->fan_speed = EMC2101_get_fan_speed(); + // get the fan RPM + power_management->fan_speed = EMC2302_get_fan_speed(0); + power_management->fan_speed = EMC2302_get_fan_speed(1); // Two board temperature sensors ESP_LOGI(TAG, "Board Temp: %d, %d", TMP1075_read_temperature(0), TMP1075_read_temperature(1)); @@ -281,6 +283,16 @@ void POWER_MANAGEMENT_HEX_task(void * pvParameters) power_management->chip_temp = (float)TPS546_get_temperature(); ESP_LOGI(TAG, "TPS546 Temp: %2f", power_management->chip_temp); + EMC2302_set_fan_speed(1, 100); + + // This causes the fan to cycle on/off quickly, need some hysteresis + // for active fan control + //if (power_management->chip_temp > 65) { + // EMC2302_set_fan_speed(1, 100); + //} else { + // EMC2302_set_fan_speed(1, 60); + //} + // 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)) {