Communicating with the fan controller
This documentation will take you through the low level details of connecting to and communicating with the fan controller. There are libraries available that do this work for you already, but if your microcontroller does not support these libraries or if you like to get more hands on with the low level protocol, this article is for you.
The I2C bus
The controller uses the ubiquitous I2C bus for communication. All that is needed for this protocol is a common ground line between the VanTurtle fan controller (refereed to as the board in this documentation) and a SCL (clock) and SDA (data) line that can be pulled low.
Connect GND to the ground on your microcontroller, and VCC to a 5v or 3.3v source. Then connect SDA and SCL to the pins on your microcontroller which support those. Usually this is almost any pins and you can define which one are used in software.
The bus will need a pull-up resistor (PUR) on both the clock and data line. For some microcontrollers like the Raspberry Pi these come integrated already. If your microcontroller does not have those build-in there are already PURs on the board, but they are not enabled by default. This is because the PUR will set the voltage to VCC, which can be higher than the microcontroller expects. If you are sure that your supplied VCC is not higher than the max input voltage for your microcontroller you can enable the PUR by bridging the two pads at the bottom of the board marked “PUR”. You could apply a little solder to permanently bridge them. After this you should be able to measure voltage between GND and SDA.
Finding the address
Each VanTurtle fan controller occupies a single 7-bit I2C address, which is selected using the three hardware address pins on the board. You’ll find these marked “I2C ADDR” on the back of the board. The pins are labeled A0, A1 and A2. By connecting these pins you determine which address the board will respond to on the I2C bus.
The default address, with all pins diconnected, is 27. You can connect (“short”) or disconnect any combination of the three pins to change the address. This allows you to use multiple different boards on the same bus. Here are the possible addresses:
| A0 | A1 | A3 | Address |
|---|---|---|---|
| Shorted | Shorted | Shorted | 0x20 |
| Disconnected | Shorted | Shorted | 0x21 |
| Shorted | Disconnected | Shorted | 0x22 |
| Disconnected | Disconnected | Shorted | 0x23 |
| Shorted | Shorted | Disconnected | 0x24 |
| Disconnected | Shorted | Disconnected | 0x25 |
| Shorted | Disconnected | Disconnected | 0x26 |
| Disconnected | Disconnected | Disconnected | 0x27 |
Before attempting any communication, ensure that you know which address your board is configured for and that your microcontroller is using the same value. If communication fails, the address selection is the first thing to verify. On most platforms, you can also confirm the address by performing an I2C bus scan and observing which addresses acknowledge.
Initializing the board
Once the board is physically connected and the correct I2C address is known, the next step is to initialize the I/O expander on the board. Initialization sets almost all pins in write mode and the auto hold sense in input mode.
The expander exposes two independent 8-bit ports with each port corresponding to one fan. During initialization, both ports must be configured identically. This is a list of all relevant registers:
| Register | Address | Description |
|---|---|---|
| Input fan 1 | 0x00 |
Read IO state, useful for autohold |
| Input fan 2 | 0x01 |
|
| Output fan 1 | 0x02 |
Set output low or high |
| Output fan 2 | 0x03 |
|
| Configuration fan 1 | 0x06 |
Set which pins are input and which are output |
| Configuration fan 2 | 0x07 |
First, it is recommended (though not strictly required) to verify that the board is responding on the bus. This can be done by reading any register from the device, for example one of the configuration registers. A successful read indicates that the address and wiring are correct.
If that succeeds, congratulations! You’re talking to the board.
Next, we need to configure the direction of each pin. On both ports, pin 7 is used as an input to sense the auto hold LED state, while all other pins are outputs used to simulate button presses. To achieve this, write the value 0x01 to both configuration registers. In binary, this corresponds to 00000001, meaning bit 0 is an input and all other bits are outputs.
You should see the LEDs on the board go from dimly on to fully off. This signals that the board has been configured. You can test a simple command by turning the fan one LED on:
Pressing buttons
All interaction with the fan is performed by simulating physical button presses using the output pins. Each button corresponds to a specific bit in the output register for the selected fan. A button press is represented by driving the associated output pin high for a short period of time and then returning it to low.
The output registers are 8-bit wide, with each bit controlling one function. Bit 0 is used as the auto hold LED input and should always remain low. The remaining bits are mapped as follows:
| Bit | RJ45 function | RJ11 function |
|---|---|---|
| 0 | Invalid This is the auto hold input pin |
Invalid This is the auto hold input pin |
| 1 | Fan activity LED On the VanTurtle controller, not the fan |
Fan activity LED On the VanTurtle controller, not the fan |
| 2 | Auto Hold temperature, also turns the fan on from sleep |
Invalid Pin floating with RJ11 connection |
| 3 | In / Out Reverse airflow |
On / Speed Turns on, then cycles speeds 1-2-3-4 |
| 4 | On / Off | Close lid |
| 5 | Faster | Open lid |
| 6 | Slower | Off |
| 7 | Beep Just makes the fan beep |
Invalid Pin floating with RJ11 connection |
| 5 AND 6 | Open / Close Only on some models |
Invalid Use bits 4 and 5 instead |
To press a button, you must first read the current value of the output register, modify only the bit corresponding to the desired button, and then write the updated value back. This read–modify–write sequence is important, as multiple outputs may be active at the same time and writing a fixed value could unintentionally change the state of other pins. Read current state from fan one:
Then you must set the bit of the function you want to high and set the LED to on. It’s important to set the LED on in the same write to the LED is always on if a button is being pressed on the fan. If any button on the fan is held down it will ignore any other input, even on the control panel on the fan itself. It is therefore important for debugging fan issues that the LEDs can be trusted.
In this example we want to reverse the airflow of the fan, In / Out is assigned to bit 3, so we set bit 3 high and make sure that bit 1, the activity LED, is also set to high:
Then we’ll have to wait a bit. The Maxxair will poll every so often, possibly every 50 milliseconds. It’s recommended to hold the button pressed for at least 150 milliseconds to make sure the button press is registered.
When the wait is over, read the output register again:
This should hopefully be the same data as we read, but if any bits have been written to during our wait we do not want to overwrite them. To turn the output off again we take the read result 00001010 and set our bit 3 to 0 again. If all bits but bit 1 are 0 again, we can turn the LED on bit 1 off again to:
Depending on the fan model, On / Off must be held longer (approximately 750 ms) to be detected reliably. Additionally, issuing one or two short (150ms) Beep presses immediately before pressing On / Off can significantly improve reliability on these models.
Reading the Auto Hold state
In addition to simulating button presses, the board also allows you to read back the Auto Hold state, which indicates whether the fan is currently in automatic (“hold to set”) mode.
Each fan exposes this information via one input pin on the I/O expander. As described earlier, pin 0 of each port is configured as an input and is electrically connected to the Auto Hold LED on the fan. This LED is driven by the fan itself, not by the board.
To read the Auto Hold state, you must read the input register corresponding to the fan:
The register contains the state of all eight pins on the port, but only bit 0 is relevant for Auto Hold detection. The state is inverted and set to 1 if autohold is off, and 0 if the fan is in auto mode. In this case, bit 0 is set to 1, which means the Auto Hold LED is off.
You can use the autohold to “reset” the fan to a state that your microcontroller knows, as turning auto hold on will always turn the fan on but never turn it off. You can then trigger an On / Off and know for sure the fan is off.