ts was dumb. doesnt seem to set fan curve though?
This commit is contained in:
@@ -55,7 +55,7 @@ struct aio_t {
|
||||
libusb_device_handle* handle;
|
||||
enum aio_pump_mode_t pump_mode;
|
||||
float water_temp;
|
||||
uint16_t pump_counter;
|
||||
int16_t pump_counter;
|
||||
uint16_t pump_speed;
|
||||
uint16_t fan_speed[2];
|
||||
};
|
||||
|
||||
118
src/aio.c
118
src/aio.c
@@ -11,21 +11,12 @@ static constexpr uint8_t max_curve_points = 7;
|
||||
|
||||
static uint8_t req[buf_size], resp[buf_size];
|
||||
|
||||
static struct aio_params_t params = {
|
||||
.fans = {
|
||||
.setpoint = 43.5f,
|
||||
.min_duty = 20,
|
||||
.max_duty = 80,
|
||||
.fan_stop = false,
|
||||
.ctrl = {
|
||||
.Ki = 0.1f,
|
||||
.Kd = 10.0f
|
||||
},
|
||||
}};
|
||||
|
||||
static inline float clamp(const float value, const float min, const float max) {
|
||||
return fmaxf(fminf(value, max), min);
|
||||
}
|
||||
static const struct curve_point_t fan_curve[] = {
|
||||
{ .temp = 37, .duty = 15 },
|
||||
{ .temp = 40, .duty = 40 },
|
||||
{ .temp = 46, .duty = 60 },
|
||||
{ .temp = 50, .duty = 100 }
|
||||
};
|
||||
|
||||
static void aio_usb_claim(libusb_device_handle *dev) {
|
||||
int ret = libusb_claim_interface(dev, 0);
|
||||
@@ -43,7 +34,7 @@ static void aio_usb_release(libusb_device_handle *dev) {
|
||||
}
|
||||
|
||||
static int aio_post(libusb_device_handle *dev, const int req_len, const int resp_len) {
|
||||
// applog(LOG_DBG, "writing to aio, %02x", req[0]);
|
||||
applog(LOG_DBG, "writing to aio reg 0x%02x", req[0]);
|
||||
int ret = 0;
|
||||
ret += libusb_bulk_transfer(dev, 0x01, req, req_len, nullptr, usb_timeout);
|
||||
ret += libusb_bulk_transfer(dev, 0x81, resp, resp_len, nullptr, usb_timeout);
|
||||
@@ -51,19 +42,9 @@ static int aio_post(libusb_device_handle *dev, const int req_len, const int resp
|
||||
}
|
||||
|
||||
static float aio_get_water_temp(libusb_device_handle *dev) {
|
||||
static float last_read = 36.6f; // sane init value so it doenst ramp the fan up
|
||||
req[0] = 0xa9;
|
||||
if (aio_post(dev, 1, 6) != 0)
|
||||
return last_read;
|
||||
const float temp = (float)resp[3] + (float)resp[4] / 10.0f;
|
||||
|
||||
if (temp > 10.0f && temp < 65.0f) {
|
||||
constexpr float max_change = 0.5f; // 0.5C change per refresh cycle
|
||||
const float delta = temp - last_read;
|
||||
last_read += fmaxf(fminf(delta, max_change), -max_change);
|
||||
}
|
||||
|
||||
return last_read;
|
||||
aio_post(dev, 1, 6);
|
||||
return (float)resp[3] + (float)resp[4] / 10.0f;
|
||||
}
|
||||
|
||||
static uint16_t aio_get_pump_speed(libusb_device_handle *dev) {
|
||||
@@ -91,6 +72,8 @@ static void aio_get_fan_speed(libusb_device_handle *dev, uint16_t *speeds) {
|
||||
}
|
||||
|
||||
static void aio_set_fan_duty(libusb_device_handle *dev, const uint8_t *duty) {
|
||||
if (duty == nullptr)
|
||||
return;
|
||||
static uint8_t last_duty = 255;
|
||||
if (duty[0] == last_duty)
|
||||
return;
|
||||
@@ -98,8 +81,6 @@ static void aio_set_fan_duty(libusb_device_handle *dev, const uint8_t *duty) {
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
req[1] = i;
|
||||
req[2] = MIN(MAX(duty[i], 0), 100);
|
||||
if (params.fans.fan_stop && req[2] <= params.fans.min_duty)
|
||||
req[2] = 0;
|
||||
if (aio_post(dev, sizeof(req), buf_size) == 0)
|
||||
last_duty = req[2];
|
||||
}
|
||||
@@ -199,7 +180,9 @@ void aio_detect(struct aio_t *aio) {
|
||||
libusb_detach_kernel_driver(aio->handle, 0);
|
||||
|
||||
aio_usb_claim(aio->handle);
|
||||
applog(LOG_INF, "found Corsair AIO device at %04x:%04x, fw ver: %s. Set point is %.1fC, fan stop %s", AIO_USB_VID, AIO_USB_PID, aio_get_firmware_version(aio->handle, (char[16]){0}), (double)params.fans.setpoint, params.fans.fan_stop ? "ENABLED" : "DISABLED");
|
||||
applog(LOG_INF, "found Corsair AIO device at %04x:%04x, fw ver: %s", AIO_USB_VID, AIO_USB_PID, aio_get_firmware_version(aio->handle, (char[16]){0}));
|
||||
aio_set_fan_duty(aio->handle, nullptr); // so it doenst complain the func is unused
|
||||
aio_set_fan_curve(aio->handle, fan_curve, sizeof(fan_curve) / sizeof(fan_curve[0]));
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_QUIET); // needed for init ig?
|
||||
aio_set_color(aio->handle, AIO_COLOR_FIXED, 0, nullptr, 0); // so it doenst complain the func is unused
|
||||
aio_usb_release(aio->handle);
|
||||
@@ -216,46 +199,57 @@ void aio_update(struct aio_t *aio) {
|
||||
aio->pump_mode = aio_get_pump_mode(aio->handle);
|
||||
aio_get_fan_speed(aio->handle, aio->fan_speed);
|
||||
|
||||
/* fan logic */
|
||||
static float fan_duty = 0.0f;
|
||||
static float prev_temp = 36.0f; // 20 avoids huge jump of slope at boot
|
||||
const float error = aio->water_temp - params.fans.setpoint;
|
||||
const float slope = aio->water_temp - prev_temp;
|
||||
prev_temp = aio->water_temp;
|
||||
const uint16_t avg_rpm = (uint16_t)((aio->fan_speed[0] + aio->fan_speed[1]) / 2);
|
||||
switch (aio->pump_mode) {
|
||||
case AIO_PUMP_MODE_QUIET:
|
||||
if (avg_rpm >= 500)
|
||||
aio->pump_counter++;
|
||||
else
|
||||
aio->pump_counter = 0;
|
||||
|
||||
fan_duty += error * params.fans.ctrl.Ki + slope * params.fans.ctrl.Kd;
|
||||
fan_duty = clamp(fan_duty, params.fans.min_duty, params.fans.max_duty);
|
||||
if (aio->pump_counter >= 300) {
|
||||
aio->pump_counter = 0;
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED);
|
||||
}
|
||||
break;
|
||||
case AIO_PUMP_MODE_BALANCED:
|
||||
if (avg_rpm >= 700)
|
||||
aio->pump_counter++;
|
||||
else if (avg_rpm <= 400)
|
||||
aio->pump_counter--;
|
||||
else
|
||||
aio->pump_counter = 0;
|
||||
|
||||
// applog(LOG_DBG, "Fan duty %.3f, error %.4f, slope %.4f", (double)fan_duty, (double)error * (double)params.fans.ctrl.Ki, (double)slope * (double)params.fans.ctrl.Kd);
|
||||
aio_set_fan_duty(aio->handle, (uint8_t[]){(uint8_t)fan_duty, (uint8_t)fan_duty}); // wew lad
|
||||
if (aio->pump_counter >= 300) {
|
||||
aio->pump_counter = 0;
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_EXTREME);
|
||||
}
|
||||
if (aio->pump_counter <= -300) {
|
||||
aio->pump_counter = 0;
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_QUIET);
|
||||
}
|
||||
break;
|
||||
case AIO_PUMP_MODE_EXTREME:
|
||||
if (avg_rpm <= 500)
|
||||
aio->pump_counter--;
|
||||
else
|
||||
aio->pump_counter = 0;
|
||||
|
||||
/* pump logic */
|
||||
if (fan_duty > (float)params.fans.max_duty * 0.75f && aio->pump_counter < 300)
|
||||
aio->pump_counter++;
|
||||
if (fan_duty < (float)params.fans.min_duty * 1.75f && aio->pump_counter > 0)
|
||||
aio->pump_counter--;
|
||||
|
||||
if (aio->pump_counter > 280)
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_EXTREME);
|
||||
if (aio->pump_counter > 60)
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED);
|
||||
if (aio->pump_counter == 0)
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_QUIET);
|
||||
if (aio->pump_counter <= -300) {
|
||||
aio->pump_counter = 0;
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED);
|
||||
}
|
||||
break;
|
||||
case AIO_PUMP_MODE_UNKNOWN:
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED);
|
||||
break;
|
||||
}
|
||||
|
||||
aio_usb_release(aio->handle);
|
||||
}
|
||||
|
||||
void aio_close(const struct aio_t *aio) {
|
||||
const struct curve_point_t fan_curve[] = {
|
||||
{ .temp = 34, .duty = 20},
|
||||
{ .temp = 35, .duty = 35 },
|
||||
{ .temp = 39, .duty = 50 },
|
||||
{ .temp = 46, .duty = 75 },
|
||||
{ .temp = 55, .duty = 100}
|
||||
};
|
||||
|
||||
aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED);
|
||||
aio_set_fan_curve(aio->handle, fan_curve, sizeof(fan_curve) / sizeof(fan_curve[0]));
|
||||
libusb_attach_kernel_driver(aio->handle, 0); // reattach so liquidctl still works
|
||||
libusb_close(aio->handle);
|
||||
libusb_exit(nullptr);
|
||||
|
||||
Reference in New Issue
Block a user