adafruit_emc2101

Brushless fan controller

  • Author(s): Bryan Siepert

Implementation Notes

Hardware:

Software and Dependencies:

class adafruit_emc2101.EMC2101(i2c_bus)

Basic driver for the EMC2101 Fan Controller.

Parameters:

i2c_bus (I2C) – The I2C bus the EMC is connected to.

See adafruit_emc2101.EMC2101_EXT for (almost) complete device register set. See adafruit_emc2101.EMC2101_LUT for the temperature look up table functionality.

Quickstart: Importing and using the device

Here is an example of using the EMC2101 class. First you will need to import the libraries to use the sensor

import board
from adafruit_emc2101.emc2101_lut import EMC2101_LUT as EMC2101

Once this is done you can define your board.I2C object and define your sensor object

i2c = board.I2C()  # uses board.SCL and board.SDA
emc = EMC2101(i2c)

Now you have access to the manual_fan_speed attribute to setup the desired fanspeed

emc.manual_fan_speed = 25

If you need control over PWM frequency and the controller’s built in temperature/speed look-up table (LUT), you will need emc2101_lut.EMC2101_LUT which extends this class to add those features, at the cost of increased memory usage.

Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/2101.pdf

property conversion_rate

The rate at which temperature measurements are taken.

Return int:

corresponding to the ConversionRate enumeration.

property dac_output_enabled

When set, the fan control signal is output as a DC voltage instead of a PWM signal.

property devconfig

Read the main device config register. See the CONFIG_* bit definitions in the emc2101_regs module, or refer to the datasheet for more detail. Note: this is not the Fan Config register!

property devstatus

Read device status (alerts) register. See the STATUS_* bit definitions in the emc2101_regs module, or refer to the datasheet for more detail.

property external_temperature

The temperature measured using the external diode. The value is read as a fixed-point 11-bit value ranging from -64 to approx 126, with fractional part of 1/8 degree.

Returns:

float temperature in degrees centigrade.

Raises:
  • RuntimeError – if the sensor pind (DP,DN) are open circuit (the sensor is disconnected).

  • RuntimeError – if the external temp sensor is a short circuit (not behaving like a diode).

property fan_speed

The current speed in Revolutions per Minute (RPM).

Returns:

float fan speed rounded to 2dp.

forced_ext_temp

The value that the external temperature will be forced to read when forced_temp_enabled is set. This can be used to test the behavior of the LUT without real temperature changes. Force Temp is 7-bit + sign (one’s complement?).

forced_temp_enabled

When True, the external temperature measurement will always be read as the value in forced_ext_temp. Not applicable if LUT disabled.

initialize()

Reset the controller to an initial default configuration

property internal_temperature

The temperature as measured by the EMC2101’s internal 8-bit temperature sensor, which validly ranges from 0 to 85 and does not support fractions (unlike the external readings).

Returns:

int temperature in degrees centigrade.

invert_fan_output

When set to True, the magnitude of the fan output signal is inverted, making 0 the maximum value and 100 the minimum value

property lut_enabled

Enable or disable the internal look up table used to map a given temperature to a fan speed.

When the LUT is disabled (the default), fan speed can be changed with manual_fan_speed. To actually set this to True and modify the LUT, you need to use the extended version of this driver, emc2101_lut.EMC2101_LUT.

property manual_fan_speed

The fan speed used while the LUT is being updated and is unavailable. The speed is given as the fan’s PWM duty cycle represented as a float percentage. The value roughly approximates the percentage of the fan’s maximum speed.

property part_info

manufacturer, part id and revision. Normally returns (0x5d, 0x16, 0x1).

Type:

The part information

property spinup_drive

The drive strength of the fan on spinup in % max PWM duty cycle (which approximates to max fan speed).

Return int:

corresponding to the SpinupDrive enumeration.

property spinup_time

The amount of time the fan will spin at the currently set drive strength.

Return int:

corresponding to the SpinupTime enumeration.

property tach_limit

The maximum speed expected for the fan. If the fan exceeds this speed, the status register TACH bit will be set.

Return float:

fan speed limit in RPM

Raises:

OSError – if the limit is 0 (not a permitted value)

adafruit_emc2101.emc2101_regs

Brushless fan controller EMC2101 Register addresses.

Register offset definitions for the SMC EMC2101 fan controller.

  • Author(s): Bryan Siepert, Ruth Ivimey-Cook

