Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fan control for NZXT E PSUs #55

Closed
wants to merge 1 commit into from

Conversation

@jonasmalacofilho
Copy link
Owner

jonasmalacofilho commented Oct 13, 2019

Related: #46 ("Improve support for Seasonic/NZXT E-series PSUs")

Adds an implementation for set_fixed_speed, allowing fan control through the CLI:

# liquidctl set fan speed 35

The channel name is not currently enforced, but 'fan' seems like the obvious choice. The duty cycle is so far only clamped to [0%, 100%].


I still have a few questions...

Does the code in this branch work?
What is the minimum duty value for which the unit reacts?

# liquidctl status | grep 'Fan speed'

# liquidctl set fan speed 100
# liquidctl status | grep 'Fan speed'

# liquidctl set fan speed 0
# liquidctl status | grep 'Fan speed'

# liquidctl set fan speed 50
# liquidctl status | grep 'Fan speed'
...

[suggestion: do a binary search; also, 23% seems to be an important value]

What happens to the fan speed when the unit doesn't receive constant updates (i.e. when not using CAM)? Does it permanently stays the same (e.g. if left on 100% for a couple of minutes)? Or does it revert back to some default behavior?

Presumably the unit must be able to not kill itself if CAM is not running. One possible way to implement that would be for it to honor the specified duty as long as it is above some predefined minimum curve (based on temperature, load, or both). Can we somehow observe this fallback behavior (e.g. by setting the fan speed to its minimum allowed value and ramping the power draw/temperature)?

Pinging @jnettlet for testing.


Missing:

  • clamping of duty to its minimum useful value
  • update the documentation
  • safety considerations
@jonasmalacofilho jonasmalacofilho added this to the v1.3.0 milestone Oct 13, 2019
@jonasmalacofilho jonasmalacofilho force-pushed the seasonic-fan-control branch 2 times, most recently from 7831bc1 to 0cca8a5 Oct 15, 2019
@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Oct 19, 2019

Pinging @jnettlet

@jonasmalacofilho jonasmalacofilho force-pushed the seasonic-fan-control branch from 9feb373 to 0543445 Oct 20, 2019
@jonasmalacofilho jonasmalacofilho changed the title Implement fan control for Seasonic E PSUs Implement fan control for NZXT E PSUs Oct 22, 2019
@ivan-cukic

This comment has been minimized.

Copy link
Contributor

ivan-cukic commented Oct 23, 2019

For me, the fan speed is always zero. I can try and 'listen' to the speed somehow if you think that would be beneficial.

@jnettlet

This comment has been minimized.

Copy link

jnettlet commented Oct 23, 2019

@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Oct 24, 2019

Thank you both for the feedback.

I'll double check that I haven't broken anything in the status reporting side since the initial driver, and that there are no obvious mistakes in this branch.

There might also be an extra final byte unaccounted for, which could be a Packet Error Checking (PEC) byte. The read commands don't have any PEC, but their responses seem to (though I haven't tried to the decode them); and it would make sense if only writes required PEC. I'll take a look at the captures I already have.

In the mean time, if any of you can supply a new capture specifically tailored to changing fan speeds and modes, it would be great. Please make sure that it includes any possible PSU initialization routines that we may be missing (e.g. start from a cold boot, start the capture before the guest and CAM).


EDIT: since capturing the USB traffic is pretty disruptive to at least one of you, you might also want to include some multirail OCP changes in the in the end on the test/capture. Just make sure to let me know if you did that, and also what were those changes.

@ivan-cukic

This comment has been minimized.

Copy link
Contributor

ivan-cukic commented Oct 24, 2019

Sorry for not being precise - for me, fan is zero regardless of this patch.

@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Oct 24, 2019

@ivan-cukic

I had considered that interpretation, yes, but it's nice of you to confirm. Can you show me the output of liquidctl status --debug?


I'm not sure how the base platform (Seasonic Focus Gold, IIRC) works, and how much this was changed for the NZXT E, but high-end PSUs generally don't really need the fan until there's significant load and/or temperature increase.

From screenshots it seems that in CAM there's a zero-fan-speed region, so it's reasonable to assume there's a similar region in standalone mode (though the curve could be different and/or based on different parameters).

@ivan-cukic

This comment has been minimized.

Copy link
Contributor

ivan-cukic commented Oct 24, 2019

