Forum: Mikrocontroller und Digitale Elektronik Windgeschwindigkeitsmesser


von Mischa L. (mischamv)


Lesenswert?

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

von Helfer (Gast)


Lesenswert?

Jo, was spricht dagegen? Steht was gegenteiliges in den Datenblättern 
des µC oder des Reed-Relais?

von Mischa L. (mischamv)


Lesenswert?

@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
}

von Helfer (Gast)


Lesenswert?

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?

von Helfer (Gast)


Lesenswert?

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.

von Helfer (Gast)


Lesenswert?

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.

von Mischa L. (mischamv)


Lesenswert?

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

von Helfer (Gast)


Lesenswert?

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.

von Helfer (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.