crazy horse wrote:
> andererseits: warum sollte man einen Eingang samplen, an dem sowieso
> nichts dran ist bzw. der auf Masse liegt??
Vermutlich, weil man ein betriebssystemähnliches Universalprogramm
schreiben will, dass auf alle Eventualitäten vorbereitet ist. ;-)
Spaß beiseite...
@Tim:
Ich habe mal in den Code reingeschaut, bin aber kein C-Freak, also aus
Sicht des Assembler nutzenden Bastlers. Dabei fiel mir auf:
- Der ADC wird auf Quelle und Referenzquelle eingestellt, gestartet
und per Busy-Poll gewartet, dass er fertig wird. Das ist zwar nicht
falsch, das würde ich aber nicht tun. Denn Busy-Poll ver"wartet"
wertvolle Rechenzeit, erzeugt Müll (Störimpulse) und bringt rein gar
nix. Stattdessen würde ich den ADC im Hintergrund laufen lassen und
entweder per ADC-Int oder (ganz nebenbei) per Timer-Int auslesen. Das
Aktivieren des Sleep während der Controller auf den nächsten Int
wartet, senkt auch den Müll (CPU-Takt ist ja im Sleep aus).
- Die erste Messung wird verworfen. Das ist gut so, denn unter
bestimmten
Bedingungen ist die erste Messung nach der Quellenumschaltung ja auch
fehlerhaft. Dann erfolgen 10 Messungen, deren Messwerte addiert
werden,
um sie dann durch 10 zu dividieren. Warum um Gottes Willen 10???
Hast Du mal drüber nachgedacht, wie sich ein AVR strecken muss, eine
Division durch 10 zu rechnen? Mit 8, 16 oder gar 256 Messungen könnte
der AVR das per Shift bzw. durch Verwerfen des Low-Bytes realisieren,
aber 10 ist einfach nicht zu Ende gedacht. Auch als C-Programmierer
sollte man daran denken, dass der AVR kein C kann, sondern nur ASM
bzw.
Maschinencode.
Wenn ich mehrere ADC-Werte brauche, dann lese ich diese reiherum ein.
Meist lasse ich den ADC frei laufen und frage den Wert im
Timer-Interrupt ab. Dieser ist sowiso vorhanden und kann das nebenbei
miterledigen. Dabei wird ADC-Tempo und Timer-Intervall so aufeinander
abgestimmt, dass pro Timer-Intervall mindestens zwei neue ADC-Wandlungen
erfolgt sind. Das sorgt dafür, dass die erste Wandlung ignoriert wird.
Im Timer-Interrupt lese ich nun erstmal ADMUX aus, ermittle daraus die
Quelle, lese dann ADC aus und sichere den Wert in einem Datenfeld
(Quelle als Index), incrementiere die Quelle und schreibe sie nach ADMUX
zurück. Nun kann sich der Controller in der Mainloop anderen Dingen
widmen, der ADC läuft im Hintergrund, er wandelt einmal, zweimal, .. und
irgendwann schlägt der Timer zu und liest ihn aus.
Wird das letzte Fünkchen Genauigkeit benötigt, dann ist der ADC nur
während Sleep im Mode ADC-Noise-Reduction zu betreiben, das ist aber
eine andere Baustelle, das erfordert etwas umsichtigeres Herangehen, da
der Timer-Takt solange deaktiviert ist und daher die Timer-Intervalle
daran angepasst werden müssen...
...