Hallo
Allerdings eine frage was willst du mit 4-Bit, das ist ja extrem ungenau.
Wenn ich nur schwarz oder weis unterscheiden will, sind 4Bit mehr als genug.
Inzwischen habe ich das mit dem ADC gut im Griff und kann mit einem 8MHz-ATMega ein Fernsehbild(bas) digitalisieren. Allerdings nicht mit der maximalen horizontalen Auflösung, dafür reichen die 8MHz nicht aus. Vertikal habe ich aber volle Auflösung (bei 384*288 Punkten).
Um die maximale Abtastrate zu erreichen betreibt man den ADC im free-running-Modus mit dem kleinsten prescaler-Wert (clk/2). Dann muss man nur noch möglichst schnell die gewandelten Daten auslesen, weil der ADC pro Wandlung nur 2 Takte benötigt. Deshalb kommt es quasi auf jeden Takt an, der zum Lesen benötigt wird. Da der ADC nur einen neuen Wert bildet, wenn ein alter gelesen wurde, kann man sich die ganze Handshakerei sparen. Da 8 Bit schneller als 16Bit gelesen werden können, stellt man ein linksbündiges Ergebniss ein und liest nur ADCH aus. Hier das Setup meines ADCs:
Code:
// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4 (E_INT1)
ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 4;
// setzte free running triggern
SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein interupt, Wandler einschalten, prescaller /2
ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
// Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen
ADCSRA |= (1<<ADATE) | (1<<ADIF);
// Initialisierung starten
ADCSRA |= (1<<ADSC);
// und noch die wohl eher unnötige Initiallesung
while (!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
Nach diesem Code sampelt der ADC ununterbrochen die angelegte Spannung. Nun muss man die Daten so schnell wie möglich in den Speicher übertragen um sie später auszuwerten. In C geht das wohl mit Zeigern auf Felder am schnellsten:
uint8_t pixel[256],*pixelzeiger=pixel[0];
do *pixelzeiger=ADCH; while (*pixelzeiger++ > 20);
So schaffe ich ca. 60 Werte/Zeile des Videobilds. Andere Varianten die ohne Zeiger direkt auf das Feld zugreifen liefern max. 50 Werte pro Zeile.
Wegen der internen 2,56V-Referenz des ADCs bedeuten Werte < 30 ein Synchronsignal, also den Start einer neuen Zeile. Um eine Zeile einzulesen um die Werte anschliesend in einem Diagramm darzustellen, genügt dieser kurze Code:
Code:
cli();
while (ADCH > 20); // warten bis aktuelle Zeile zu Ende
while (ADCH < 30); // warten bis Synchronimpuls fertig
do *pixelzeiger=ADCH; while (*pixelzeiger++ > 20);
sei();
*pixelzeiger=0; // Endekennung der Daten
Danach stehen die Daten in pixel[] mit einer 0 im letzten Element.
Bei der schrittweisen Erhöhung der Abtast- und Auslesegeschwindigkeit habe ich übrigens keine nennenswerten Fehllesungen festgestellt. Bei der verwendeten linksbündigen Darstellung des Ergebnisses betrug die Abweichung bei der Messung einer 1,5V-Batterie nur 0,02V gegenüber einer langsamen Messung mit prescaler /64.
Gruß
mic
Lesezeichen