Hallo, ich habe einen Windgeschwindigkeitsmesser, die Spannung wird einfach mit einem Reed-Relais geschaltet. 0-100Hz 0 bis 40m/s und ich will die Frequenz messen. Kann ich es direkt an µC anschließen, dass es einfach 5V mit Reed geschalten wird? gruß Mischa
Jo, was spricht dagegen? Steht was gegenteiliges in den Datenblättern des µC oder des Reed-Relais?
@Helfer eigentlich nichts. Nachdem ich verusucht hatte mittels timer/interrupt je 1sekunde die Anzahl der Impulse zu messen. Habe ich dieses Code gefunden. Kann mir da jemand helfen, wie ich das ganze in Sekunden umrechnen kann? gruß
1 | #include <avr\io.h> |
2 | #include <avr\interrupt.h> |
3 | #define ICP PINB0
|
4 | |
5 | //define ovrflow counter
|
6 | |
7 | uint16_t ov_counter; |
8 | |
9 | //define times for start and end of signal
|
10 | |
11 | uint16_t rising, falling; |
12 | |
13 | //define overall counts
|
14 | |
15 | uint32_t counts; |
16 | |
17 | //overflow counter interrupts service routine
|
18 | |
19 | |
20 | |
21 | ISR(TIMER1_OVF_vect){ |
22 | |
23 | ov_counter++; |
24 | |
25 | }
|
26 | |
27 | //Timer1 capture interrupt service subroutine
|
28 | |
29 | ISR(TIMER1_CAPT_vect){ |
30 | |
31 | /*This subroutine checks was it start of pulse (rising edge)
|
32 | |
33 | or was it end (fallingedge)and performs required operations*/
|
34 | |
35 | if (ICP) //if high level |
36 | |
37 | {
|
38 | |
39 | //save start time
|
40 | |
41 | rising=ICR1; |
42 | |
43 | //set to trigger on falling edge
|
44 | |
45 | TCCR1B=TCCR1B&0xBF; |
46 | |
47 | //reset overflow counter
|
48 | |
49 | ov_counter=0; |
50 | |
51 | }
|
52 | |
53 | else
|
54 | |
55 | {
|
56 | |
57 | //save falling time
|
58 | |
59 | falling=ICR1; |
60 | |
61 | //rising edge triggers next
|
62 | |
63 | TCCR1B=TCCR1B|0x40; |
64 | |
65 | counts=(uint32_t)falling-(uint32_t)rising+(uint32_t)ov_counter; |
66 | |
67 | |
68 | |
69 | |
70 | /*you can convert coutns to seconds and send to LCD*/
|
71 | |
72 | }
|
73 | |
74 | }
|
75 | |
76 | |
77 | int main(void) { |
78 | |
79 | //Serielle übertragung aktivieren
|
80 | |
81 | |
82 | |
83 | //enable overflow and input capture interrupts
|
84 | |
85 | TIMSK1=0x24; |
86 | |
87 | /*Noise canceller, without prescaler, rising edge*/
|
88 | |
89 | TCCR1B=0xC1; |
90 | |
91 | sei(); |
92 | |
93 | |
94 | |
95 | while(1) { |
96 | }
|
97 | |
98 | }
|
Die Umrechnungan scheitert daran, dass man nicht weiss, wie schnell dein AVR getaktet wird. Du kannst dir die Umrechnung fürs erste auch schenken und mal counts also quasi die Rohdaten als solche anzeigen lassen. Ändert sich counts sinnvoll mit der Geschwindigkeit des Windmessers?
Wenn du eine sinnvolle Anzeige von counts bekommst: Du hast F_CPU Takte pro Sekunde, also entsprechen laut Dreisatz counts Takte t Sekunden... Damit kannst du t und damit auch die Frequenz f = 1/t und damit auch die Windgeschwindigkeit ausrechnen. Wenn du keine sinnvolle Anzeige von counts bekommst: Das Thema Entprellung ist auch bei Reed-Relais aktuell.
Der Code ist im übrigen nicht besonders gut geschrieben. Du solltest unbedingt die Grundlagen des Artikels Interrupt bzgl. volatile und atomarem Zugriff im Code ergänzen.
Super, danke für die schnelle Antowort. der Atmega328p ist mit 16 MHz getaktet. Was genau meint Ihr mit unsauberer Programmierung, z.B. dass zu viele Anweisungen in Interrupt ausgeführt werden? gruß Mischa
Nö, dazu kann ich noch nix sagen, weil noch kein fetter Code in den ISRs steht. Grundsätzlich hast du aber mit dem Ziel knappen Code in der ISR zu schreiben Recht. Die Stelle /*you can convert coutns to seconds and send to LCD*/ musst du ja nicht mit lahmem Code füllen, sondern du kannst (und solltest) die Aufbereitung und die Ausgabe im Programmteil ausserhab der ISRs machen. Ich meinte besonders: >> Du solltest unbedingt die Grundlagen des Artikels Interrupt >> bzgl. volatile und atomarem Zugriff im Code ergänzen. counts solltest du volatile machen. Und wenn du auf counts im Hauptprogramm zugreifst, muss du den Zugriff atomar kapseln, d.h. während des Lesezugriffs die Interrupts kurz sperren. Kurz heisst daher Interrupts sperren, Lesen und Kopie anlegen, Interrupts freigeben dann mit Kopie weiterarbeiten. Ein nicht volatiles ov_counter könnte funktionieren, da die Variablen nur innerhalb der ISRs benutzt wird und die selber nicht von Interrupts unterbrochen werden. Schön ist diese Variante aber nicht. ov_counter würde ich auch volatile machen.
Bei deiner Formel für counts stimmt IMHO was nicht:
>> counts=(uint32_t)falling-(uint32_t)rising+(uint32_t)ov_counter;
Ich würde benutzen:
counts = 65536UL * ov_counter + falling - rising;
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.