BitaxeTuner server · accessories

Pico fan controller

A Raspberry Pi Pico 2 on the Pi 3's USB port controls up to six 4-pin PWM fans: one for the voltage regulator (VR) of each Bitaxe and up to three for the case. On top come a 7.5-inch e-paper with the most important values, four buttons and temperature sensors. If anything fails, the fans run at full speed.

Set up the Raspberry Pi: ready-made image · Breadboard · Display, buttons, sensors · Shopping list · Pico via WLAN ·Deutsch

Pi 3Ready-made image: write it once, done

The release page has BitaxeTuner-Server-<version>-pi-arm64.img.xz: the official Raspberry Pi OS Lite (64-bit) with the BitaxeTuner server pre-installed, the restart function for button 4 and the host name bitaxetuner. Your credentials and miner data are not part of the image; the desktop app puts them on the SD card afterwards.

  1. Open Raspberry Pi Imager → device “Raspberry Pi 3” → operating system “Use custom” → the .img.xz file → SD card (16 GB or more) → write. The Imager offers no settings for custom images – the app takes care of that in the next step.
  2. Re-insert the SD card. In the BitaxeTuner app (0.3.1 or later): Mode → Prepare Raspberry Pi → choose the “bootfs” drive, enter the admin password for the server twice, user and password for the Pi (SSH), Wi-Fi name and password (Pi 3: 2.4 GHz only; empty = LAN cable only), tick “Include my data” → “Write setup package to the SD card”. All passwords are stored on the card only as hashes. The app remembers the address and access token.
  3. Insert the card into the Pi and power it on. The first boot takes 3–5 minutes (expand the file system, create the user, apply the package). Afterwards the Pi deletes the password hash and the data copy from the card.
  4. In the app: “Test connection” → “Switch only”. Only now does the Pi poll the miners, and the PC stops doing so. The interface is also available in the browser at http://bitaxetuner.local:8484/.
Without a setup package the server starts empty; then set it up in the browser. Get the setup code with ssh <user>@bitaxetuner.local and sudo cat /var/lib/bitaxetuner/SETUP-CODE.txt. If the PC doesn't find bitaxetuner.local, enter the Pi's IP address from your router. First-boot log: /var/log/bitaxetuner-firstboot.log.
Backup to a USB stick (version 0.4.0 or later): plug a stick (FAT32, exFAT or ext4) into the Pi and choose “Use a USB stick on the Pi” in the browser under Settings → Backup. The Pi then backs up to the stick every day. On a Pi that was set up before 0.4.0, run this once via SSH after the server update: sudo sh /opt/bitaxetuner/current/install.sh --system.

OverviewWho talks to whom

3 × Bitaxe AxeOS · Wi-Fi VR temperature Raspberry Pi 3 BitaxeTuner server targets speed USB Pico Watchdog 5 s 6 × PWM 6 × driver BC547 + 2 R Ch1 · VR miner 1 Ch2 · VR miner 2 Ch3 · VR miner 3 Ch4 · case Ch5 · case Ch6 · spare 5 V supply 2–3 A +5 V common GND
The temperature comes from the server's normal miner polling; the Pico only knows target values in percent. The Pi only powers the Pico (USB); the fans hang on their own power supply. Both grounds are connected, otherwise the control signal doesn't work.

CircuitOne channel (build it the same way six times)

Raspberry Pi Pico GP0 · Pin 1 GND · Pin 38 3V3(OUT) · Pin 36 GP16 · Pin 21 R1 1 kΩ R2 10 kΩ Q1 BC547B C · B · E PWM, 25 kHz GND · also supply − R3 10 kΩ tach, 2 pulses/revolution +5 V from supply Fan Ch1 4 · PWM 1 · GND 3 · tach 2 · +5 V
PWM (fan wire blue) Tach (green) +5 V (yellow) GND (black) 3.3 V from the Pico
The transistor pulls the fan's PWM line to ground. If the Pico delivers no signal (off, crashed, cable off), R2 keeps the transistor off and the fan runs at full speed via its own pull-up. That is why the signal is inverted; the software takes care of it. R3 pulls the tach line up to 3.3 V, never to 5 V, because the Pico's pins only tolerate 3.3 V. On the breadboard build R3 is left out; the Pico's built-in pull-up does the job there.
BC547B legs: flat side facing you, legs down: left C (collector), middle B (base), right E (emitter). The similar-looking 2N3904 is wired exactly the other way round (E · B · C), so don't just swap them.

