Fan speed seems to be working, Added some INA260 tests. doesn't seem like power is working yet

This commit is contained in:
Skot Croshere 2023-01-19 22:17:36 -05:00
parent b0cc6b0cb6
commit e90b1acceb
6 changed files with 246 additions and 32 deletions

View File

@ -1,2 +1,2 @@
idf_component_register(SRCS "EMC2101.c" "i2c_simple_main.c" "led_controller.c" "DS4432U.c" "EMC2101.c"
idf_component_register(SRCS "INA260.c" "EMC2101.c" "i2c_simple_main.c" "led_controller.c" "DS4432U.c" "EMC2101.c" "INA260.c"
INCLUDE_DIRS ".")

View File

@ -2,6 +2,8 @@
#include "esp_log.h"
#include "driver/i2c.h"
#include "EMC2101.h"
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
@ -10,24 +12,13 @@
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
//EMC2101 -- Fan and temp sensor controller
//address: 0x4C
#define EMC2101_SENSOR_ADDR 0x4C //Slave address of the EMC2101
#define EMC2101_PRODUCTID_REG 0xFD //should be 0x16 or 0x28
#define EMC2101_CONFIG_REG 0x03
#define EMC2101_FANCONFIG_REG 0x4A
#define EMC2101_FANSETTING_REG 0x4C
#define EMC2101_TACHREADING_REG 0x46 //2 bytes
static const char *TAG = "EMC2101.c";
/**
* @brief Read a sequence of I2C bytes
*/
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len) {
return i2c_master_write_read_device(I2C_MASTER_NUM, EMC2101_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return i2c_master_write_read_device(I2C_MASTER_NUM, EMC2101_I2CADDR_DEFAULT, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
}
/**
@ -37,14 +28,15 @@ static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) {
int ret;
uint8_t write_buf[2] = {reg_addr, data};
ret = i2c_master_write_to_device(I2C_MASTER_NUM, EMC2101_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
ret = i2c_master_write_to_device(I2C_MASTER_NUM, EMC2101_I2CADDR_DEFAULT, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return ret;
}
//takes a fan speed percent
void EMC2101_set_config(uint8_t reg) {
ESP_ERROR_CHECK(register_write_byte(EMC2101_CONFIG_REG, reg));
ESP_ERROR_CHECK(register_write_byte(EMC2101_REG_CONFIG, reg));
}
//takes a fan speed percent
@ -52,20 +44,21 @@ void EMC2101_set_fan_speed(float percent) {
uint8_t speed;
speed = (uint8_t)(63.0 * percent);
ESP_ERROR_CHECK(register_write_byte(EMC2101_FANSETTING_REG, speed));
ESP_ERROR_CHECK(register_write_byte(EMC2101_REG_FAN_SETTING, speed));
}
//RPM = 5400000/reading
uint32_t EMC2101_get_fan_speed(void) {
uint8_t data[3];
uint8_t tach_lsb, tach_msb;
uint16_t reading;
uint32_t RPM;
ESP_ERROR_CHECK(register_read(EMC2101_TACHREADING_REG, data, 2));
ESP_ERROR_CHECK(register_read(EMC2101_TACH_LSB, &tach_lsb, 1));
ESP_ERROR_CHECK(register_read(EMC2101_TACH_MSB, &tach_msb, 1));
ESP_LOGI(TAG, "Raw Fan Speed = %02X %02X", data[0], data[1]);
//ESP_LOGI(TAG, "Raw Fan Speed = %02X %02X", tach_msb, tach_lsb);
reading = data[0] | (data[1] << 8);
reading = tach_lsb | (tach_msb << 8);
RPM = 5400000/reading;
ESP_LOGI(TAG, "Fan Speed = %d RPM", RPM);
@ -73,9 +66,9 @@ uint32_t EMC2101_get_fan_speed(void) {
}
void EMC2101_read(void) {
uint8_t data[3];
uint8_t data;
/* Read the EMC2101 WHO_AM_I register, on power up the register should have the value 0x16 or 0x28 */
ESP_ERROR_CHECK(register_read(EMC2101_PRODUCTID_REG, data, 1));
ESP_LOGI(TAG, "EMC2101 PRODUCT ID = 0x%02X", data[0]);
ESP_ERROR_CHECK(register_read(EMC2101_REG_CONFIG, &data, 1));
ESP_LOGI(TAG, "EMC2101 Config register = 0x%02X", data);
}

View File

@ -1,6 +1,61 @@
#ifndef EMC2101_H_
#define EMC2101_H_
#define EMC2101_I2CADDR_DEFAULT 0x4C ///< EMC2101 default i2c address
#define EMC2101_CHIP_ID 0x16 ///< EMC2101 default device id from part id
#define EMC2101_ALT_CHIP_ID 0x28 ///< EMC2101 alternate device id from part id
#define EMC2101_WHOAMI 0xFD ///< Chip ID register
#define EMC2101_INTERNAL_TEMP 0x00 ///< The internal temperature register
#define EMC2101_EXTERNAL_TEMP_MSB 0x01 ///< high byte for the external temperature reading
#define EMC2101_EXTERNAL_TEMP_LSB 0x10 ///< low byte for the external temperature reading
#define EMC2101_STATUS 0x02 ///< Status register
#define EMC2101_REG_CONFIG 0x03 ///< configuration register
#define EMC2101_REG_DATA_RATE 0x04 ///< Data rate config
#define EMC2101_TEMP_FORCE 0x0C ///< Temp force setting for LUT testing
#define EMC2101_TACH_LSB 0x46 ///< Tach RPM data low byte
#define EMC2101_TACH_MSB 0x47 ///< Tach RPM data high byte
#define EMC2101_TACH_LIMIT_LSB 0x48 ///< Tach low-speed setting low byte. INVERSE OF THE SPEED
#define EMC2101_TACH_LIMIT_MSB 0x49 ///< Tach low-speed setting high byte. INVERSE OF THE SPEED
#define EMC2101_FAN_CONFIG 0x4A ///< General fan config register
#define EMC2101_FAN_SPINUP 0x4B ///< Fan spinup behavior settings
#define EMC2101_REG_FAN_SETTING 0x4C ///< Fan speed for non-LUT settings, as a % PWM duty cycle
#define EMC2101_PWM_FREQ 0x4D ///< PWM frequency setting
#define EMC2101_PWM_DIV 0x4E ///< PWM frequency divisor
#define EMC2101_LUT_HYSTERESIS 0x4F ///< The hysteresis value for LUT lookups when temp is decreasing
#define EMC2101_LUT_START 0x50 ///< The first temp threshold register
#define EMC2101_TEMP_FILTER 0xBF ///< The external temperature sensor filtering behavior
#define EMC2101_REG_PARTID 0xFD ///< 0x16
#define EMC2101_REG_MFGID 0xFE ///< 0xFF16
#define MAX_LUT_SPEED 0x3F ///< 6-bit value
#define MAX_LUT_TEMP 0x7F ///< 7-bit
#define EMC2101_I2C_ADDR 0x4C ///< The default I2C address
#define EMC2101_FAN_RPM_NUMERATOR 5400000 ///< Conversion unit to convert LSBs to fan RPM
#define _TEMP_LSB 0.125 ///< single bit value for internal temperature readings
/**
* @brief
*
* Allowed values for `setDataRate`.
*/
typedef enum {
EMC2101_RATE_1_16_HZ, ///< 1_16_HZ
EMC2101_RATE_1_8_HZ, ///< 1_8_HZ
EMC2101_RATE_1_4_HZ, ///< 1_4_HZ
EMC2101_RATE_1_2_HZ, ///< 1_2_HZ
EMC2101_RATE_1_HZ, ///< 1_HZ
EMC2101_RATE_2_HZ, ///< 2_HZ
EMC2101_RATE_4_HZ, ///< 4_HZ
EMC2101_RATE_8_HZ, ///< 8_HZ
EMC2101_RATE_16_HZ, ///< 16_HZ
EMC2101_RATE_32_HZ, ///< 32_HZ
} emc2101_rate_t;
void EMC2101_set_fan_speed(float);
void EMC2101_read(void);
uint32_t EMC2101_get_fan_speed(void);

View File

@ -1,8 +1,61 @@
//INA260 -- Power meter
//address: 0x40
#define INA260_SENSOR_ADDR 0x40 //Slave address of the INA260
#define INA260_MANFID_REG 0xFE //should be 0x5449
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
// /* Read the INA260 WHO_AM_I register, on power up the register should have the value 0x5449 */
// ESP_ERROR_CHECK(register_read(INA260_SENSOR_ADDR, INA260_MANFID_REG, data, 2));
// ESP_LOGI(TAG, "INA260 MANF ID = 0x%02X%02X", data[0], data[1]);
#include "INA260.h"
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
static const char *TAG = "INA260.c";
/**
* @brief Read a sequence of I2C bytes
*/
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len) {
return i2c_master_write_read_device(I2C_MASTER_NUM, INA260_I2CADDR_DEFAULT, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
}
/**
* @brief Write a byte to a I2C register
*/
static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) {
int ret;
uint8_t write_buf[2] = {reg_addr, data};
ret = i2c_master_write_to_device(I2C_MASTER_NUM, INA260_I2CADDR_DEFAULT, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return ret;
}
float INA260_read_current(void) {
uint8_t data[2];
ESP_ERROR_CHECK(register_read(INA260_REG_CURRENT, data, 2));
//ESP_LOGI(TAG, "Raw Current = %02X %02X", data[1], data[0]);
return (uint16_t)(data[0] | (data[1] << 8)) * 1.25;
}
float INA260_read_voltage(void) {
uint8_t data[2];
ESP_ERROR_CHECK(register_read(INA260_REG_BUSVOLTAGE, data, 2));
//ESP_LOGI(TAG, "Raw Voltage = %02X %02X", data[1], data[0]);
return (uint16_t)(data[0] | (data[1] << 8)) * 1.25;
}
float INA260_read_power(void) {
uint8_t data[2];
ESP_ERROR_CHECK(register_read(INA260_REG_POWER, data, 2));
//ESP_LOGI(TAG, "Raw Power = %02X %02X", data[1], data[0]);
return (uint16_t)(data[0] | (data[1] << 8)) * 10;
}

105
main/INA260.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef INA260_H_
#define INA260_H_
#define INA260_I2CADDR_DEFAULT 0x40 ///< INA260 default i2c address
#define INA260_REG_CONFIG 0x00 ///< Configuration register
#define INA260_REG_CURRENT 0x01 ///< Current measurement register (signed) in mA
#define INA260_REG_BUSVOLTAGE 0x02 ///< Bus voltage measurement register in mV
#define INA260_REG_POWER 0x03 ///< Power calculation register in mW
#define INA260_REG_MASK_ENABLE 0x06 ///< Interrupt/Alert setting and checking register
#define INA260_REG_ALERT_LIMIT 0x07 ///< Alert limit value register
#define INA260_REG_MFG_UID 0xFE ///< Manufacturer ID Register
#define INA260_REG_DIE_UID 0xFF ///< Die ID and Revision Register
/**
* @brief Mode options.
*
* Allowed values for setMode.
*/
typedef enum _mode {
INA260_MODE_SHUTDOWN = 0x00, /**< SHUTDOWN: Minimize quiescient current and
turn off current into the device inputs. Set
another mode to exit shutown mode **/
INA260_MODE_TRIGGERED = 0x03, /**< TRIGGERED: Trigger a one-shot measurement
of current and bus voltage. Set the TRIGGERED
mode again to take a new measurement **/
INA260_MODE_CONTINUOUS = 0x07, /**< CONTINUOUS: (Default) Continuously update
the current, bus voltage and power
registers with new measurements **/
} INA260_MeasurementMode;
/**
* @brief Conversion Time options.
*
* Allowed values for setCurrentConversionTime and setVoltageConversionTime.
*/
typedef enum _conversion_time {
INA260_TIME_140_us, ///< Measurement time: 140us
INA260_TIME_204_us, ///< Measurement time: 204us
INA260_TIME_332_us, ///< Measurement time: 332us
INA260_TIME_558_us, ///< Measurement time: 558us
INA260_TIME_1_1_ms, ///< Measurement time: 1.1ms (Default)
INA260_TIME_2_116_ms, ///< Measurement time: 2.116ms
INA260_TIME_4_156_ms, ///< Measurement time: 4.156ms
INA260_TIME_8_244_ms, ///< Measurement time: 8.224ms
} INA260_ConversionTime;
/**
* @brief Averaging Count options.
*
* Allowed values forsetAveragingCount.
*/
typedef enum _count {
INA260_COUNT_1, ///< Window size: 1 sample (Default)
INA260_COUNT_4, ///< Window size: 4 samples
INA260_COUNT_16, ///< Window size: 16 samples
INA260_COUNT_64, ///< Window size: 64 samples
INA260_COUNT_128, ///< Window size: 128 samples
INA260_COUNT_256, ///< Window size: 256 samples
INA260_COUNT_512, ///< Window size: 512 samples
INA260_COUNT_1024, ///< Window size: 1024 samples
} INA260_AveragingCount;
/**
* @brief Alert trigger options.
*
* Allowed values for setAlertType.
*/
typedef enum _alert_type {
INA260_ALERT_CONVERSION_READY = 0x1, ///< Trigger on conversion ready
INA260_ALERT_OVERPOWER = 0x2, ///< Trigger on power over limit
INA260_ALERT_UNDERVOLTAGE = 0x4, ///< Trigger on bus voltage under limit
INA260_ALERT_OVERVOLTAGE = 0x8, ///< Trigger on bus voltage over limit
INA260_ALERT_UNDERCURRENT = 0x10, ///< Trigger on current under limit
INA260_ALERT_OVERCURRENT = 0x20, ///< Trigger on current over limit
INA260_ALERT_NONE = 0x0, ///< Do not trigger alert pin (Default)
} INA260_AlertType;
/**
* @brief Alert pin polarity options.
*
* Allowed values for setAlertPolarity.
*/
typedef enum _alert_polarity {
INA260_ALERT_POLARITY_NORMAL = 0x0, ///< Active high open-collector (Default)
INA260_ALERT_POLARITY_INVERTED = 0x1, ///< Active low open-collector
} INA260_AlertPolarity;
/**
* @brief Alert pin latch options.
*
* Allowed values for setAlertLatch.
*/
typedef enum _alert_latch {
INA260_ALERT_LATCH_ENABLED = 0x1, /**< Alert will latch until Mask/Enable
register is read **/
INA260_ALERT_LATCH_TRANSPARENT = 0x0, /**< Alert will reset when fault is
cleared **/
} INA260_AlertLatch;
float INA260_read_current(void);
float INA260_read_voltage(void);
float INA260_read_power(void);
#endif /* INA260_H_ */

View File

@ -25,6 +25,7 @@
#include "led_controller.h"
#include "DS4432U.h"
#include "EMC2101.h"
#include "INA260.h"
static const char *TAG = "i2c-test";
@ -50,12 +51,19 @@ void app_main(void) {
// DS4432U_set(reg_setting); ///eek!
EMC2101_read();
//Fan Tests
EMC2101_set_config(0x04); //set the tach input
EMC2101_read();
EMC2101_set_fan_speed(0.5);
vTaskDelay(2000 / portTICK_RATE_MS);
vTaskDelay(1000 / portTICK_RATE_MS);
EMC2101_get_fan_speed();
//Current Sensor tests
ESP_LOGI(TAG, "Current: %.2fmA", INA260_read_current());
ESP_LOGI(TAG, "Voltage: %.2fV", INA260_read_voltage());
ESP_LOGI(TAG, "Power: %.2fW", INA260_read_power());
ESP_ERROR_CHECK(i2c_master_delete());
ESP_LOGI(TAG, "I2C unitialized successfully");
}