Hallo,
ich habe jetzt einige Zeit im Netz gesucht aber keine Lösung gefunden -
vielleicht stehe ich auch einfach auf dem Schlauch...
Ich habe einen Atmega328p und möchte über den Analog Comparator den
Ladezustand eines Kondensators messen um damit die Kapazität bestimmen
zu können. Es sollen ca. 1pF-500pF gemessen werden.
Nun habe ich von dem ACSR Register und dem ACI Bit gelesen. Mir fehlt
aber eine Vorlage um das auf Papier bringen zu können.
Ich möchte die interne ACBG Referenz verwenden und damit dann die Zeit
messen bis der Kondensator (bis ACBG) aufgeladen ist.
Gibt es da ein Beispiel in C?
Hugo P. schrieb:> Gibt es da ein Beispiel in C?
Ein Beispiel für Zeitmessungen in C?
Nicht eins, sondern ganz sicher tausende und mehr!
Such dir eins aus.
Hugo P. schrieb:> Ich habe einen Atmega328p und möchte über den Analog Comparator den> Ladezustand eines Kondensators messen um damit die Kapazität bestimmen> zu können. Es sollen ca. 1pF-500pF gemessen werden.
Ab gewisser Genauigkeitsanforderungen würde ich 1pF als "sportlich"
bezeichnen.
Das Bit soll ja gesetzt sein, wenn der Komparator den gewünschten
Zustand erkannt hat...was er vielleicht hat? Ich finde es auch ein wenig
krude, die Ein- und Ausgabe-Steuerung auf die Makros zu verteilen und
dahinter PC1 und PC0 zu legen. Ich hätte eher mit etwas in der Form DDRC
= (1 << PC0) | (1 << PC1) gerechnet, irgendwie in Funktionen gekapselt.
(Der Compiler macht daraus bei Bedarf ohnehin Inline-Konstrukte.)
Das ganze ist ja noch im Aufbau und nur für Tests gedacht. Jedoch komme
ich nicht darauf warum der AVR einen Reset macht!?
In die ISR Routine kommt er gar nicht mehr.
Hugo P. schrieb:> ISR(ANA_COMP_vect)> {> // clear interrupt> sbi(ACSR, ACI);> }> Ich komme bis zu dem while(!util_IsBitSet(ACSR, ACI)) - dann gibt es> einen Reset. Im Debugger sehe ich, dass das ACI Flag gesetzt ist.
Die While Schleife dürfte nie verlassen werden, weil laut Datenblatt das
Bit bei Ausführung der ISR gelöscht wird:
"Bit 4 – ACI: Analog Comparator Interrupt Flag
This bit is set by hardware when a comparator output event triggers the
interrupt mode defined by ACIS1 and
ACIS0. The Analog Comparator interrupt routine is executed if the ACIE
bit is set and the I-bit in SREG is set.
ACI is cleared by hardware when executing the corresponding interrupt
handling vector. Alternatively, ACI is
cleared by writing a logic one to the flag."
Hast du auch einen Schaltplan zu deinem Projekt?
TIFR1=_BV(ICF1)|_BV(OCF1A);// clear input capture and output compare flag bit
117
PORTD|=(1<<PD5);
118
// start charging
119
sbi(PORTC,CHARGE_C);
120
121
// wait until output is high
122
while(!(PINC&(1<<CHARGE_C)))
123
ICR1=0;
124
125
// wait for timer counter interrupt
126
while(!(tifr=(TIFR1&(_BV(ICF1)|_BV(OCF1A)))));
127
128
if(!(tifr&_BV(OCF1A)))// check for overflow bit
129
{
130
// stop counting
131
average[actual_value]=ICR1;
132
PORTD&=~(1<<PD5);
133
134
if(actual_value==sizeof(average)-1)
135
{
136
uint32_tsum=0;
137
138
for(intloop=0;loop<sizeof(average);loop++)
139
sum=sum+average[loop];
140
141
sum/=sizeof(average);
142
143
uart_putc((sum>>8)&0xFF);
144
uart_putc(sum&0xFF);
145
}
146
}
147
else
148
PORTD&=~(1<<PD5);
149
}
150
}
151
}
Mit dem Oszi messe ich eine Zeit von ~205µs. Ich habe einen 12MHz Quarz
und einen Prescaler von 1. Somit sollte in ICR1 ein Wert von ~2500
rauskommen. Ich bekomme aber bei 100 Werten im Mittel zwischen 120-140
Counts.
Das sind dann 1/12000000 * 130 == ~11µs ??
Der PD5 wird nur als Trigger für das Oszi hergenommen (Channel 3, blau).
Channel 1, gelb, ist die Spannung am Kondensator.
EDIT: uint8_t average[100] = {0};
Kann nicht gehen in einem uint8_t array uint16_t Werte abzulegen.
Jetzt bekomme ich einen Wert von ~2475:
Das sind dann ca. 0,00020625 Sekunden. Passt also!
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