PinoutWhich channel on which pin

ChannelSuggestionPWM → R1Tach ← fan pin 3
Ch1VR fan miner 1GP0 · Pin 1GP16 · Pin 21
Ch2VR fan miner 2GP2 · Pin 4GP17 · Pin 22
Ch3VR fan miner 3GP4 · Pin 6GP18 · Pin 24
Ch4Case fan 1GP6 · Pin 9GP19 · Pin 25
Ch5Case fan 2GP8 · Pin 11GP20 · Pin 26
Ch6SpareGP10 · Pin 14GP21 · Pin 27
—3.3 V for all R3 (soldered version only)3V3(OUT) · Pin 36
—Ground (with supply −)GND · pin 38 (or 3, 8, 13, 18, 23, 28, 33)

Each PWM pin sits on its own PWM slice of the Pico, so every channel gets a clean 25 kHz. Which channel belongs to which miner is set later in the interface; the table is only the suggested wiring. If you only build Ch1–Ch3 for now, Ch4–Ch6 simply stay empty.

BreadboardBuild without soldering

Everything goes on an 830-point breadboard (columns 1–63, rows a–j). The drawing shows channel Ch1 fully wired; Ch2–Ch6 are built the same way, each six columns further right. On the breadboard R3 is left out: the software switches on the Pico's built-in pull-up for the tach line.

+5V GND free GND abcde fghij 15101520 2530354045 505560 Pico H USB left · pin 1 = h1 Ch2Ch3Ch4Ch5Ch6 Ch1 Q1 470 µF (+ to +5V) USB fan adapter Pin 2 / Pin 1 2 +5V 1 GND
PWM Tach +5 V GND Resistor
The Pico H sits with USB to the left in columns 1–20: its pins 1–20 in row h (pin number = column), pins 40–21 opposite in row c. For each Pico pin, holes a/b (top) or i/j (bottom) stay free for jumpers. The upper rails carry +5 V and GND from the USB fan adapter, the lower GND rail is connected via the dashed jumper, the lower plus rail stays free.

One channel, step by step

B is the channel's first column (Ch1: B = 22, so B+3 = 25). The table below lists B and the Pico holes for each channel.

#Part / jumperfromto
1Fan pin header (4 pins)a(B) … a(B+3)a(B) = pin 1 GND (black), a(B+3) = pin 4 PWM (blue)
2Jumper fan GNDb(B)upper blue rail (GND)
3Jumper fan +5 Vb(B+1)upper red rail (+5 V)
4Jumper tachb(B+2)Pico tach hole (table)
5Transistor BC547B, flat side facing you (towards row j)g(B+3) C · g(B+4) B · g(B+5) Eacross the gap: jumper e(B+3) → f(B+3)
6R1 1 kΩ (lying flat)h(B)h(B+4)
7R2 10 kΩi(B+4)lower blue rail (GND)
8Jumper emitterj(B+5)lower blue rail (GND)
9Jumper PWM from the PicoPico PWM hole (table)j(B)
ChannelColumns (B)Pin headerPico PWM holePico tach hole
Ch122–27 (22)a22–a25j1 · GP0a20 · GP16
Ch228–33 (28)a28–a31j4 · GP2a19 · GP17
Ch334–39 (34)a34–a37j6 · GP4a17 · GP18
Ch440–45 (40)a40–a43j9 · GP6a16 · GP19
Ch546–51 (46)a46–a49j11 · GP8a15 · GP20
Ch652–57 (52)a52–a55j14 · GP10a14 · GP21

