Forum: Mikrocontroller und Digitale Elektronik Lüfterdrehzahl auf LCD


von Daniel (Gast)


Lesenswert?

Hallo,

Möchte Zwei Papst Lüfter 12V 5,3 Watt  Multifan 4212  2GH über ein 
Atmel ein und ausschalten, dafür nutze ich ein BC und lass diesen dann 
die 12V Durchschalten, wenn der Atmel 0V oder +5V liefert das klappt.

Aber wie kann ich nun vom Gelben Kabel (Schwarz Masse, Rot Plus, Gelb 
Tacho) die Drehzahl messen und auf meinem LCD anzeigen lassen?

Kann mir jemand vielleicht paar Beispiele nennen? Hab zwar schon 
gesucht, aber ich will ja nicht den Lüfter Steuern sondern lediglich die 
Drehzahl herausfindren.

Wäre super Nett
Danke!
Daniel

von Steven (. (ovular) Benutzerseite


Lesenswert?

Ich bin mir da zwar nicht ganz sicher, aber ich glaube pro Umdrehung 
bekommst du ein 12V Puls auf die Tacholeitung.
Dann musst du das ganze nur noch über ein 20k-Widerstand auf ein Pin 
deines µC-legen.
Und die Anzahl der Pulse innerhalb einer Zeit auswerten und danach das 
ganze auf einem LCD-Ausgeben.

Gruß Steven

von Daniel (Gast)


Lesenswert?

Prima, danke..

Hab ich ne Chance mit nem Multimeter das auf der Leitung ohne Oszi zu 
messen?

Die Pulsabstände lassen sich ja bestimmt mit nem Timer lösen oder hat 
mir da jemand ein Vorschlag?

von Steven (. (ovular) Benutzerseite


Lesenswert?

>Hab ich ne Chance mit nem Multimeter das auf der Leitung ohne Oszi zu
>messen?
Mit einer Frequenzmessung und einer kleinen Umrechnung ist das wohl 
möglich.

Ja Timer ist wohl das beste.
Also ich würde Vorschlagen eine Sek. lang die Pulse zählen und danach 
mal kurz ausgeben (LCD).

MfG Steven

von Rudolph R. (rudolph)


Lesenswert?

Der Tacho-Pin bei PC-Lueftern ist Open-Collector, für die Papst Teile 
sollte ein Blick in das Datenblatt helfen.

Es wird also immer gegen GND geschaltet und Pegel mit einem 
Pullup-Widerstand "erzeugt", ein paar kilo-Ohm gegen 5V zum Beispiel.

Ein Standard PC-Lüfter macht zwei Impulse pro Umdrehung.
Und wenn man zählt, wie viele Impulse pro 0,3 Sekunden kommen,
hat man direkt die Umdrehungen pro Minute.

22 Impulse pro 0,3 Sekunden bei 2 Impulsen pro Umdrehung = 2200 
Umdrehungen pro Minute

Nochmal filtern durch Mittelwert-Bildung und die Anzeige wird stabil.

von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

schaue dir einmal den Anhang Seite 90 an, dort ist alle beschrieben was 
du suchst.

von Daniel (Gast)


Lesenswert?

Danke,

Also ich Hänge an mein Tachosignal Kabel (Gelb) 1x 20k Widerstand dran, 
klemme diesen dann ein einen bebliebig freien Port eines Atmega, ich 
nehme wohl an das der Ground vom Lüfter ebenfalls mit dem GND des Atmels 
beschaltet werden muss.. richtig?

von mäxchen (Gast)


Lesenswert?

Ja, und den Pullup im uc noch aktivieren.

von Daniel (Gast)


Lesenswert?

Prima Danke ;-)

So Nun klappt die Ausgabe bereits per UART, nur stellt sich mir die 
Frage wie ich die Funktion Realisiere, gibts irgendwo einen 
Verwendbarencode oder ansätze für avr-gcc?

Danke

von Daniel (Gast)


Lesenswert?

Kann mir denn niemand einen Anstoss geben oder Infos wo Ich diesbezügl. 
was finde?

Brauch ich den ADC um die Impulse zu messen oder wie mess ich denn das 
generell?

von Daniel (Gast)


Lesenswert?

Mein Lüfter hängt nun an einem ATMega 16,

Meine Tacholeitung an einem 20K Widerstand an PA6 mit aktiviertem Pull 
Up Widerstand.

Wie kann ich nun weiter machen oder PA6 auslesen??

von Rudolph R. (rudolph)


Lesenswert?

Daniel wrote:
> Mein Lüfter hängt nun an einem ATMega 16,

Schön, da habe ich auch zwei Stück dran.

> Meine Tacholeitung an einem 20K Widerstand an PA6 mit aktiviertem Pull
> Up Widerstand.

Was meinst Du damit? 20k in Reihe?
Das wäre dann nicht so geschickt.

> Wie kann ich nun weiter machen oder PA6 auslesen??

An PAx gibt es nicht viele Möglichkeiten.
Analog macht keinen Sinn, also bleibt nur, den Port zu pollen.

Das habe ich vor Jahren mal so gemacht:

[code]
 while(1)
 {
  data_new = PIND; // read data from PORTD

  // count pulses per 0.3s to determine the RPM of fan0
  if(data_new & (1<<PIND5)) // check if PD5 is high
  {
   if((data_old & (1<<PIND5)) == 0) // if it was low before ...
   {
    data_old |= (1<<PIND5);
    fan0_counter++; // ...we detected a new pulse
   }
  }
  else
  {
   data_old &= ~(1<<PIND5);
  }
 ...
[code]

Dazu gehört noch ein Timer-Interrupt der alle 300 ms den Wert von 
fan0_counter in einen 8-Byte Ringpuffer kopiert und fan0_counter wieder 
auf Null setzt.

Aus diesem Ringpuffer wird dann im weiteren Verlauf ein Mittelwert 
gebildet und ausgegeben, sowie für eine einfache Regelung benutzt.

Naja, das habe ich gemacht, weil ich zwei Lüfter und einen 
Drehimpulsgeber mit Taster habe, zusammen fünf digital I/O's die ich in 
der Hauptschleife so schnell sie eben durchläuft immer wieder einlese.

Mit nur einem Lüfter kannst Du auch die Input-Capture Einheit von Timer 
1 benutzen.

Alternativ könnte man auch INT0...INT2 benutzen um Ereignisse zu zählen, 
dann bräuchte man aber wiederrum einen Timer um diesen Ereignissen eine 
Zeitbasis zu geben.

von Daniel (Gast)


Lesenswert?

Hallo,

Danke für deine antwort ;-)

An welchen Port wäre es den am besten das Tacho Signal anzuschließen?
Der atmega bietet ja schon viel ;-) leider kenn ich mich in dem Thema 
mit Tachosignal und so nich wirklich so gut aus :(

Ja sind 2x 10K Widerstände hintereinander gelötet.

Daniel

von Ich (Gast)


Lesenswert?

>An welchen Port wäre es den am besten das Tacho Signal anzuschließen?

Kommt darauf an, wie Du das Problem lösen möchtest.

>Der atmega bietet ja schon viel ;-) leider kenn ich mich in dem Thema
>mit Tachosignal und so nich wirklich so gut aus :(

Naja, ist ein Rechteck, 2 Impulse pro Umdrehung meistens.

>Ja sind 2x 10K Widerstände hintereinander gelötet.

Macht mal ein Bild wie Du das angeschlossen hast.

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

So,

Hab nun mal flüchtig in Eagle gezeichnet wie ich aktuell den Lüfter und 
das Signal an den ATmega16 angeschlossen habe.

Oder muss ich mein Signal mittels 1x 10k auf GND setzen und dann mit 
1x10K an den PA7 ?

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hab aktuell folgenden Code gebastelt:
1
#include <stdlib.h>
2
#include <avr/interrupt.h>
3
#include <avr/io.h>
4
#include <avr/pgmspace.h>
5
#include "lcd_lib.h"
6
#include "debounce_keys.h"
7
8
volatile uint8_t time = 0; //time = Zeit zwischen 2 impulsen
9
volatile uint8_t i = 0; //zähler
10
char buffer[20]; //buffer
11
12
int main(void)
13
{
14
  TCCR0 |= (1<<CS00) | (1<<CS02); // Timer CPU-Takt / 1024
15
16
    /* initialize display, cursor off */
17
    lcd_init(LCD_DISP_ON);
18
19
  KEY_DDR &= ~ALL_KEYS;                // konfigure key port for input
20
    KEY_PORT |= ALL_KEYS;                // and turn on pull up resistors
21
 
22
    TCCR0 = (1<<CS02)|(1<<CS00);      // divide by 1024
23
    TIMSK = 1<<TOIE0;        // enable timer interrupt
24
 
25
  LED_PORT = 0xFF;
26
    LED_DDR = 0xFF;
27
 
28
  sei();
29
30
  lcd_clrscr();
31
  lcd_puts("Willkommmen!\n");
32
33
  lcd_puts("Drehzahl: ");
34
  
35
36
  DDRA  &= ~ (1 << DDA6);
37
  PORTA  |= (1 << PA6);   
38
39
    for (;;) {                           /* loop forever */
40
    loop_until_bit_is_set(PINA, PA6);
41
      TCNT0 = 0;
42
    loop_until_bit_is_clear(PINA, PA6);
43
      loop_until_bit_is_set(PINA, PA6);
44
      time = TCNT0;
45
      i++; //zähler + 1
46
    
47
    if(i > 50)
48
    {
49
      i = 0;
50
51
      itoa(time, buffer, 10);
52
      lcd_gotoxy(5,3);
53
      lcd_puts(buffer);
54
    }
55
56
    
57
58
    }
59
}

Nun erhalte ich die Ausgabe auf dem LCD von: 74 oder 75, halte ich den 
Lüfter per Hand an schnellt die Zahl auf 248... was gibt er mir da aus?

von Rudolph R. (rudolph)


Angehängte Dateien:

Lesenswert?

Nochmal, im Lüfter ist ein Transistor der gegen GND geschaltet wird.

Eventuell kommt man ohne nur mit den internen Pullup's hin.


Edit: die verwendeten LCD Funktionen sind mit ziemlicher Sicherheit für 
die Anwendung ungeeignet, da diese ordentlich Zeit verbrennen durch den 
Aufruf von _delay_ms() - Zeit in der Du keinen Impuls messen kannst.

von Daniel S. (sany)


Lesenswert?

Muss der Ventilator so angeschlossen wie in deinem Schaltplan?

Sorry, sagte ja hab bisher nicht mit sowas gearbeitet, dafür mit ADC 
etc..

Wie schauts den mit dem Capturing (ICP1) vom Atmega aus könnte man da 
was basteln?

von Rudolph R. (rudolph)


Lesenswert?

Daniel Steiner wrote:
> Muss der Ventilator so angeschlossen wie in deinem Schaltplan?

Ja, der mittlere Pin ist noch der Versorgungs-Anschluss des Lüfters.
Und die 33nF sind so aus "Gefühl" mit drin um das Signal ein wenig 
runder zu machen.

> Sorry, sagte ja hab bisher nicht mit sowas gearbeitet, dafür mit ADC
> etc..
>
> Wie schauts den mit dem Capturing (ICP1) vom Atmega aus könnte man da
> was basteln?

Sicher, davon hat der Mega16 aber - und auch wohl sonst jeder Mega - nur 
einen.
Das habe ich aber auch bereits geschrieben...

Du kannst ja auch mal nach einem Frequenz->Spannungs Umsetzer IC suchen, 
wenn Du da was passendes findest, kannst Du den ADC benutzen.

von Marc (Gast)


Lesenswert?

hi daniel,

dein programm ist ja schon mal gar nicht so schlecht. ich wuerde das 
ganye mal so versuchen:

* Timer initalisieren auf Overflow nach 0,3s und den Overflow interrupt 
aktivieren
* globale volatile variable in der du dir die ticks per Interval und 
eine fuer ein flag 'data ready'
* in der main schleife pins pollen und mit jeder high->low flanke 
variable incrementieren. Wenn data ready interrupts disablen und count 
variable * 100 anzeigen. data ready flag loeschen und count variable 0. 
interrupts aktivieren. falls noch andere interrupts im spiel sind 
natuerlich nur den timer overflow interrupt disablen
* im timer overflow data ready setzen und eventuell timer count register 
initialisieren

wenn du willst kannst du das intervall auch nach oben oder nach unten 
aendern musst dann halt den multiplikator anpassen. zum stabilisieren 
des wertes koenntest du auch noch eine mittelwertsbildung ueber mehrere 
intervalle machen.

in c sieht das dann ungefaehr so aus:
1
/* includes etc hier */
2
3
#define CNT_OFFSET      (timer offset)
4
5
volatile uint8_t rpm1;
6
volatile uint8_t dataready;
7
8
ISR (TIMER0_OVF_vect) {
9
   dataready = 1;
10
   TCNT0 = CNT_OFFSET;
11
}
12
13
int
14
main (void) {
15
   uint8_t tmp;
16
17
   /* set counter prescaler und enable timer interrupt
18
   ....
19
   */
20
21
   /* init PORT pullup enable, input
22
   ....
23
   */
24
25
   TCNT0 = CNT_OFFSET;
26
27
   sei();
28
29
   while (1) {
30
      if (((PINX & (1 << PX0)) ^ tmp)) && (!(PINX & (1 << PX0)))) {
31
         /* sollte ein high->low transit sein */
32
         rpm1++;
33
      }
34
      if (dataready) {
35
         cli();
36
37
         /* lcd ausgabe hier */
38
39
         dataready = 0;
40
         rpm1 = 0;
41
         sei();
42
      }
43
      tmp = PINX & (1 << PX0);
44
   }
45
}

koennte funktionieren, habs nicht ausprobiert.

gruss
marc

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.