Guten Tag,
ich möchte gerne mit einem ATmega88 die Drehzahl eines Motors erfassen.
Dazu nutze ich einen Hall Sensor, der pro Motorumdrehung einen Impuls
erzeugt. Die Impulse erfasse ich mithilfe der Input Capture Einheit des
Controllers.
Da ich den Timer 1 schon zum generieren eines PWM Signales nutze, läuft
dieser mit einer Frequenz von ca. 20 kHz (prescaler von 1). Gleichzeitig
möchte ich über diesen Timer die Dauer einer Motorumdrehung messen, um
daraus die Drehzahl zu berechnen. Der Code dazu sieht folgendermaßen
aus:
1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | #define true 1
|
5 | #define false 0
|
6 | #define F_CPU 8000000UL
|
7 | #define periodendauer_timer1 (1000000 / (F_CPU/1024)) //in us
|
8 |
|
9 | volatile uint16_t ueberlauf;
|
10 | volatile uint16_t icr1_wert_1;
|
11 | volatile uint16_t icr1_wert_2;
|
12 | volatile uint16_t uerberlauf_gesp;
|
13 | volatile uint8_t messung_beendet;
|
14 | uint16_t drehzahl;
|
15 |
|
16 | void timer_1_init(void)
|
17 | {
|
18 | TCCR1A |= (1<<WGM10) | (1<<WGM11) | (1<<COM0A1); //WGM10, WGM11, WGM12 = 1; 10-Bit Fast PWM Mode, OC1A(PB1) = PWM output
|
19 | TCCR1B |= (1<<WGM12) | (1<<ICNC1) | (1<<ICES1); //ICNC1, ICES1 = 1; Input Capture am ICP1 Pin (PB0) aktiviert mit Filter
|
20 | TCCR1B |= (1<<CS10); //CPU clk / 1 (Kein Teiler)
|
21 | TIMSK1 |= (1<<TOIE1) | (1<<ICIE1); //Interrupt bei: Input Capture und TimerÜberlauf
|
22 | }
|
23 |
|
24 |
|
25 | int main(void)
|
26 | {
|
27 | DDRD |= (1<<PD0) | (1<<PD1) | (1<<PD6);
|
28 | DDRB |= (1<<PB1);
|
29 |
|
30 | timer_1_init();
|
31 |
|
32 | sei (); //Glogale Interrupts aktivieren
|
33 |
|
34 | while (1)
|
35 | {
|
36 | if (messung_beendet == true)
|
37 | {
|
38 | messung_beendet = false;
|
39 | uint32_t x = uerberlauf_gesp * periodendauer_timer1;
|
40 | uint16_t y = (1024-icr1_wert_1 + icr1_wert_2) * (periodendauer_timer1 / 1024.0);
|
41 |
|
42 | drehzahl = (60000000 / (x + y));
|
43 | }
|
44 | }
|
45 | }
|
46 |
|
47 | ISR (TIMER1_OVF_vect)
|
48 | {
|
49 | OCR1A = pwm_duty_ocr1a; //Übernahme des PWM Tastgrads von der Regelung
|
50 | ueberlauf ++;
|
51 | }
|
52 |
|
53 | ISR (TIMER1_CAPT_vect)
|
54 | {
|
55 | static uint8_t durchlauf;
|
56 |
|
57 | if (durchlauf == 0)
|
58 | {
|
59 | ueberlauf = 0;
|
60 | icr1_wert_1 = ICR1;
|
61 | durchlauf ++;
|
62 | }
|
63 | else if (durchlauf == 1)
|
64 | {
|
65 | durchlauf = 0;
|
66 | icr1_wert_2 = ICR1;
|
67 | uerberlauf_gesp = ueberlauf;
|
68 | messung_beendet = true;
|
69 | }
|
70 | }
|
Da ich noch Anfänger bin, wollte ich Euch fragen, ob Ihr das anders
lösen würdet oder ob Ihr Verbesserungsvorschläge zum Code habt.