Once for all channels

Before powering on for the first time: 0. Measure between pin 1 and pin 2 of the USB fan adapter: it must be about 5 V. Some adapters step up to 12 V (labelled “12V” or with a small box in the cable) – that would destroy the 5 V fans. 1. Don't plug anything into column 1 at the top (a1, b1); that's where the 5 V from USB (VBUS) is. 2. On many breadboards the rails are split in the middle (gap in the red/blue line); in that case bridge each rail there with a short jumper. 3. Only plug in fan connectors with the USB charger unplugged; the black wire (pin 1) goes into hole a(B).

ExtensionE-paper, buttons and temperature sensors

Everything hangs on the same Pico and goes onto the same breadboard. The holes below again refer to the Pico in columns 1–20 (pins 1–20: holes i/j, pins 21–40: holes a/b). None of them is used by the fans yet.

ConnectionPico pinBreadboard holeTarget
E-paper VCCVSYS · Pin 39b2display socket pin 39
E-paper GNDGNDupper blue raildisplay socket pin 38
E-paper DINGP15 · Pin 20i20display socket pin 15
E-paper CLKGP14 · Pin 19i19display socket pin 14
E-paper CSGP13 · Pin 17i17display socket pin 12
E-paper DCGP12 · Pin 16i16display socket pin 11
E-paper RSTGP11 · Pin 15i15display socket pin 16
E-paper BUSYGP22 · Pin 29a12display socket pin 17
Button 1 · next screen / acknowledge block foundGP1 · Pin 2j2tab A; tab B → lower GND rail
Button 2 · fans automaticGP3 · Pin 5j5as above
Button 3 · fans 100 % (hold 5 s: fans off)GP5 · Pin 7j7as above
Button 4 (red) · restart Pi + Pico, hold 3 sGP7 · Pin 10j10as above
Sensor bus column 3.3 V3V3(OUT) · Pin 36a5jumper to a60
Sensor bus column dataGP26 · Pin 31a10jumper to a61
Resistor 4.7 kΩ (only one for all sensors)e60 – e61
Each sensor: red (+3.3 V)b60 / c60 / d60one hole per sensor
Each sensor: yellow (data)b61 / c61 / d61one hole per sensor
Each sensor: black (GND)upper blue rail

E-paper 7.5" (red/black/white)

The module is actually designed for plugging the Pico on top. Here the Pico stays on the breadboard, and only eight wires go via male-male jumpers into the module's socket header – each into the hole where the module expects the signal (column “Target”, pin 1 is marked on the module). Do not plug the Pico directly onto the module: the module expects the display on GP8–GP13, but the fans use GP8 and GP10 here – BitaxeTuner drives the display on GP11–GP15 and GP22. The display's ribbon cable goes into the module's flip-lock connector, contacts facing down.

The display refreshes at most every 3 minutes (default 5, optionally not at all at night) and takes about 16 seconds to do so. That protects the panel. On an alert (miner offline, case too warm) it refreshes immediately.

Pages (each can be switched on or off, preview in the browser under Fans & display): overview, daily summary, history, BTC, BCH or both prices, monthly and daily summary with a selectable chart, groups, electricity price traffic light, temperature sensors and a QR code to the web UI. Colours can be inverted (white text on black). The block found screen ends either after a configurable number of hours or – like the warnings – only with button 1.

Program updates: when a new BitaxeTuner version ships a new fan program, the server installs it by itself on the next connection – via USB or over Wi-Fi – and the Pico restarts. Only MicroPython itself is updated by hand (UF2 file, as during the first setup).

Buttons

The push buttons have solder tabs: one alligator clip each on tab A and B, the other ends on the pins of two male-male jumpers that go into the board. Direction doesn't matter. The Pico has built-in pull-ups, no resistors needed; its LED blinks on every press.

