Arduino Lüftersteuerung für 4pol PWM PCLüfter (25kHz)

Ein Arduino-Klon in der Pro-mini 5V/16MHz Variante + Potti + LCD + 12V Netzteil (von kaputtem NAS) = Lüftersteuerung mit analoger Steuerung und Drehzahlanzeige für PWM PC Lüfter.

Der Code bassiert auf dem Lüftersteuerungs Beispiel von der TimerOne Lib und dem Hello World der LiquidCrystal Lib.
Die RPM mit interrupt hab ich mir selbst ausgedacht, aber leider gibt es einen Bug den ich noch nicht gefunden habe (manchmal ist der Wert viel zu hoch).
Der Pro-Mini und sogar einige Kabel sind recycelt, der Pro-Mini hat kaputte Lötstellen und es kann daher kein spi mehr angeschlossen werden.
Das teuerste dürfte das LCD sein, aber davon habe ich zu viele, da ich jetzt meistens mit 3.3V Pegel arbeite und daher OLED Displays oder TFTs verwende.

Verbaute Teile:


Dürfte alles zusammen in Deutschland um die 10€ - 15€ kosten, aus China deutlich billiger, aber ich mag nicht wegen jedem Teil zum Zoll.
Außerdem braucht man einen Lötkolben (Lötstation mit Temperaturregelung ist Gold wert) und kleinen Elektronik Seitenschneider (Eine gute Abisolierzange ist auch nützlich).
Zum Programieren einen PC mit der Arduino Software und einen Wandler USB (oder old-school Seriell) auf 5V TTL (Ich nutze FTDI Breakout Reloaded V1.2 von watterott.com aber das gibt es nicht mehr).

Aufbau

Der PWM-Pin des Lüfters muss an 9 oder 10 (PWM Timer 1 gesteuert).
Der Tacho-Pin des Lüfters muss an 2 oder 3 (Interrupt)
Rest frei veränderbar.

Das ganze im Bild festgehalten

Links zu TimerOne Lib/Info:

TimerOne Lib Download
Info zu TimerOne

Code:

#include <TimerOne.h>
#include <LiquidCrystal.h>

#define intPin 2
#define fanPin 9
#define ainPin A6

volatile unsigned long t1 = 0;
volatile unsigned long t2 = 0;

void inter() {
  t2 = t1;
  t1 = millis();
}

const int rs = 8, en = 7, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello!");

  pinMode(ainPin, INPUT);
  pinMode(intPin, INPUT_PULLUP);
  // Attach an interrupt to the ISR vector
  attachInterrupt(digitalPinToInterrupt(intPin), inter, RISING);
  Timer1.initialize(40);  // 40 us = 25 kHz
}

void loop(void) {
  lcd.clear();
  int ainValue=analogRead(ainPin);
  float dutyCycle = 100.0 * float(ainValue) / 1023.0;
  lcd.print("PWM = ");
  lcd.print(dutyCycle);
  lcd.print("%");
  Timer1.pwm(fanPin, ainValue);
  lcd.setCursor(0, 1);
  lcd.print("RPM = ");
  lcd.print(rpm());
  delay(1000);
}

unsigned long rpm() {
  unsigned long r = 0;
  if (t2 > 0 && t1 > t2) {
    r = 30000ul / (t1 - t2);
  }
  t2 = 0ul;
  return r;
}