www.mikrocontroller.net

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


Autor: Felix (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
  

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



int uart_putc (volatile char c)        
{
      while (!(UCSRA & (1<<UDRE)))  //warten 
    {
    }
 
    
 
    UDR = c;                      //senden
    return 0;
}


void uart_puts (char *s)   //string senden
{     
while (*s)     
  {   
   uart_putc(*s);         
   s++;     
  } 
}




int main(void)
{

 UCSRB |= (1<<TXEN);                // UART einschalten
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);   
 
    UBRRH = UBRR_VAL >> 8;
    UBRRL = UBRR_VAL & 0xFF;
 DDRD &= ~(1 << PD3);
 DDRD |= (1<<PD5);
 int i;
 

  while(1)
  {
     
  

if (PIND & (1<<PD2))
{
// Global Interrupts aktivieren
  sei();
  // Timer 0 konfigurieren
  
  TCCR0 |= (1<<CS00)|(1<<CS01)|(1<<WGM01); // Prescaler 64 
  
  OCR0 = 250-1; 
 
 
TIMSK |= (1<<OCIE0);
}


if (PIND & (1<<PD3))
{
   
  
  geschw = 5 / ((millisekunden + sekunden*1000) * 3600) ;   //Ber.
  TIMSK &= ~(1<<OCIE0);
  cli ();
  
   char s[8]; 
   dtostrf( geschw , 6, 3, s ); 
   uart_puts( s );




  for (i=0;i<5;i++)
   {
   PORTD |= (1<<PD5);
   _delay_ms(100);                    //StatusLed
   PORTD &= ~(1<<PD5);
   _delay_ms(100);
   }
  }
  }
          }
   

// Compare Interrupt Handler 

ISR (TIMER0_COMP_vect)
{
  millisekunden++;
  if(millisekunden == 2000)
  {
    sekunden++;
    millisekunden = 0;
   
  }
}



Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
  // Timer 0 konfigurieren
  TCCR0 |= (1<<CS00)|(1<<CS01)|(1<<WGM01); // Prescaler 64 
  OCR0 = 250-1; 

  while(1)
  {
    if (PIND & (1<<PD2)) // *** Start ***
    {
      millisekunden = 0;
      sekunden = 0;
      TCNT0 = 0;
      TIMSK |= (1<<OCIE0);
      sei();
    }

    if (PIND & (1<<PD3)) // *** STOPP ***
    {
      cli ();
      TIMSK &= ~(1<<OCIE0);

      // Berechnen...
      geschw = 5.0 / ((millisekunden + sekunden*1000UL) * 3600) ;

      // Ausgabe...
      // ...
    }    
  }
}  

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.