Button 1 flips to the next page or acknowledges a special screen (e.g. block found); the display then reacts after about 30 seconds instead of 3 minutes. Button 2 (automatic) cancels “100 %” and “Off”. Button 3 briefly sets the fans to 100 % immediately, even if the server isn't responding right now; holding it for 5 seconds switches the extra fans off (safety rules stay active). Button 4 only reacts after holding it for 3 seconds (LED lights for 1 s); a short press does nothing. Before restarting, the server stops running benchmarks and restores the miner settings. The buttons can be disabled in the settings.

Several temperature sensors (e.g. power supply and miner room)

The 3-wire DS18B20 all hang in parallel on the same three lines: column 60 collects 3.3 V, column 61 the data (both columns are free to the right of Ch6). There is only one 4.7 kΩ resistor, no matter how many sensors. Each sensor has a fixed built-in ID: the server recognises it by that and adds it by itself under “Fans & display → Temperature sensors”, where you give it a name and a warning threshold.

  • Which one is which? Warm a sensor in your hand and watch which value rises in the list.
  • Red must be connected (no “parasitic” mode over 2 wires).
  • Soft stranded wire ends hold poorly in a breadboard: use an alligator clip onto a male-male jumper, or ferrules or Dupont connectors.
  • Sensor on a small board with its own resistor (often called a “module”, pins −/+/S): then our 4.7 kΩ is not needed; three such modules are still fine.
  • Cables up to about 10 m in total are no problem with 4.7 kΩ.

For each sensor you decide whether it counts for the case fans (measured value “Temperature sensors”, the warmest one applies) and whether it appears on the display. Too warm → push notification and red display line. Sensor missing for more than 2 minutes → notification. If it counts for the case fans, they run at the value for “unknown” (default 100 %) until then.

PowerSupply

5 V fans (recommended)

3 × NF-A4x10 5V PWM
about 0.05 A each
2 × case 5V PWM
about 0.1–0.15 A each
total
below 0.5 A
source
USB charger 5 V, ≥ 2 A via the USB fan adapter

+5 V to all fan pins 2, ground to the GND rail. An electrolytic capacitor (470 µF) on the 5 V rail smooths voltage spikes at start-up.

12 V case fans (if you have them)

The circuit is the same: the PWM signal doesn't depend on the fan voltage. Pin 2 then gets +12 V from a second power supply whose minus also goes to the common GND rail.

+12 V must never touch the Pico, the Pi or the 5 V line. Separate screw terminals and coloured wires help.

Don't power the fans from the Pi's 5 V pin or the Pico's USB: the Pi 3 has little headroom for that, and fans briefly draw much more current when starting up.

ShoppingWhat you need (no soldering)

