Hallo! Dies ist mein erster Beitrag hier. Ich möchte 2 12V Computer Lüfter (3 Pol.) mit einem ATmega8 oder 16 Steuern und deren Drehzahl messen. Die Lüfter werden über die PWM gesteuert, da ist auch alles klar. Jetzt hängt es nur noch an der Drehzahl? Hier die Schaltung die ich anwenden möchte für die Drehzahlmessung: VCC vom uC | 10k | Lüfter ---+--- uC-Eingang Ist das so Korrekt wen das Lüftersignal gegen GND zieht? Ich habe in einem anderen Beitrag gelesen das ich diese Schaltung zur Drehzahlermittlung nur anwenden kann, wenn ich eine "Hi Side PWM" nutze. Meine eigentliche Frage: Wie kann ich das Software-technisch mit Bascom Realisieren? Das Programmieren fällt mir noch ein wenig schwer. Ich weis das ich die Impulse pro Sekunde zählen muss, Aber wie? Ein kleines Beispiel währe mir sehr Willkommen!!! Danke schon mal im voraus!!! Gruß Peter
http://www.analog.com/library/analogdialogue/archives/38-02/fan_speed.pdf kleine Infos zum Tacho-Signal
1 | ' ******** FAN Interrupts |
2 | On Int3 FANISR Nosave : Config Int3 = Falling ': Enable Int3 |
3 | On Int2 FANISR Nosave : Config Int2 = Falling ': Enable Int2 |
4 | On Int1 FANISR Nosave : Config Int1 = Falling ': Enable Int1 |
5 | On Int0 FANISR Nosave : Config Int0 = Falling ': Enable Int0 |
6 | On Int7 FANISR Nosave : Config Int7 = Falling ': Enable Int7 |
7 | On Int6 FANISR Nosave : Config Int6 = Falling ': Enable Int6 |
in der FANISR musst Du dann rechnen, 1 Umdrehung 2 Pulse. Entweder die Zeit zwischen n Umdrehungen oder n Sekunden lang Pulse zählen.
Ist die Schaltung nun i.O. oder nicht ???
Ist OK wenn du Highside (Plusleitung) schaltest.
Hast du getestet ob die Lüfter überhaupt PWM mögen? Ich hab damit keine guten Erfahrungen gemacht, die Lüfter haben laute Geräusche von sich gegeben.
#Hast du getestet ob die Lüfter überhaupt PWM mögen? ja aber ein kondensator hat da abhilfe geschaffen
1 | ' ******** FAN Interrupts |
2 | On Int3 FANISR Nosave : Config Int3 = Falling ': Enable Int3 |
3 | On Int2 FANISR Nosave : Config Int2 = Falling ': Enable Int2 |
4 | On Int1 FANISR Nosave : Config Int1 = Falling ': Enable Int1 |
5 | On Int0 FANISR Nosave : Config Int0 = Falling ': Enable Int0 |
6 | On Int7 FANISR Nosave : Config Int7 = Falling ': Enable Int7 |
7 | On Int6 FANISR Nosave : Config Int6 = Falling ': Enable Int6 |
Das ist für ein Anfänger ziemlich viel wirres zeug was da steht! Gibt es jemand der mir das etwas genauer erklären kann? hier schon mal mein bisheriger code:
1 | $regfile = "m16def.dat" |
2 | $crystal = 8000000 |
3 | |
4 | 'LCD Config |
5 | Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2 |
6 | Cursor Off |
7 | Cls |
8 | |
9 | 'Port Config |
10 | Config Pinb.0 = Input |
11 | Portb.0 = 1 |
12 | Fan1 Alias Pinb.0 |
13 | |
14 | Config Pinb.1 = Input |
15 | Portb.1 = 1 |
16 | Fan2 Alias Pinb.1 |
17 | |
18 | 'Timer und Interupts |
19 | Config Timer1 = Timer , Prescale = 256 |
20 | Enable Timer1 |
21 | On Timer1 Isr_von_timer1 |
22 | Enable Interrupts |
23 | Timer1 = 34285 |
24 | |
25 | 'Variablen |
26 | Dim Rpm1 As Word |
27 | |
28 | 'Hauptprogramm |
29 | Do |
30 | |
31 | Cls |
32 | |
33 | Locate 1 , 1 |
34 | Lcd Rpm1 ; " RPM " |
35 | Locate 2 , 1 |
36 | Lcd Rpm2 ; " RPM " |
37 | |
38 | Wait 1 |
39 | |
40 | Loop |
41 | |
42 | 'ISR von timer1 |
43 | Isr_von_timer1: |
44 | Timer1 = 34285 |
45 | '############################# |
46 | '#hier komme ich nicht weiter# |
47 | '############################# |
48 | Return |
49 | End |
mir fehlt einfach nur der ansatz wie man das lösen kann!! gruß peter
man kann mit einem Interrupt die Flanke detektieren, das willst du. so konfiguriert man die Int's bei einem zB Mega128. was ist da wirr ?
Wirr ist da z.B., daß er einen Mega16 hat und keinen Mega128. Und der hat auch keine 6 Ints. Prima, nun weiß er, wie beim 128er ganze 6 Ints so definiert werden, daß sie sogar in die gleiche ISR führen. Wo liegt da der Sinn?????? Würde ich als Anfänger auch nicht verstehen. @Peter: Ob deine 34285 für den Timer stimmen, habe ich gerade nicht nachgerechnet, kommt mir aber nicht bekannt vor. Was Du machen solltest, denn Deinem Programm fehlt doch so einiges: Du willst RPM2 auf das LCD schreiben, hast aber RPM2 nie dimensioniert!!! Da sollte aber der Compiler schon gemeckert haben. - Lege Deine beiden Tachoimpulse auf INT-Eingänge. - Dimensioniere zwei Variablen, die bei den entsprechenden INTs hochzählen. - Lege einen Timer an, der z.B. jede Sekunde ausgelöst wird. - Wenn der Timer auslöst, speicher Dir den Inhalt der beiden Variablen weg zum Berechnen. - Setze die Variablen und den Timer zurück. - Setze eine Merker-Variable, daß der Timer ausgelöst war. - Frage die Merker-Variable im Hauptprogramm ab, um die RPM-Berechnung auszuführen. - Lösche die Merker-Variable wieder. - Durch die beiden Variablen kennst du nun die Anzahl der Lüfterimpulse pro Sekunde und damit die Drehzahl. Versuchs mal!!
Hallo Das hört sich sehr amdängerfreundlich an! Danke! Ich werde es heute Nachmittag gleich ausprobieren! Gruss peter
Hallo! ich habe das jetzt mal so gemacht wie oben beschrieben. Und es funktioniert! Danke Hackes :-) und natürlich ein dank an alle anderen hier mein fertiger code:
1 | $regfile = "m16def.dat" |
2 | $crystal = 8000000 |
3 | |
4 | |
5 | 'LCD Config |
6 | Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portb.4 , Rs = Portb.3 |
7 | Cursor Off |
8 | Cls |
9 | |
10 | |
11 | 'Port Config |
12 | Config Pind.2 = Input |
13 | Portd.2 = 1 |
14 | Fan1 Alias Pind.2 |
15 | |
16 | Config Pind.3 = Input |
17 | Portd.3 = 1 |
18 | Fan2 Alias Pind.3 |
19 | |
20 | |
21 | 'Timer und interupts |
22 | Config Timer1 = Timer , Prescale = 256 |
23 | Enable Timer1 |
24 | On Timer1 Isr_timer1 |
25 | Timer1 = 34285 |
26 | |
27 | Config Int0 = Falling |
28 | Config Int1 = Falling |
29 | On Int0 Isr_int0 |
30 | On Int1 Isr_int1 |
31 | Enable Int0 |
32 | Enable Int1 |
33 | Enable Interrupts |
34 | |
35 | |
36 | 'Variablen |
37 | Dim Rpm1 As Word |
38 | Dim Rpm2 As Word |
39 | Dim Rpm1_temp As Word |
40 | Dim Rpm2_temp As Word |
41 | Dim X As Byte |
42 | |
43 | |
44 | 'Hauptprogramm |
45 | Do |
46 | |
47 | If X = 1 Then |
48 | 'werte berechnen |
49 | Rpm1 = Rpm1 * 30 'rpm * 30sek. (weil 2 imputse pro umdrehung) |
50 | Rpm2 = Rpm2 * 30 'rpm * 30sek. (weil 2 imputse pro umdrehung) |
51 | 'werte anzeigen |
52 | Cls |
53 | Locate 1 , 1 |
54 | Lcd Rpm1 |
55 | Locate 2 , 1 |
56 | Lcd Rpm2 |
57 | X = 0 |
58 | Wait 1 |
59 | End If |
60 | |
61 | Loop |
62 | |
63 | |
64 | 'isr von timer1 |
65 | Isr_timer1: |
66 | |
67 | If X = 1 Then |
68 | Return |
69 | End If |
70 | |
71 | Timer1 = 34285 |
72 | Rpm1 = Rpm1_temp |
73 | Rpm2 = Rpm2_temp |
74 | Rpm1_temp = 0 |
75 | Rpm2_temp = 0 |
76 | X = 1 |
77 | Return |
78 | |
79 | |
80 | 'isr von int0 |
81 | Isr_int0: |
82 | Rpm1_temp = Rpm1_temp + 1 |
83 | Return |
84 | |
85 | |
86 | 'isr von int1 |
87 | Isr_int1: |
88 | Rpm2_temp = Rpm2_temp + 1 |
89 | Return |
90 | |
91 | |
92 | 'Ende |
93 | End |
Ist wahrscheinlich nicht der Übersichtlichste code aber er funktioniert. Für Verbesserungsvorschläge habe ich immer ein offenes Ohr! Gruß Peter
Hallo Peter, prima, wenn es geklappt hat. Das freut mich. Habe es wirklich nur überflogen, aber grundsätzlich ist es das, was ich meinte. Unübersichtlich trifft es in der Tat etwas. Mache reichlich Gebrauch von der TAB-Taste!
1 | 'Hauptprogramm |
2 | Do |
3 | |
4 | If X = 1 Then |
5 | X = 0 'Merker SOFORT löschen |
6 | |
7 | 'werte berechnen |
8 | Rpm1 = Rpm1 * 30 'rpm * 30sek. (weil 2 imputse pro umdrehung) |
9 | Rpm2 = Rpm2 * 30 'rpm * 30sek. (weil 2 imputse pro umdrehung) |
10 | 'werte anzeigen |
11 | |
12 | Cls |
13 | Locate 1 , 1 |
14 | Lcd Rpm1 |
15 | Locate 2 , 1 |
16 | Lcd Rpm2 |
17 | |
18 | Wait 1 |
19 | End If |
20 | |
21 | Loop |
Das ist z.B. MEIN Stil. Muß man nicht zwingend so machen. Man erkennt welches LOOP zu welchem DO gehört und welches ENDIF zum IF. Bei den IFs finde ich das wichtig. Man erkennt sofort wo mal ein ENDIF fehlt. Den Merker sollte man direkt löschen, wenn er gesetzt wurde. Habe ich mal korrigiert. Dann ist es sehr unschön, daß es in der Timer-ISR zwei RETURNS gibt. Sowas macht man nicht. Zu einem Aufruf sollte es immer genau EIN Return geben. Im übrigen ist die Abfrage ob X=1 ist da überflüssig. Die ISR wird immer nach genau einer Sekunde aufgerufen. In der Zeit ist X im Hauptprogramm ganz sicher schon wieder gelöscht, also null. Oder ich sehe gerade den Haken nicht. Wenn Du Timer und INT-ISRs hast, dann ist es wichtig sich klar zu machen, wann wird mein Hauptprogramm "unterbrochen". WANN kann WAS überhaupt passieren. So, das war dann die konstruktive Kritik. Viel Spaß noch beim Programmieren lernen und hier im Forum. Gruß Hackes
Hallo! Danke werde ich mir zu herzen nehmen! Das mit "if x = 1" habe ich auch schon erkannt! Das Return aus "timer1_isr" habe ich raus genommen! Und dein Programmierstil ist sehr Übersichtlich, genau so steht es eigentlich auch in meinem Buch. Aber ich war wahrscheinlich zu faul. gruß peter
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.