Implementation Notes

Hardware:

Software and Dependencies:

adafruit_emc2101.emc2101_lut

Brushless fan controller: extended functionality

  • Author(s): Bryan Siepert, Ryan Pavlik

Implementation Notes

Hardware:

Software and Dependencies:

The class defined here may be used instead of adafruit_emc2101.EMC2101, if your device has enough RAM to support it. This class adds LUT control and PWM frequency control to the base feature set.

class adafruit_emc2101.emc2101_lut.EMC2101_LUT(i2c_bus)

Driver for the EMC2101 Fan Controller, with PWM frequency and temperature look-up-table (LUT) control.

See adafruit_emc2101.EMC2101 for the base/common functionality. See adafruit_emc2101.EMC2101_EXT for (almost) complete device register set but no temperature look-up-table LUT support.

Parameters:

i2c_bus (I2C) – The I2C bus the EMC is connected to.

initialize()

Reset the controller to an initial default configuration.

Raises:

RuntimeError – if auto_check_status and an alert status bit is set

property lut

The dict-like representation of the LUT, an instance of FanSpeedLUT. Use this to update or read the current LUT.

You can use python ‘with’ on this class to perform a multiple update of the LUT. Usage:

with emc2101.lut as lut:
    lut[20] = 0
    lut[40] = 10

The device only supports 8 entries in the LUT. If you try to add more than this the update will fail with a ValueError. If the add is part of a ‘with’ block, this happens when the block ends.

To delete an entry from the current table, assign None to the current temperature slot(s).

with emc2101.lut as lut:
    lut[20] = 0
    lut[40] = 10

emc2101.lut[20] = None
print(emc2101.lut.lookup_table)

will print one item, for temp 40, speed 10%.

property lut_enabled

Enable or disable the internal look up table used to map a given temperature to a fan speed. When the LUT is disabled fan speed can be changed with manual_fan_speed. :return enable_lut

lut_temperature_hysteresis

The amount of hysteresis, in degrees centigrade, of hysteresis applied to temperature readings used for the LUT. As the temperature drops, the controller will switch to a lower LUT entry when the measured value is below the lower entry’s threshold, minus the hysteresis value.

property pwm_frequency

Selects the base clock frequency used for the fan PWM output

property pwm_frequency_divisor

The Divisor applied to the PWM frequency to set the final frequency.

Raises:

RuntimeError – if auto_check_status and an alert status bit is set

set_pwm_clock(use_preset=False, use_slow=False)

Select the PWM clock source, choosing between two preset clocks or by configuring the clock with pwm_frequency and pwm_frequency_divisor.

Parameters:
  • use_preset (bool) – True: Select between two preset clock sources False: The PWM clock is set by pwm_frequency and pwm_frequency_divisor

  • use_slow (bool) – True: Use the 1.4kHz clock False: Use the 360kHz clock.

Returns:

None

Raises:

adafruit_emc2101.emc2101_fanspeed

Brushless fan controller: extended functionality

  • Author(s): Bryan Siepert, Ryan Pavlik

Implementation Notes

Hardware:

Software and Dependencies:

class adafruit_emc2101.emc2101_fanspeed.FanSpeedLUT(fan_obj)

A class used to provide a dict-like interface to the EMC2101’s Temperature to Fan speed Look Up Table (LUT).

Keys are integer temperatures, values are fan duty cycles between 0 and 100. A max of 8 values may be stored.

To remove a single stored point in the LUT, assign it as None.

Usage: At 50 C the speed should be 62% of max duty cycle. (Updates the chip immediately).

emc2101.lut[50] = 62

Set two values up and write to the chip on exit from ‘with’ block.

with emc2101.lut as lut:
    lut[20] = 0
    lut[40] = 10

Delete an unneeded temperature point: (Updates the chip immediately).

emc2101.lut[20] = None

Read a dict of the currently set values:

values = emc2101.lut.lookup_table
# returns:
# { 40: 10, 50: 62 }

Delete some LUT values, assign None:

for temp in emc2101.lut.lookup_table:
    emc2101.lut[temp] = None

Delete all LUT values at once:

emc2101.lut.clear()
clear()

Clear all LUT entries.

property lookup_table

Return a dictionary of LUT values.

adafruit_emc2101.emc2101_ext