PartQtyPurposeShop (Germany)
Raspberry Pi Pico 2 H (RP2350, headers already soldered)1Fan, display and button controllerBerryBase · 6,50 €required
7.5" e-paper module for Pico, 800 × 480, red/black/white1Status displayBerryBase · 52,90 €display
Square push button, normally open – 3 × black, 1 × red (restart)4Next / automatic / 100 % / restartBerryBase · about €0.80 eachbuttons
Alligator clip cable set1Connect buttons without solderingBerryBase · about €3.90buttons
Temperature sensor DS18B20, 3-wire (e.g. waterproof, 1 m cable)1–3Power supply, miner room, …BerryBase · about €2.70sensors
Resistor 4.7 kΩ, ¼ W1Pull-up for the DS18B20BerryBasesensors
microSD card 16 GB or more (for the ready-made image)1Pi 3have one?required
Breadboard set 400 & 830 points with 3 × 40 jumper wires (M-M, F-F, M-F) – used: 830 board, male-male and 2 × female-male1BuildAmazonrequired
Transistor BC547B (NPN, TO-92)6 (+2 spare)Q1 per channelBerryBaserequired
Resistor 1 kΩ, ¼ W6R1 per channelBerryBaserequired
Resistor 10 kΩ, ¼ W6R2 per channel (no R3 on the breadboard)BerryBaserequired
Pin header 1×40, straight – break into 4-pin pieces for the fan connector1Fan connectionBerryBaserequired
Jumper wires male-male, strip of 40, 20 cm (only needed for all 6 channels)0–1extra jumpersBerryBasefor 6 channels
Jumper wire box, 140 pieces in 14 lengths1short, flat jumpers (emitter, ground, collector)BerryBaserecommended
USB-A to 4-pin fan adapter (pins at the end), check for 5 V first1Fan power onto the boardhave onerequired
USB charger 5 V, at least 2 A (e.g. an old phone charger)1Power source for the fanshave one?required
Electrolytic capacitor 470 µF / 25 V1Buffer on the 5 V railBerryBaserecommended
USB 2.0 cable A to Micro-B, 0.5 m (data cable)1Pi 3 ↔ PicoBerryBaserequired
Noctua NF-A4x10 5V PWM (40 mm) – or NF-A4x20 5V PWM for more airflow3VR cooling per minerNoctua shop, Caseking, Amazonrequired
Case fan 5V PWM, e.g. Noctua NF-A8 5V PWM or NF-A12x25 5V PWM1–2Case ventilationNoctua shop, Caseking, Amazonoptional

Tools: just side cutters (split the pin header, trim legs) and a multimeter for checking. As of 27 Sep 2026: the 830 breadboard was out of stock at BerryBase, hence the Amazon set. The shops are examples from Germany – any electronics shop with the same parts will do. A power supply module or barrel jack is not needed; the power comes via the USB fan adapter.

AssemblyPutting it together and first test

  1. MicroPython onto the Pico: hold the BOOTSEL button, plug the Pico into a PC via USB, drag the UF2 file for “Raspberry Pi Pico 2” (RPI_PICO2) from micropython.org/download onto the drive that appears. The server flashes the fan program itself later.
  2. Populate the breadboard according to the layout – first the Pico, rails and ground jumper, then one channel after the other. Don't connect any fan or power supply yet.
  3. Check (multimeter, continuity test): no continuity between the red and the blue rail; nothing in column 1 at the top (VBUS); every black fan wire ends up in a(B).
  4. First the USB charger, then one fan on Ch1: without the Pico it must run at full speed right away. That's the fail-safe, which works here even without software.
  5. Plug the Pico into the Pi 3 via USB. The server detects it, uploads the fan program and takes over control; the speed appears in the interface.
  6. Assign the fans (Fans & display) and connect the remaining channels.
  7. Good to know: from fan program v8 a hardware watchdog supervises the Pico. If its program hangs, it restarts after 8 seconds, and until then the fans run at full speed. If you open the Pico with Thonny or a terminal for tinkering, you will therefore see a restart every few seconds – for tinkering, flash MicroPython again first (BOOTSEL + UF2); the server installs the fan program again afterwards.

From 0.9.7No cable to the server: Pico via WLAN

With a Raspberry Pi Pico 2 WH (with WLAN, headers already soldered) the fan controller and the display no longer have to be connected to the server via USB. There are two variants, which can also be combined:

Fan Pico

Pico 2 WH instead of Pico 2 H on the fan board (or the breadboard) – same form factor, same pins. The fans still get their power from the board's USB-C socket, the Pico gets its own USB power supply on its micro-USB socket.

An e-paper can still hang on the board via cable.

Display Pico

Plug the Pico 2 WH directly onto the Waveshare e-paper module – no wires, no board. Orientation as shown by the Pico outline printed on the module: USB socket towards the “Interface Config” end, i.e. away from the ribbon cable, VBUS on VBUS, GP0 on GP0; with power off. Power via a USB power supply on the Pico.

