Compare commits

..

3 commits

5 changed files with 211 additions and 10 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/build
/lib
/local.make
/*.code-workspace

1
docs/circuit-netlist.txt Normal file
View file

@ -0,0 +1 @@
'microcontroller #5:4 #7:5 #19:2 #23:0 header=Arduino Micro sz=34 p0=13 p1=12 p2=+3V p3=11 p4=AREF p5=10 p6=18 p7=9 p8=19 p9=8 p10=20 p11=7 p12=21 p13=6 p14=22 p15=5 p16=23 p17=4 p18=NC p19=3 p20=NC p21=2 p22=+5V p23=GND p24=RESET p25=RESET p26=GND p27=0 p28=VIN p29=1 p30=14 p31=17 p32=15 p33=16 p34= p35= p36= p37= p38= p39=

148
docs/circuit.svg Normal file
View file

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" width="600" height="360" xmlns="http://www.w3.org/2000/svg">
<line x1="440" y1="80" x2="440" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="150" y1="130" x2="440" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="240" y1="80" x2="240" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="150" y1="140" x2="240" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="480" y1="200" x2="480" y2="280" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="280" y1="200" x2="480" y2="200" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="280" y1="200" x2="280" y2="280" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="150" y1="200" x2="280" y2="200" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="360" y1="220" x2="560" y2="220" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="150" y1="220" x2="360" y2="220" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="560" y1="80" x2="560" y2="280" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="520" y1="80" x2="520" y2="280" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="360" y1="80" x2="360" y2="280" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="320" y1="80" x2="320" y2="280" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="500" y="330" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="middle">female fan connector 1</text>
<text x="300" y="330" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="middle">female fan connector 0</text>
<text x="500" y="30" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="middle">male fan header 1</text>
<text x="300" y="30" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="middle">male fan header 0</text>
<text x="560" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">GND</text>
<line x1="560" y1="280" x2="560" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="560" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="520" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">+12V</text>
<line x1="520" y1="280" x2="520" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="520" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="480" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">TACH</text>
<line x1="480" y1="280" x2="480" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="480" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="440" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">PWM</text>
<line x1="440" y1="280" x2="440" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="440" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="360" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">GND</text>
<line x1="360" y1="280" x2="360" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="360" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="320" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">+12V</text>
<line x1="320" y1="280" x2="320" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="320" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="280" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">TACH</text>
<line x1="280" y1="280" x2="280" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="280" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="240" y="305" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="hanging">PWM</text>
<line x1="240" y1="280" x2="240" y2="297" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="240" cy="300" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="560" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">GND</text>
<line x1="560" y1="63" x2="560" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="560" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="520" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">+12V</text>
<line x1="520" y1="63" x2="520" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="520" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="480" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">TACH</text>
<line x1="480" y1="63" x2="480" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="480" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="440" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">PWM</text>
<line x1="440" y1="63" x2="440" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="440" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="360" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">GND</text>
<line x1="360" y1="63" x2="360" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="360" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="320" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">+12V</text>
<line x1="320" y1="63" x2="320" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="320" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="280" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">TACH</text>
<line x1="280" y1="63" x2="280" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="280" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="240" y="55" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="baseline">PWM</text>
<line x1="240" y1="63" x2="240" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="240" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="90" y="90" style="font-family:monospace;font-size:11px;text-anchor:middle" dominant-baseline="middle">Arduino Micro</text>
<rect x="40" y="100" width="100" height="180" style="fill-opacity:0;stroke:rgb(0, 0, 0);stroke-width:2" />
<line x1="30" y1="110" x2="40" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="110" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">13</text>
<line x1="140" y1="110" x2="150" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="110" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">12</text>
<line x1="30" y1="120" x2="40" y2="120" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="120" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">+3V</text>
<line x1="140" y1="120" x2="150" y2="120" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="120" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">11</text>
<line x1="30" y1="130" x2="40" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="130" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">AREF</text>
<line x1="140" y1="130" x2="150" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="130" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">10</text>
<line x1="30" y1="140" x2="40" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="140" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">18</text>
<line x1="140" y1="140" x2="150" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="140" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">9</text>
<line x1="30" y1="150" x2="40" y2="150" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="150" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">19</text>
<line x1="140" y1="150" x2="150" y2="150" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="150" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">8</text>
<line x1="30" y1="160" x2="40" y2="160" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="160" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">20</text>
<line x1="140" y1="160" x2="150" y2="160" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="160" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">7</text>
<line x1="30" y1="170" x2="40" y2="170" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="170" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">21</text>
<line x1="140" y1="170" x2="150" y2="170" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="170" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">6</text>
<line x1="30" y1="180" x2="40" y2="180" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="180" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">22</text>
<line x1="140" y1="180" x2="150" y2="180" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="180" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">5</text>
<line x1="30" y1="190" x2="40" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="190" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">23</text>
<line x1="140" y1="190" x2="150" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="190" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">4</text>
<line x1="30" y1="200" x2="40" y2="200" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="200" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">NC</text>
<line x1="140" y1="200" x2="150" y2="200" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="200" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">3</text>
<line x1="30" y1="210" x2="40" y2="210" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="210" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">NC</text>
<line x1="140" y1="210" x2="150" y2="210" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="210" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">2</text>
<line x1="30" y1="220" x2="40" y2="220" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="220" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">+5V</text>
<line x1="140" y1="220" x2="150" y2="220" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="220" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">GND</text>
<line x1="30" y1="230" x2="40" y2="230" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="230" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">RESET</text>
<line x1="140" y1="230" x2="150" y2="230" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="230" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">RESET</text>
<line x1="30" y1="240" x2="40" y2="240" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="240" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">GND</text>
<line x1="140" y1="240" x2="150" y2="240" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="240" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">0</text>
<line x1="30" y1="250" x2="40" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="250" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">VIN</text>
<line x1="140" y1="250" x2="150" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="250" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">1</text>
<line x1="30" y1="260" x2="40" y2="260" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="260" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">14</text>
<line x1="140" y1="260" x2="150" y2="260" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="260" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">17</text>
<line x1="30" y1="270" x2="40" y2="270" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="44" y="270" style="font-family:monospace;font-size:11px;text-anchor:start" dominant-baseline="middle">15</text>
<line x1="140" y1="270" x2="150" y2="270" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<text x="136" y="270" style="font-family:monospace;font-size:11px;text-anchor:end" dominant-baseline="middle">16</text>
<ellipse cx="280" cy="200" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<ellipse cx="360" cy="220" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<ellipse cx="560" cy="220" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
</svg>

View file

@ -1,10 +0,0 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"makefile.configureOnOpen": true
}
}

61
readme.md Normal file
View file

@ -0,0 +1,61 @@
# Kulifuli — The Arduino Half
Kulifuli is an Arduino Micro based PC fan controller with the option to send a fake tachometer PWM
signal back to the motherboard. This is useful for for example server motherboards that refuse to
operate unless such a signal is received. (Such as the one in my HP Proliant that always spins its
fans at 100% after the latest firmware update. Thank you HP, very cool of you to do that.)
This repository contains the Arduino side of the software, in addition to information about the
hardware. For the software to run on the host see
[this repository](https://kernelmaft.com/forgejo/zedfrigg/kulifuli-host).
## Building
Requirements: GNU Coreutils, GNU Make,
[Arduino CLI](https://docs.arduino.cc/arduino-cli/),
[GCC for AVR](https://www.microchip.com/en-us/tools-resources/develop/microchip-studio/gcc-compilers)
This project uses the standard Arduino core library obtained via Arduino CLI, but we do not use it
as a build tool.
To obtain said library:
```sh
arduino-cli core update-index
arduino-cli core install arduino:avr
```
To build the project:
```sh
make build
```
The firmware image for the Arduino Micro should now be present as `build/kulifuli.hex`.
## Flashing
Additional requirement: [AVRDUDE](https://github.com/avrdudes/avrdude)
Connect the Arduino Micro to your computer over USB. If USB serial support is set up correctly the
device should now have a path it can be referenced by, e.g. `/dev/ttyACM0` on Linux. Create a file
named `local.make` in the root of the project containing `arduino_serial_port =` followed by this
path.
Now flash the firmware image to the device:
```sh
make upload
```
## Hardware
The hardware design is extremely simple, it contains no active components other than the Arduino
Micro. Two case fans can be connected to the male fan headers, and the female fan connectors should
be connected to their original headers on the motherboard. The fan controller sits in between the
fans and the motherboard, passing through the power and ground but intercepting the control
signals.
![Circuit diagram of the hardware, see below for a structural representation](docs/circuit.svg)
You can obtain a netlist file of this circuit [here](docs/circuit-netlist.txt).