Forum: Mikrocontroller und Digitale Elektronik Mega16 Timer-Start/Stop für Geschwindigkeitsmessung


von Felix (Gast)


Lesenswert?

Hallo zusammen,
ich versuch mich schon seit Tagen an einer Geschwindigkeitsmessung mit 
einem mega16.
Es soll die Geschwindigkeit auf 5m berechnet und per rs232 aufn PC 
gegeben werden, allerdings wird hier nur 0.0000000 oder 65536.000 
gesendet...
Timer-Start mit PD2, Stopp mit PD3.
Auch nach einschlägigen Tipps hab ich nen Gerhirnknoten.
Kann mir jemand die betreffende Stelle coden?
Danke schonmal für die Hilfe,
Felix
1
  
2
3
volatile unsigned int  millisekunden;
4
volatile unsigned int sekunden;
5
volatile float geschw;
6
volatile unsigned int i;
7
8
9
10
int uart_putc (volatile char c)        
11
{
12
      while (!(UCSRA & (1<<UDRE)))  //warten 
13
    {
14
    }
15
 
16
    
17
 
18
    UDR = c;                      //senden
19
    return 0;
20
}
21
22
23
void uart_puts (char *s)   //string senden
24
{     
25
while (*s)     
26
  {   
27
   uart_putc(*s);         
28
   s++;     
29
  } 
30
}
31
32
33
34
35
int main(void)
36
{
37
38
 UCSRB |= (1<<TXEN);                // UART einschalten
39
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);   
40
 
41
    UBRRH = UBRR_VAL >> 8;
42
    UBRRL = UBRR_VAL & 0xFF;
43
 DDRD &= ~(1 << PD3);
44
 DDRD |= (1<<PD5);
45
 int i;
46
 
47
48
  while(1)
49
  {
50
     
51
  
52
53
if (PIND & (1<<PD2))
54
{
55
// Global Interrupts aktivieren
56
  sei();
57
  // Timer 0 konfigurieren
58
  
59
  TCCR0 |= (1<<CS00)|(1<<CS01)|(1<<WGM01); // Prescaler 64 
60
  
61
  OCR0 = 250-1; 
62
 
63
 
64
TIMSK |= (1<<OCIE0);
65
}
66
67
68
if (PIND & (1<<PD3))
69
{
70
   
71
  
72
  geschw = 5 / ((millisekunden + sekunden*1000) * 3600) ;   //Ber.
73
  TIMSK &= ~(1<<OCIE0);
74
  cli ();
75
  
76
   char s[8]; 
77
   dtostrf( geschw , 6, 3, s ); 
78
   uart_puts( s );
79
80
81
82
83
  for (i=0;i<5;i++)
84
   {
85
   PORTD |= (1<<PD5);
86
   _delay_ms(100);                    //StatusLed
87
   PORTD &= ~(1<<PD5);
88
   _delay_ms(100);
89
   }
90
  }
91
  }
92
          }
93
   
94
95
// Compare Interrupt Handler 
96
97
ISR (TIMER0_COMP_vect)
98
{
99
  millisekunden++;
100
  if(millisekunden == 2000)
101
  {
102
    sekunden++;
103
    millisekunden = 0;
104
   
105
  }
106
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> volatile unsigned int millisekunden;
> volatile unsigned int sekunden;
> volatile float geschw;

Ändere diese Berechnung damit es keinen Integer-Überlauf gibt:

>   geschw = 5 / ((millisekunden + sekunden*1000) * 3600) ;   //Ber.

Z.B. Float Ergebnis = Float Zähler / Unsigned long Nenner

>   geschw = 5.0 / ((millisekunden + sekunden*1000UL) * 3600) ;   //Ber.
                                                  ^^

Die Berechnung kannst du mit gutem Gewissen nach dem Abschalten des 
Timers machen, dann brauchst du dich auch nicht um atomaren Zugriff auf 
millisekunden und sekunden zu kümmern (s. AVR-GCC-Tutorial Variablen 
> 1 Byte). geschw braucht nicht volatile zu sein.

Die Berechnung könntest du bei diesem Verfahren geringfühig genauer 
machen, wenn du den angebrochenen Zählerstand im TCNT0 Register 
berücksichtigst.

Vor dem Start des Timers würde ich noch millisekunden und sekunden 
nullen, wenn mehrere Messungen gemacht werden sollen.

Und ich würde dann auch Umordnen:
1
  // Timer 0 konfigurieren
2
  TCCR0 |= (1<<CS00)|(1<<CS01)|(1<<WGM01); // Prescaler 64 
3
  OCR0 = 250-1; 
4
5
  while(1)
6
  {
7
    if (PIND & (1<<PD2)) // *** Start ***
8
    {
9
      millisekunden = 0;
10
      sekunden = 0;
11
      TCNT0 = 0;
12
      TIMSK |= (1<<OCIE0);
13
      sei();
14
    }
15
16
    if (PIND & (1<<PD3)) // *** STOPP ***
17
    {
18
      cli ();
19
      TIMSK &= ~(1<<OCIE0);
20
21
      // Berechnen...
22
      geschw = 5.0 / ((millisekunden + sekunden*1000UL) * 3600) ;
23
24
      // Ausgabe...
25
      // ...
26
    }    
27
  }
28
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Nachtrag: Check auch noch die Berechnung wegen der millisekunden. Es 
scheint so, dass du den Timer in 0,5ms Schritten laufen lässt (if 
(millisekunden == 2000)). Dann musst du das auch in der Formel für die 
Geschwindigkeit berücksichtigen!

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.