cumi
24.01.2007, 15:33
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?
/// 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
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?
/// 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