Hallo Zusammen

Um die Geschwindigkeit eines Modellautos zu messen arbeite ich mit einem Weg-Impuls-Geber.

Nun habe ich jedoch noch einige Probleme mit der Software. Das folgende Modul funktioniert ganz gut, muss jedoch irgendwo noch einen Bug haben, da es in zufälligen Abständen (zwischen wenigen hunder Millisekunden und einigen Minuten) zu Fehlauswertungen kommt. freqGet() liefert dann irgend einen komisch Wert, welcher am häufigsten 0 ist. Dabei wird die Frequenz zurzeit noch von einem Rechteckgenerator geliefert. An diesem sollte es also nicht liegen.

Damit man den Code schneller versteht hier ein paar grundsätzliche Dinge:

Das Signal liegt am Analogkomperator, welcher mit einem Kondensator noch einwenig geglättet wird. Getriggert wird bei 2.5V. Das Signal ist ein Rechteck von 0-5V.
Um zusätzlich noch entprellen zu können wird der Analog Comparator Interrupt beim auftreten eines Interrupts kurz deaktiviert und einwenig später vom Timer wieder aktiviert.
timGet() liefert ein DWord (32 Bit langer unsigned Typ). Dieses zählt auf dem Systemtakt hoch und überläuft nach ca. 9min einfach.


Ich komme bei diesem Problem schon seit geraumer Zeit nicht weiter. Finden vielleicht jemand von euch den Fehler?

Code:
/// includes --------------------------------------------------------------------
#include <normlib.h>
#include <interrupt.h>
#include "avr.h"
#include "tim.h"
#include "out.h"
#include "dataTable.h"
#include "data.h"
#include "freq.h"

// global variables ------------------------------------------------------------
byte freqPulsLedFlag;
byte freqEnable;

// local definitions -----------------------------------------------------------

// local variables -------------------------------------------------------------
static word  actFreq;
static dword t0,tI1; //timestamp of last puls
static dword dt;     //delta t
static byte  signal;
static byte  preload;
static dword pLedTime;

// global function implementation ----------------------------------------------
void freqInit(){
  TCCR0=BV(CS02)|BV(CS00); // activate Timer 0, prescaler /1024
  preload=dataGetByte(DATATABLE_AC_TCNT0); //preload  of Timer0

  // Enable Analog Comparator, Enable Analog Comparator Interrupt
  if(dataGetByte(DATATABLE_AC_EDGE))
    ACSR=BV(ACIS0)|BV(ACIS1); //rising Edge
  else
    ACSR=BV(ACIS1);           //falling Edge

  cbi(ACSR,ACD);   //Enable Analog Comparator
  sbi(ACSR,ACIE);  //Enable Analog Comparator Interrupt
  
  actFreq        =0;
  signal         =FALSE;
  freqPulsLedFlag=TRUE;
  freqEnable     =TRUE;
  pLedTime       =(F_CPU/1000)*dataGetWord(DATATABLE_PULS_LED_FREQ);
}
word freqGet(){
  return actFreq;
}
void freqUpdate(){
  if(!freqEnable)
    return;
  cli();
  dword t1=tI1;
  sei();
  if(t0!=t1){
    signal=TRUE;
    if(t1<t0)
      dt=-t0+t1;
    else
      dt=t1-t0;
    if(dt<((dword)(10*F_CPU/0xFFFF)))
      actFreq=0xFFFF;
    else
      actFreq=(word)((dword)(10*F_CPU)/dt);
    t0=t1;
    if(freqPulsLedFlag)    
      outClear(OUT_PULS);
  }
  if(!signal){
    actFreq=0;
    return;
  }
  if(t0==t1){
    dword t2=timGet();
    dword dtN;
    if(t2<t0)
      dtN=-t0+t2;
    else
      dtN=t2-t0;
    if(dtN>dt){
      actFreq=(word)((dword)(10*F_CPU)/dtN);
    }
  }
  if(timReached((dword)F_CPU,t0))
    signal=FALSE;
  if(freqPulsLedFlag&&timReached(pLedTime,t0))
    outSet(OUT_PULS);
}

// interrupt routines ----------------------------------------------------------
ISR(ANA_COMP_vect){
  tI1=timGet();
  cbi(ACSR,ACIE);  //disable Analog Comparator Interrupt
  TCNT0=preload;   //preload Timer0
  sbi(TIMSK,TOIE0);//enable Timer 0 Interrupt  
}
ISR(TIMER0_OVF_vect){
  sbi(ACSR,ACI);   //clear Analog Comparator Interrupt Flag
  sbi(ACSR,ACIE);  //enable Analog Comparator Interrupt
  cbi(TIMSK,TOIE0);//disable Timer 0 Overflow Interrupt
}

// EOF -------------------------------------------------------------------------
Danke für eure Hilfe!

Gruss
cumi