The program then uses the Waveshare layout (GP8–GP13, BUSY GP13), not the cable layout of the fan board (BUSY GP22). Which layout applies is set by the Pico's role, not by the server setting. On the module: switch “Interface Config” at 0 (4-wire SPI). Without WLAN: “Set up display Pico via USB (no WLAN) …” sets the role directly over the USB cable.

Keys on the module (Pico program 8.2 and later): KEY0 turns the page or acknowledges a special screen (like button 1). KEY1 redraws the current page right away with fresh values; hold it for 3 seconds to trigger the restart (like button 4). The RUN key only restarts the Pico itself.

It shows the display and reports its buttons; it has no fans. For this the program uses the Waveshare pin layout (GP8–GP13).

  1. Install MicroPython for the W: hold BOOTSEL, connect the Pico to a PC via USB, drag the UF2 file for “Raspberry Pi Pico 2 W” (RPI_PICO2_W) from micropython.org/download onto the drive. The file without “W” has no WLAN.
  2. Connect the Pico to the server with a USB data cable (Pi or PC running the BitaxeTuner server). If another Pico is already plugged in there, choose the right port in the dialog.
  3. In the browser open Fans & display and choose “Set up fan Pico for WLAN …” (card Connection) or “Set up display Pico for WLAN …” (card E-paper display, “Display is attached: own display Pico”).
  4. Enter WLAN name and password (the Pico only supports 2.4 GHz), keep or change the device name. After about 30 seconds BitaxeTuner reports “Set up” and the IP address the Pico got.
  5. Unplug the Pico from the server and connect it to its own power supply (5 V, 1 A is enough). The server connects by itself within a few seconds; the connection is shown under Connection or “Connected via”.
Good to know: The server looks for the Pico as bitaxetuner-fans.local or bitaxetuner-display.local and otherwise falls back to the last IP address it reached. Most reliable is a fixed IP in the router (DHCP reservation) – then enter it in the field “WLAN: device name or IP address”. New versions of the Pico program are installed by the server over WLAN, no cable needed.

Security

If it doesn't work

“key does not match”
The Pico was set up again elsewhere or the server was reinstalled → from Pico program 8.5 without USB: hold BOOTSEL on the Pico (display Pico also KEY0) for 3 seconds until the LED blinks fast, then “Fans & display → Picos” → “Pair again” and compare the code with the LED or display. Otherwise set the Pico up for WLAN again via USB.
“does not answer (WLAN?)”
Check WLAN name/password, is the 2.4 GHz network on? Look up the Pico's IP in the router and enter it.
“is set up as display Pico”
Fan and display Pico swapped → use the other setup button.
Display stays blank
Check first: Pico orientation on the module (USB socket away from the ribbon cable, VBUS on VBUS), ribbon cable fully inserted and locked, switch “Interface Config” at 0, role “display” (see above). To check the hardware without a server: open epd_test.py in Thonny and "Run" – after 20–30 s a test picture with a black and a red bar appears; the output says “(BUSY ok)” when the display answers. The program on the Pico stays unchanged.
Thonny loses the connection
From Pico program 8 a hardware watchdog restarts the Pico 8 s after the program is stopped. From 8.1: press BOOTSEL within 3 s after plugging in (LED lit) – the program then does not start and Thonny stays connected.
Back to USB
Choose “Connection: USB cable on the server” and save; the program keeps working via USB.

SoftwareSettings in BitaxeTuner

VR fan per miner (Ch1–Ch3)

Manual
fixed value, e.g. 60 %
Automatic
curve by this miner's VR temperature
Example curve
up to 50 °C → 25 %, from 70 °C → 100 %, linear in between
Hysteresis
2 °C so the fan doesn't oscillate
Minimum
adjustable; below it the fan stays off or runs at minimum

Case fans (Ch4–Ch6)

Manual
fixed value for the whole group
Automatic
by the highest temperature of all assigned miners
Measured value
VR, ASIC or sensor temperature (DS18B20)
Curve
own values, separate from the VR fans
Night mode
optional maximum at fixed times (quieter)

Always active, cannot be switched off