[DEBUG] liquidctl.cli: liquidctl v1.2.0 (editable)
Device 0, NZXT E850 (experimental)
[DEBUG] liquidctl.driver.usb: replacing stock kernel driver with libusb
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 01 60 fc (and 58 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 11 41 d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 01 60 8e (and 58 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 33 00 8a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 01 60 90 (and 58 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 00 00 ef 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 00 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 8f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 00 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 04 06 f9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 00 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 87 c9 3a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 00 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 4f e2 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 01 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 ed 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 01 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 00 06 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 01 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 f5 c8 9c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 01 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 df da 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 02 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 4b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 02 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 05 06 be 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 02 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 00 c8 b2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 02 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 00 c8 5d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 03 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 03 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 72 02 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 03 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 f1 c9 9d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 03 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 5f da c5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 04 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 04 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 9a 01 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 04 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 60 c9 b6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 04 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 33 d2 2b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.usb: ensure interface is released
Temperature                     51.0  °C
Fan speed                          0  rpm
Firmware version          A017/40983  
+12V #1 output voltage         12.03  V
+12V #1 output current          3.05  A
+12V #1 output power           36.94  W
+12V #2 output voltage         12.00  V
+12V #2 output current          1.91  A
+12V #2 output power           22.97  W
+12V #3 output voltage         12.04  V
+12V #3 output current          0.00  A
+12V #3 output power            0.00  W
+5V output voltage              4.89  V
+5V output current              3.88  A
+5V output power               18.97  W
+3.3V output voltage            3.20  V
+3.3V output current            2.75  A
+3.3V output power              8.80  W
[DEBUG] liquidctl.driver.usb: ensure interface is released
[DEBUG] liquidctl.driver.usb: restoring stock kernel driver
@jonasmalacofilho jonasmalacofilho force-pushed the seasonic-fan-control branch 3 times, most recently from 2310ec1 to 5094ba8 Oct 25, 2019
@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Oct 25, 2019

I didn't find anything I could have broken between the initial driver and this PR. I also couldn't spot any major bugs here, nor any obviously missing commands.

One thing I did notice in the captures is that the PSU seemed to start with the fan at 0 rpm, and that it was CAM that set it to a higher value. So there's a chance that the fan speed is being reported correctly after all (specially since --debug shows that we sending the exact same message as CAM).

Right now I'm betting on the extra byte, which does indeed appear to be a PEC. I added it to the driver, and let's see if that allows fan control to work (and a non-zero fan speed to be reported).

@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Oct 31, 2019

Right now I'm betting on the extra byte, which does indeed appear to be a PEC. I added it to the driver, and let's see if that allows fan control to work (and a non-zero fan speed to be reported).

Let me know if this helped or made no difference.

@jonasmalacofilho jonasmalacofilho removed this from the v1.3.0 milestone Nov 3, 2019
@ivan-cukic

This comment has been minimized.

Copy link
Contributor

ivan-cukic commented Nov 3, 2019

Tried the branch and master with these commits cherry picked - still 0 RPM

@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Nov 3, 2019

Seeing the --debug output of the tests (including all speed setting and status commands) could help.

@ivan-cukic

This comment has been minimized.

Copy link
Contributor

ivan-cukic commented Nov 6, 2019

liquidctl status --debug                                                                                                                                                                                                                                                                                                                                                      

[DEBUG] liquidctl.cli: running liquidctl v1.3.0rc1 (editable)
[DEBUG] liquidctl.driver.usb: searching GenericHidBus (api=hidraw, drivers=[CommonSmartDeviceDriver, CorsairHidPsuDriver, KrakenTwoDriver, SeasonicEDriver, SmartDeviceDriver, SmartDeviceV2Driver])
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x7793:0x2500
[DEBUG] liquidctl.driver.usb: instanced driver for NZXT E850 (experimental)
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xb05:0x18f3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: searching PyUsbBus (drivers=[AsetekDriver, CommonAsetekDriver, CorsairAsetekDriver, LegacyAsetekDriver])
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x424:0x2514
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xb05:0x18f3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x7793:0x2500
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.cli: device: NZXT E850 (experimental)
NZXT E850 (experimental)
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 01 60 fc (and 58 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 11 41 d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 01 60 8e (and 58 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 37 00 de 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 01 60 90 (and 58 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 00 00 ef 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 00 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 8f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 00 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 04 06 f9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 00 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 4e c9 6a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 00 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 ec db c9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 01 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 ed 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 01 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 00 06 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 01 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 f0 c8 dd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 01 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 e5 da 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 02 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 4b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 02 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 05 06 be 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 02 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 00 c8 b2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 02 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 00 c8 5d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 03 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 03 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 73 02 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 03 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 cd c9 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 03 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 34 da a7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 03 04 60 06 02 04 20 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 03 01 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 04 8b (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 9a 01 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 04 8c (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 4c c9 e4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ad 00 04 04 60 06 02 04 96 (and 55 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 13 d2 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
├── Temperature                     55.0  °C
├── Fan speed                          0  rpm
├── Firmware version          A017/40983  
├── +12V #1 output voltage         12.03  V
├── +12V #1 output current          2.61  A
├── +12V #1 output power           31.38  W
├── +12V #2 output voltage         12.00  V
├── +12V #2 output current          1.88  A
├── +12V #2 output power           23.16  W
├── +12V #3 output voltage         12.04  V
├── +12V #3 output current          0.00  A
├── +12V #3 output power            0.00  W
├── +5V output voltage              4.90  V
├── +5V output current              3.60  A
├── +5V output power               17.62  W
├── +3.3V output voltage            3.20  V
├── +3.3V output current            2.59  A
└── +3.3V output power              8.30  W
liquidctl set fan speed 50 --debug     
                                                                                                                                                                                                                                                                                                                                      
[DEBUG] liquidctl.cli: running liquidctl v1.3.0rc1 (editable)
[DEBUG] liquidctl.driver.usb: searching GenericHidBus (api=hidraw, drivers=[CommonSmartDeviceDriver, CorsairHidPsuDriver, KrakenTwoDriver, SeasonicEDriver, SmartDeviceDriver, SmartDeviceV2Driver])
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x7793:0x2500
[DEBUG] liquidctl.driver.usb: instanced driver for NZXT E850 (experimental)
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xb05:0x18f3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: searching PyUsbBus (drivers=[AsetekDriver, CommonAsetekDriver, CorsairAsetekDriver, LegacyAsetekDriver])
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x424:0x2514
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xb05:0x18f3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x7793:0x2500
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.cli: device: NZXT E850 (experimental)
[INFO] liquidctl.driver.seasonic: setting fan PWM duty to 50%
[DEBUG] liquidctl.driver.seasonic: write ac 04 60 3b 20 e3 ae (and 57 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 1b d2 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ac 04 60 3b 20 e3 ae (and 57 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 1b d2 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ac 04 60 3b 20 e3 ae (and 57 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 1b d2 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
liquidctl set fan speed 0 --debug
                                                                                                                                                                                                                                                                                                                                             
[DEBUG] liquidctl.cli: running liquidctl v1.3.0rc1 (editable)
[DEBUG] liquidctl.driver.usb: searching GenericHidBus (api=hidraw, drivers=[CommonSmartDeviceDriver, CorsairHidPsuDriver, KrakenTwoDriver, SeasonicEDriver, SmartDeviceDriver, SmartDeviceV2Driver])
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x7793:0x2500
[DEBUG] liquidctl.driver.usb: instanced driver for NZXT E850 (experimental)
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xb05:0x18f3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: searching PyUsbBus (drivers=[AsetekDriver, CommonAsetekDriver, CorsairAsetekDriver, LegacyAsetekDriver])
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x46d:0xc328
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xe8f:0xa8
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x424:0x2514
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0xb05:0x18f3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x3
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x7793:0x2500
[DEBUG] liquidctl.driver.usb: probing drivers for device 0x1d6b:0x2
[DEBUG] liquidctl.cli: device: NZXT E850 (experimental)
[INFO] liquidctl.driver.seasonic: setting fan PWM duty to 0%
[DEBUG] liquidctl.driver.seasonic: write ac 04 60 3b 00 00 a7 (and 57 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 1b d2 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ac 04 60 3b 00 00 a7 (and 57 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 1b d2 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[DEBUG] liquidctl.driver.seasonic: write ac 04 60 3b 00 00 a7 (and 57 padding bytes)
[DEBUG] liquidctl.driver.seasonic: received aa 04 02 1b d2 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
jonasmalacofilho added a commit that referenced this pull request Nov 7, 2019
Comparing the captures against the debug data supplied by Ivan shows
that, apparently, most of the response from a write word command is
simply whatever was left on the device output buffer.[1]

Thus, it seems that the only check we can do is for a first byte ==
0xaa.

[1] #55 (comment)
@jonasmalacofilho jonasmalacofilho force-pushed the seasonic-fan-control branch from 5094ba8 to af29ef0 Nov 7, 2019
@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Nov 7, 2019

I fixed some issues but, honestly, none of them are the obvious cause for set fan speed to be ignored.

I do have one more idea of to try, based on what I've seen with Corsair PSUs, but first I would like to know that I didn't break other things with these last few changes.

So can I ask you to update to the latest commit (currently af29ef0) and send me the output from the following script?

#/usr/bin/env bash

# set bash to trace and halt on errors 
set -xe

liquidctl $OPTIONS status | grep 'Fan speed'
liquidctl $OPTIONS --debug set fan speed 100
sleep 5

liquidctl $OPTIONS --debug status
liquidctl $OPTIONS set fan speed 0
sleep 5

liquidctl $OPTIONS status | grep 'Fan speed'
liquidctl $OPTIONS set fan speed 50
sleep 5

liquidctl $OPTIONS status | grep 'Fan speed'

Root privileges are needed for liquidctl, and you can use OPTIONS to pass additional flags (e.g. to select the device if you have many).

@jonasmalacofilho jonasmalacofilho force-pushed the seasonic-fan-control branch from af29ef0 to bda2c0a Nov 7, 2019
@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Nov 10, 2019

Note: I use rebase liberally on my feature branches, and some of the fixes I mentioned above were done directly on the 'master' branch.

Uses the FAN_COMMAND_1 (0x3b) PMBus command, with the desired duty cycle
encoded in LINEAR11, and a PEC byte.

---

In the captures supplied by Jon[1][2] we can't see any missing commands
or bugs that would explain why fan control wasn't working in the initial
implementation.  There is however an extra trailing byte passed with
FAN_COMMAND_1, and it clearly isn't leftover data from a previous use of
the buffer.  Instead, it could be a Packed Error Code (PEC).

			     ac04603b17009b
			     ac04603b0000a7
				         ^^

Unfortunately confirming this was not trivial and all the first attempts
of validating the observed PECs failed.

After that a lot of time was spent looking at captures, reading the
specs _again_ and verifying the CRC implementation, until...

The PMBus spec states that the PEC must be computed for the entire
message.  It also states that the message always starts with an address
byte, which is then followed by the command byte.

So, the first thing we can do is compute the PEC only from the byte that
precedes the command byte forward.  Additionally, Jon had already
speculated early on[3] that 0x60 could be the address.

			     ac04603b17009b
				 ^^^^^^^^

While this appeared to make sense, it still didn't work.

However, I had previously disagreed with him on 0x60 being an address
because, according to the PMBus spec, the address byte should contain
the address on the 7 most significant bits and a read (1) or write (0)
least significant bit.  Essentially, we should expect to see 0x60 only on
writes, such as these executions of FAN_COMMAND_1, but on all reads we
should see 0x61, which we don't.

Where we do see a pattern of LSB 1 for read and 0 for write is in the
first byte of all messages sent to the device.  But we now know that the
other bits in that first byte can't be the PMBus slave address, because
of how the PEC has to be computed and later validated by the slave
itself.

So what if 0x60 is actually the slave *address*, not the address byte?

Well, shifting it left 1 bit seems to confirm that this is the case.
At least we get a successful PEC check when we interpret it like that!

So, in the hope that his will allow fan control to work, this patch adds
a PEC to the FAN_COMMAND_1 writes.

[1]
https://github.com/jonasmalacofilho/liquidctl-device-data/tree/master/NZXT%20E500/01%20-%20generic%20capture%20-%20jnettlet
[2]
https://github.com/jonasmalacofilho/liquidctl-device-data/tree/master/NZXT%20E500/02%20-%20generic%20capture%20-%20jnettlet
[3]
#31 (comment)

---

Comparing the captures against the debug data supplied by Ivan shows
that, apparently, most of the response from a write word command is
simply whatever was left on the device output buffer.[4]

Thus, it seems that the only check we can do is for a first byte ==
0xaa.

[4] #55 (comment)
@jonasmalacofilho jonasmalacofilho force-pushed the seasonic-fan-control branch from af29ef0 to 3433ce9 Nov 12, 2019
@jonasmalacofilho jonasmalacofilho deleted the seasonic-fan-control branch Nov 12, 2019
@jonasmalacofilho

This comment has been minimized.

Copy link
Owner Author

jonasmalacofilho commented Nov 12, 2019

Patch archived, see #46.


Thank you both, but this patch was going nowhere.

I've done what I can with the information I have. Hopefully someone else can pick up the baton.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.