Hallo

Ein paar Gedanken zur Auflösung: Wie man in der Vergrößerung der oberen Bilder deutlich sieht, wir lesen den selben Wert mehrfach aus. Dazu eine kleine Rechnung: Der Takt ist 4MHz, ein Takt dauert 1/4000000=0,25µs. Eine ADC-Wandlung dauert im Dauerlauf 13 Takte, also 13*0,25µs=3,25µs. Wenn die Daten einer Zeile in 52µs durchrauschen sind 52/3,25=16 Wandlungen möglich! Deshalb sind in den 64Pixel breiten Bildern oben immer 4 Pixel nebeneinander gleich. Die Ausreiser kommen von kleinen Unterschieden im Timeing des Signals zum ADC-Takt.

Das war ja eigentlich klar (wurde auch schon mehrmals angemotzt), aber was ist mit Plan B: Nach dem Zeilenstart kurz warten und dann einen Pixel einlesen. Das bringt keine Verbesserung, weil der ADC ja weiterhin im Dauerlauf digitalisiert. Dummerweise auch noch asyncron zum Signal, bei 64µs pro Zeile kann er maximal 64/3,25=19,irgendwas Werte wandeln. Egal, wann wir den Wert einlesen, es wird immer einer der 16 möglichen Werte der Zeile sein.

Deshalb hier ein noch schnellerer Ansatz der mehr Werte aus einer Bildzeile rauskitzelt. Wie gehabt hangeln wir uns im Bild mit dem ADC im Dauerlauf durch den Bildstart und die ersten 30 Zeilen. Dann allerdings stoppe ich den ADC. Es wird dann erst der Spaltenversatz abgewartet, der ADC erneut gestartet und schließlich, nachdem der ADC die fertige Wandlung meldet, wird der Wert gespeichert. Da der ADC dann wieder im Dauerlauf digitalisiert, hangeln wir uns 5 Zeilen weiter durch das Bild und samplen nacheinander 48 Pixel in der gewählten Spalte. Nach 64 Halbbildern ist das Bild dann komplett mit 48X64 Pixeln eingelesen.

Code:
// RP6 sendet eine 48X64-HiRes-Bitmap über die serielle Schnittstelle      4.4.10 mic

 #include "RP6RobotBaseLib.h"

void ADC_Init(void)
{
	extIntOFF(); // schaltet den E_INT1-Port auf Eingang für den ADC

// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4 (E_INT1)
	ADMUX = (1<<REFS1) | (1<<REFS0)  | (1<<ADLAR) | 4;
// setze free running triggern
	SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein Interupt, Wandler einschalten, prescaler /2, ADC läuft nun mit 4MHz!
	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 empfohlene Initiallesung
	while (!(ADCSRA & (1<<ADIF)));
	ADCSRA |= (1<<ADIF);
}

int main(void)
{
	uint8_t bildspeicher[100], *bildzeiger; // 100 Byte Bildspeicher sollten reichen
	uint8_t zeile, sync, c;                 // und dürfen NICHT global sein!
	uint16_t spalte, i;
	uint8_t bmp_header_48_64_24bit[54]={
	0x42, 0x4d, 0x36, 0x24, 00, 00, 00, 00, 00, 00, 0x36, 00, 00, 00, 0x28, 00,
 	00, 00, 0x30, 00, 00, 00, 0x40, 00, 00, 00, 01, 00, 0x18, 00, 00, 00,
 	00, 00, 00, 0x24, 00, 00, 0xc4, 0x0e, 00, 00, 0xc4, 0x0e, 00, 00, 00, 00,
 	00, 00, 00, 00, 00, 00};
	initRobotBase();
	ADC_Init();

	while(1)
	{
		for(c=0; c<54; c++) writeChar(bmp_header_48_64_24bit[c]); // Header senden
  		for(spalte=0; spalte<64; spalte++)
		{
			bildzeiger=&bildspeicher[0]; // Zeiger auf Start des Bildspeicherbereich
			zeile=30; // aktuelle Zeile (35 Zeilen sind der Schrott beim Bildstart)
			setLEDs(63-spalte); // working
			
		   cli();
			do // Warten auf langen Syncbereich = Bildstart
			{
				sync=0;
				while (ADCH > 20); // warten solange Bilddaten erkannt werden
				while (ADCH < 30) sync++; // Länge des Sync-Signal zählen
			}while (sync < 40); // größer 40 bedeutet Bildstart

			while(zeile--)
			{
				while (ADCH > 20); // Bilddaten
				while (ADCH < 30); // Sync
			}
   		for(c=0; c<48; c++)
			{
				i=spalte;
				zeile=4; // Zeilensprung für 48 Zeilen
				while(zeile--)
				{
					while (ADCH > 20); // Bilddaten
					while (ADCH < 30); // Sync
				}

				ADCSRA &= ~(1<<ADEN); // ADC stoppen
				while(i--); // Pixel ansteuern
				ADCSRA |= (1<<ADATE) | (1<<ADEN) | (1<<ADIF) | (1<<ADSC); // ADC wieder starten
				while (!(ADCSRA & (1<<ADIF))); 	// 26 ADC-Takte warten bis Wandlung fertig
				*bildzeiger++=ADCH; 				// das sind ca. 6,5µs
				ADCSRA |= (1<<ADIF);
			}
			sei();

			for(zeile=0; zeile<48; zeile++) // 48 Pixel senden
			{
			   if (bildspeicher[zeile] > 20)
				{
					writeChar((bildspeicher[zeile]-20)*2); // RGB in Pixelfarbe
					writeChar((bildspeicher[zeile]-20)*2);
					writeChar((bildspeicher[zeile]-20)*2);
				}
				else
				{
					writeChar(0); // oder Schwarz
					writeChar(0);
					writeChar(0);
				}
			}
		}
		setLEDs(63); // ready
		while(!(getBumperLeft() || getBumperRight())); // Neues Bild senden?
	}
	return(0);
}
Wirklich beeindruckend ist das Ergebniss allerdings nicht:
Bild hier  

Gruß

mic