Hallo
Ich möchte wenn möglich 2 pc lüfter mit meinem arduino uno r3 verbinden und über einen potentiometer die drehzahl steuern. Leider finde ich keine passende anleitung. Ist das überhaupt möglich so ohne weiteres?
Hallo
Ich möchte wenn möglich 2 pc lüfter mit meinem arduino uno r3 verbinden und über einen potentiometer die drehzahl steuern. Leider finde ich keine passende anleitung. Ist das überhaupt möglich so ohne weiteres?
Das kommt auf die PC-Lüfter an. Da musst Du schon mehr und genauere Infos liefern. (z.B. Link, Foto incl. Typenschild usw.)
Gruß Tommy
Sind 12v mit 4pins.
Gibt es ein Datenblatt zu diesen Angaben?
Schon was älter das Video Link zu Youtube Video aber der erklärt das super, wie ich finde.
Ich hatte da auch mal was gebaut. Allerdings nur für einen Lüfter. Bei zweien muss das PWM Signal parallel geschaltet werden. Das sollte eigentlich funktionieren weil ein PWM Signal pro Lüfter nicht mehr als 5mA benötigen darf. Aber das habe ich noch nicht ausprobiert!
Es sind allerdings sind schon zwei Interrupts für die Drehzahlermittlung vorgesehen.
Funktioniert nur mit µControlerBoards die auf dem ATMega328 basieren (Uno, Nano, Pro Mini 5V)
#include <Arduino.h>
#include <util/atomic.h>
class Timer {
public:
void start() { timeStamp = millis(); }
bool operator()(const unsigned long duration) const { return (millis() - timeStamp >= duration) ? true : false; }
private:
unsigned long timeStamp {0};
};
//////////////////////////////////////////////////////////////////////////////
/// @brief Calculates the simple average.
///
/// @tparam T Datatype
/// @tparam N Number of arraymembers
/// @return T simple average
//////////////////////////////////////////////////////////////////////////////
template <typename T, size_t N> T getAverage(const T (&dataArray)[N]) {
T tmp = 0;
for (auto value : dataArray) { tmp += value; }
return tmp / N;
}
constexpr uint8_t PIN_ANALOG {A0};
constexpr uint16_t HERTZ {25000};
constexpr uint16_t PRESCALER {1};
constexpr uint8_t CLOCKSET {_BV(CS10)};
constexpr uint16_t ICOUNTER {static_cast<uint16_t>((F_CPU / (2UL * PRESCALER * HERTZ)) - 1)};
constexpr uint16_t INTERVAL_MS {1000};
constexpr uint8_t MAX_AVERAGE_IDX {12};
volatile uint32_t durationInt0;
volatile uint32_t lastDurInt0;
volatile uint32_t durationInt1;
volatile uint32_t lastDurInt1;
Timer timer;
uint32_t rpmSigValues[MAX_AVERAGE_IDX];
//////////////////////////////////////////////////////////////////////////////
/// @brief Enable external interrupts for INT0 and INT1 Pins (D2, D3)
///
//////////////////////////////////////////////////////////////////////////////
void enableExternalInterrupts() {
EICRA = _BV(ISC11) | _BV(ISC10) | _BV(ISC01) | _BV(ISC00); // Int0 & Int1 -> rising edge
EIMSK = _BV(INT1) | _BV(INT0);
}
// External Interrupt Pin D2
//
//////////////////////////////////////////////////////////////////////////////
/// @brief To determine the speed, measure the time between the edge changes (rising edge).
/// A fan provides two edge changes per revolution.
//////////////////////////////////////////////////////////////////////////////
ISR(INT0_vect) {
uint32_t timestamp = micros();
durationInt0 = (timestamp - lastDurInt0);
lastDurInt0 = timestamp;
}
// Not used yet
// External Interrupt Pin D2 (second Fan?)
ISR(INT1_vect) {
uint32_t timestamp = micros();
durationInt1 = (timestamp - lastDurInt1);
lastDurInt1 = timestamp;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Init PWM signal (25kHz)
///
//////////////////////////////////////////////////////////////////////////////
void pwmInit() {
DDRB |= _BV(PB1); // OCR1A Pin (PB1 / D9)
TCCR1A = _BV(WGM11);
TCCR1B = _BV(WGM13);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ICR1 = ICOUNTER; }
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Set dutycycle of the PWM signal
///
/// @param dc 0-100%
//////////////////////////////////////////////////////////////////////////////
void pwmSetDutyCycle(uint8_t dc) {
uint16_t ocr1a = (dc > 100) ? 100 : dc;
ocr1a = static_cast<uint16_t>((((ICR1 * 10UL * ocr1a) / 100) + 5) / 10); // Result must be 16Bit
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { OCR1A = ocr1a; }
}
//////////////////////////////////////////////////////////////////////////////
/// @brief start PWM signal
///
//////////////////////////////////////////////////////////////////////////////
void pwmStart() {
TCCR1A |= _BV(COM1A1);
TCCR1B |= CLOCKSET;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief stop PWM signal
///
//////////////////////////////////////////////////////////////////////////////
void pwmStop() {
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1A &= ~(_BV(COM1A1));
PORTB &= ~(_BV(PB1)); // OCR1A Pin (PB1 / D9) to LOW
}
//////////////////////////////////////////////////////////////////////////////////////
// Main program
//////////////////////////////////////////////////////////////////////////////////////
void setup(void) {
Serial.begin(115200);
enableExternalInterrupts();
pwmInit();
pwmSetDutyCycle(100);
pwmStart();
delay(10000); // full speed for 10 seconds
timer.start();
}
void loop() {
static uint16_t oldValue {0};
static uint8_t avgIdx {0};
static uint8_t show {0};
// Determine the potentiometer position and set the duty cycle accordingly.
uint16_t value = map(analogRead(PIN_ANALOG), 0, 1015, 20, 100);
if (value != oldValue) {
oldValue = value;
pwmSetDutyCycle(value);
}
// Determine the fan speed and output it via the serial interface.
// Do this every INTERVAL_MS milliseconds
if (timer(INTERVAL_MS) == true) {
uint32_t freq {0};
if (durationInt0 > 0) { freq = 100000000 / durationInt0; }
rpmSigValues[avgIdx] = freq;
freq = getAverage(rpmSigValues);
if (++avgIdx >= MAX_AVERAGE_IDX) { avgIdx = 0; }
if (show < (MAX_AVERAGE_IDX + 1)) {
++show;
} else {
Serial.print("Frequenz1: ");
Serial.print(freq / 100);
Serial.print('.');
Serial.print(freq % 100);
Serial.println("Hz");
freq *= 60;
freq /= 200;
Serial.print("RPM1: ");
Serial.println(freq);
}
timer.start();
}
}
Edit: Bezeichnungen im Schaltplan angepasst.
ich habe mal versucht was zu bauen mit google und chatgpt. kann mir jemand auf die schnelle sagen ob das völlig falsch ist oder funktionieren könnte?
die dc motoren sollen die lüfter darstellen und die batterie das netzteil.
das blaue kabel das oben links im brett steckt, wäre der tachoanschluss am lüfter.
hier noch ein link dazu
#include <LiquidCrystal.h>
// Pin Definitions
#define POTENTIOMETER_PIN A0
#define TACHO_PIN 2
#define MOSFET_PIN 9
// LCD Display
LiquidCrystal lcd(12, 11, 5, 6, 7, 8);
// Variables
int potValue = 0;
volatile int rpmCount = 0;
unsigned long lastTime = 0;
void setup() {
// Initialize LCD Display
lcd.begin(16, 2);
// Attach interrupt to Tachometer Pin
attachInterrupt(digitalPinToInterrupt(TACHO_PIN), countRPM, RISING);
// Initialize MOSFET Pin
pinMode(MOSFET_PIN, OUTPUT);
// Set initial state
analogWrite(MOSFET_PIN, 0); // Initially off
}
void loop() {
// Read Potentiometer value for fan speed
potValue = analogRead(POTENTIOMETER_PIN);
// Map Potentiometer value to PWM range for fan speed
int fanSpeed = map(potValue, 0, 1023, 0, 255);
// Control Fan Speed
analogWrite(MOSFET_PIN, fanSpeed);
// Read Potentiometer value for LCD contrast
int contrastValue = analogRead(POTENTIOMETER_PIN);
// Map Potentiometer value to LCD contrast range
int lcdContrast = map(contrastValue, 0, 1023, 0, 255);
// Set LCD contrast
lcd.command(0x21); // Set extended command mode
lcd.command(0x80 | lcdContrast); // Set contrast
// Display RPM on LCD
unsigned long currentTime = millis();
if (currentTime - lastTime >= 1000) {
// One second has passed
detachInterrupt(digitalPinToInterrupt(TACHO_PIN)); // Stop counting RPM
int rpm = (rpmCount / 2) * 60; // Calculate RPM (assuming 2 pulses per revolution)
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RPM: ");
lcd.print(rpm);
rpmCount = 0; // Reset counter
lastTime = currentTime;
attachInterrupt(digitalPinToInterrupt(TACHO_PIN), countRPM, RISING); // Resume counting RPM
}
}
void countRPM() {
rpmCount++;
}
Wenn der Lüfter ein 4 poliges Kabel hat, dann kannst Du das PWM Signal des UNO R3 direkt mit dem PWM Eingeng des Motors verbinden.
So wie in #7 beschrieben.
Grüße Uwe
Heisst mosfett weg, kabel auf ground und das pwm kabel auf pin 9? Und beide lüfter zusammenschliessen? Und müsste man am code noch was ändern?
Erst mall einen testen, dein Sketch muss nachher geändert werden wegen der Anzeige und nicht nur.
In #7 hast du einen kompletten Schaltplan inkl. einer funktionierenden Software. Was gefällt Dir daran nicht?
Ich hab leider keine ahnung (offensichtlich) und kann den plan lesen. Und der display wäre nice to have.
Du bringst nicht drei Bezeichnungen A0, D2 und D9 zusammen? Wenn Du den Arduino über ein Netzteil oder USB betreibst, kannst du den Spannungsregler oben links erst mal ausblenden.
doch aber der rest war mir nicht klar, gerade der spannungsregler. aber alles klar, ich glaub ich habs jetzt. versuch ich mal am wochenende. vielen dank
ich habs jetzt mal versucht nachzubauen, ist das richtig so? arduino tausch ich noch gegen einen nano
pin 5 am motor wäre pwm, pin 6 tacho
vielen dank für die hilfe
Wo zu die D1?
Ich hab die zeichnung von kai nachzubauen. Weiss nicht wozu die gebraucht wird sorry
Nennt sich Freilaufdiode. Ist nicht bei allen Ventilatoren notwendig. Schadet aber auch nicht, die sicherheitshalber einzubauen.
Also ich habs mal versucht mit einem lüfter und dem uno. Er läuft, jedoch ziemlich langsam und ich kann die geschwindigkeit nicht regeln mit dem potentiometer. Ausserdem funktioniert es mit dem nano nicht, da kommt eine fehlermeldung. Passt der überhaupt, ist ein 3.3v. Weiss jemand wie ich das einstellen kann.
Danke für die geduld