A custom CircuitPython controller for an AC Infinity Cloudline S6 axial fan that can automatically turn on based on a current sensor. Useful for external exhaust fans on laser systems — the fan engages automatically whenever the laser starts lasing.
The controller supports two modes:
- Auto — the fan runs at full speed whenever the current sensor detects the monitored load is on, and shuts off when it turns off.
- Manual — up/down buttons step through the 8 fan speeds by hand.
An 8×8 LED matrix shows the current speed.
The AutoFan is deliberately built from off-the-shelf breakout boards rather than
a from-scratch custom design. Leaning on existing, well-documented modules
(microcontroller, current sensor, LED display, buck converter, and IO expander)
kept the proof-of-concept cheap and fast to bring up — no custom silicon or
low-level board bring-up, just wiring together known-good parts and focusing the
effort on the firmware. The Eagle PCB in design/eagle/ simply
carries and connects these same modules for a tidier, more permanent build.
The controller runs on an Adafruit Trinket M0 (SAMD21). Full bill of materials (reference designators match the schematic):
| Ref | Part | Qty | Purpose |
|---|---|---|---|
| U2 | Adafruit Trinket M0 | 1 | Microcontroller (SAMD21) |
| — | Modern Device current sensor | 1 | Non-contact load detection |
| U3 | Adafruit 8x8 LED matrix (HT16K33) | 1 | Speed display |
| U1 | Adafruit MPM3610 3.3V buck converter | 1 | 10 V → 3.3 V power |
| IC1 | Microchip MCP23008 | 1 | IO expander for buttons / switch |
| T1 | 2N2222 (P2N2222) NPN transistor | 1 | Drives the fan's 10 V PWM line |
| VR1 | 10 kΩ trim potentiometer | 1 | Sensor threshold adjust (A3) |
| R2, R3 | 2.2 kΩ resistor | 2 | I2C SDA/SCL pull-ups |
| R4, R5, R6 | 1 kΩ resistor | 3 | Button/switch current limiting |
| R1 | 470 Ω resistor | 1 | Transistor base resistor |
| C2 | 0.1 µF capacitor | 1 | MCP23008 decoupling |
| S1, S2 | Momentary push button | 2 | Up / down speed |
| S3 | SPDT switch | 1 | Manual / Auto mode select |
| — | 4-pin "molex" ATX HDD connector | 1 | Fan connection (10 V / GND / PWM) |
The fan's PWM control wire is pulled up to 10 V by the fan itself; T1 pulls
it low under control of the Trinket's D4 output to generate the speed signal.
See design/eagle/ for the PCB and design/enclosure/
for the 3D-printable case.
The editable schematic is in design/eagle/Autofan.sch
(Autodesk EAGLE).
Load detection uses the Modern Device current sensor,
which senses the magnetic field around a conductor rather than making any
electrical connection to it. In practice you simply zip-tie the sensor
alongside the load's AC power cable — no cutting, splicing, or breaking into
the mains wiring. As the AC current through the cable rises and falls, the sensor
picks up the changing field and outputs a proportional analog voltage that the
Trinket reads on A0. Because it never touches the conductor, the sensor stays
galvanically isolated from mains, which keeps the low-voltage controller safe.
The firmware compares this reading against a threshold (set by the trim pot on
A3); when the monitored load draws current, AutoFan switches the fan on. See
Calibration for how to dial in the threshold.
Derived from src/code.py:
| Signal | Connection |
|---|---|
| Fan PWM output | D4 |
| Current sensor input | A0 (analog) |
| Threshold trim pot | A3 (analog) |
| LED matrix + IO expander | I2C (SCL / SDA, 400 kHz) |
| Down button | MCP23008 pin 0 (active low) |
| Up button | MCP23008 pin 1 (active low) |
| Mode switch (Manual/Auto) | MCP23008 pin 2 |
The controller runs CircuitPython.
The Adafruit libraries under src/lib/ are bundled for convenience
and come from the Adafruit CircuitPython Bundle
(MIT licensed):
adafruit_bus_deviceadafruit_debounceradafruit_ht16k33adafruit_mcp230xx
Their copyright notices and the MIT license text are retained in
src/lib/THIRD_PARTY_LICENSES.txt.
- Install CircuitPython on the Trinket M0 (see the Adafruit guide).
- Copy the contents of
src/to the board'sCIRCUITPYdrive:code.py→ the drive root- the
lib/folder → the drive root
- The controller starts automatically. Open the serial console to see status messages.
Use the scripts in src/test/ to read the sensor voltage and to
regenerate the PWM speed table. See that folder's readme for details.
TODO: Provide details for test rig to verify the AutoFan is working.
src/
code.py main controller firmware
lib/ bundled Adafruit CircuitPython libraries
test/ sensor / PWM calibration scripts
design/
eagle/ PCB schematic and board (Autodesk EAGLE)
enclosure/ 3D-printable case and button/switch caps
Details captured from the original AC Infinity controller, used to match the fan's expected PWM signal.
The stock controller has one button that cycles through 8 fan speeds and 8 LEDs that indicate the current speed. It connects to the fan via a 4-pin "molex" ATX HDD power connector.
The fan connection provides three lines:
- 10V DC power
- GND
- PWM fan-speed control wire (pulled up to 10V by the fan)
Fan speed is controlled by grounding and opening the 10V control wire to create a PWM signal.
- Controller logic: ~9.2 mA at rest, ~18.2 mA at full speed (all LEDs on).
- PWM signal line: 1 mA when grounded (left grounded to turn the fan off).
Based on a 245 µs cycle time — almost 4 kHz, likely the intended target frequency but slightly off due to drift.
PWM "high" times:
| Speed | High time | Notes |
|---|---|---|
| 0 | 0 µs | 0% PWM (off) |
| 1 | ~82 µs | |
| 2 | ~100 µs | |
| 3 | ~120 µs | |
| 4 | ~140 µs | |
| 5 | ~162 µs | |
| 6 | ~185 µs | |
| 7 | ~210 µs | |
| 8 | ~245 µs | 100% PWM (full) |
The stock controller transitions instantly between speeds 0 and 1, and smoothly transitions between the other speeds over ~2 seconds.
- Add digital trim for current sensor. (the manual trim pot is a bit of a pain)
- Add some hysteresis to handle flickering at the sensor threshold. Favor staying "on".
This project is dual-licensed to fit the two kinds of content it contains:
- Source code (
src/) — MIT License. - Hardware and design files (
design/, including the Eagle PCB and 3D enclosure models) — Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
The bundled Adafruit libraries under src/lib/ remain under their
own upstream MIT licenses; see
src/lib/THIRD_PARTY_LICENSES.txt for their
copyright notices and license text.