Brushless fan controller: extended functionality

  • Author(s): Bryan Siepert, Ryan Pavlik

Implementation Notes

Hardware:

Software and Dependencies:

The class defined here may be used instead of adafruit_emc2101.EMC2101, if your device has enough RAM to support it. This class adds LUT control and PWM frequency control to the base feature set.

class adafruit_emc2101.emc2101_ext.EMC2101_EXT(i2c_bus)

Driver for EMC2101 Fan, adding definitions for all (but LUT) device registers.

See adafruit_emc2101.EMC2101 for the base/common functionality. See adafruit_emc2101.EMC2101_LUT for the temperature look up table functionality.

Parameters:

i2c_bus (I2C) – The I2C bus the EMC is connected to.

auto_check_status = False

Enable checking status register before many operations. Slows other uses down but useful to catch limit or overtemp alerts. checks can also be made by calling check_status(). Default: ON

check_status()

Read the status register and check for a fault indicated. If one of the bits in STATUS_ALERT indicates an alert, raise an exception.

Note: The action of reading the status register also clears any outstanding alert reports, so a second read will return 0 unless the condition causing the alert persists.

Raises:

RuntimeError – if auto_check_status and an alert status bit is set

property dev_temp_critical_hysteresis

The critical temperature hysteresis for the device (measured by the internal sensor), in degrees centigrade.

Hysteresis is a lag in fan switching activity added to prevent too-rapid switching. It results in the temperature needing to fall to a lower temperature before the fan switches off than the higher temperature that caused the fan to switch on. The value here is the number of degrees centigrade of this difference. The device does not to support setting this value to 0.

Parameters:

temp (float) – the new limit temperature

Raises:

ValueError – if the supplied temperature is out of range.

property dev_temp_critical_limit

The critical temperature limit for the device (measured by internal sensor), in degrees centigrade.

Note: this value can only be written one time during any power-up sequence. To re-write it you must power cycle the chip. In order to write the limit, the tcrit override bit must first be set in the config register.

Returns:

int the device internal critical limit temperature.

Raises:

RuntimeError – if auto_check_status and an alert status bit is set

property dev_temp_high_limit

The high limit temperature for the internal sensor, in degrees centigrade.

property devstatus

Read device status (alerts) register. See the STATUS_* bit definitions in the emc2101_regs module, or refer to the datasheet for more detail.

Note: The action of reading the status register also clears any outstanding alert reports, so a second read will return 0 unless the condition causing the alert persists.

property external_temp_high_limit

The high limit temperature for the external sensor.

property external_temp_low_limit

The low limit temperature for the external sensor.

property external_temperature

The temperature measured using the external diode. The value is read as a fixed-point 11-bit value ranging from -64 C to just over approx 126 C, with fractional part of 1/8 degree centigrade.

Returns:

Float temperature in degrees centigrade.

Raises:
  • RuntimeError – if auto_check_status and an alert status bit is set.

  • RuntimeError – if the sensor pind (DP,DN) are open circuit (the sensor is disconnected).

  • RuntimeError – if the external temp sensor is a short circuit (not behaving like a diode).

property fan_speed

The current speed in Revolutions per Minute (RPM).

Returns:

float speed in RPM.

initialize()

Reset the controller to an initial default configuration.

property internal_temperature

The temperature as measured by the EMC2101’s internal 8-bit temperature sensor.

Returns:

int temperature in degrees centigrade.

property last_status

Read the saved copy of the device status register. This is kept because the action of reading the status register also clears any outstanding alert reports, so a second read will return 0 unless the condition causing the alert persists.

This method is mainly of use after a check_status call.

Returns:

int the 8-bit device status register as last read, or 0

adafruit_emc2101.emc2101_enums

Brushless fan controller

  • Author(s): Bryan Siepert

Implementation Notes

Hardware:

Software and Dependencies:

class adafruit_emc2101.emc2101_enums.CV

struct helper

classmethod add_values(value_tuples)

Creates CV entries

classmethod is_valid(value)

Returns true if the given value is a member of the CV

class adafruit_emc2101.emc2101_enums.ConversionRate

Options for conversion_rate

class adafruit_emc2101.emc2101_enums.SpinupDrive

Options for spinup_drive

class adafruit_emc2101.emc2101_enums.SpinupTime

Options for spinup_time