Bin noch nicht ganz durch aber schon mal ein paar Vorab Erfahrungen:
Setup:
gamboy-Kamera an ATMega168 mit 18,432MHz Takt, 5V Versorgung.
Die Bilder werden während des Einlesens direkt über UART0 an den Host übertragen und dort mit dem hier schon erwähnten Java Programm angezeigt.
Folgende Dinge sind dabei zu beachten:
Damit der READ Pin auf low geht, dürfen einige Register nicht 0 sein! Ich teste das mal und setze die Werte hier ins Forum. Wichtig ist aber schon mal auf jeden Fall, dass die Belichtungszeit nicht 0 sein sollte. Damit muss entweder im C0 (reg3) oder C1 (reg2) Register ein Wert != 0 stehen.
Damit im Normalmodus (grauwert-positiv-bild) auch etwas erscheint, muss P=1 M=0 und X=1 sein (reg 4, 5, 6). Steht im Datenblatt auf Seite 14.
Jetzt kommt der entscheidende Punkt, damit man bei der direkten Übertragung des Bildes zum Host über die Serielle auch etwas sinnvolles erkennen kann:
Der M64282FP Chip, der in der Gameboy Kamera verbaut ist, hat keinen Shutter (Verschluss). Das heisst, dass während das Bild ausgelesen wird, die CMOS Elemente weiter Licht aufnehmen! Deswegen kommt es auch zu seltsamen Bildern, wenn man die Kamera zu schnell bewegt.
Hier mal eine kurze Berechnung.
XCLK wird optimal, sprich mit 500kHz getaktet. Den ADC squeeze ich ein bisschen, was laut Datenblatt OK ist, da nur 8bit verwendet werden, mit Prescaler 64, auf 288KHz. Eine ADC Wandlung braucht 13 Takte. Macht also als Gesamtzeit für ein Pixel:
13*1/288k+2us = 47.14us/Pixel
Alle Pixel brauchen dann: 128*128*47.14us = 740ms.
Was fehlt? Richtig: Die Übertragung zum Host!
Dadurch wird die Zeit pro Pixel verlängert. Bei 115200bd ist das (8N1+Startbit) = 115200/10 = 11520kB/s =>86.8us/Pixel. Die kommen also zu unserer Kalkulation oben nochmal hinzu.
In Summe landen wir dann bei 2.162 Sekunden/Bild.
Fazit:
Liest man nur das Bild ein, braucht man mit dem ATMega168, bzw. allen Designs, die den internen ADC der AVRs verwenden, 740ms/Bild. Das ist dann auch die Gesamtbelichungszeit für das letzte Pixel (das erste Pixel hat nur die normale Belichungszeit plus irgendwas <47us für's Auslesen). Schreibt man die Daten direkt zum Host wird's nochmal schlimmer. Die Belichtungszeit ist dann so lange, dass die CMOS Elemente ruckzuck in die Sättigung gehen (Weisses bzw. graues Bild).
Deswegen sollte die initiale Belichtungszeit kurz sein, da die Kamera während des auslesens noch genügend Licht aufnimmt.
Hier sind mal meine Parameter: Belichtungszeit ist in us. Offset Voltage in mV (ist aber 0) und Referenzspannung in Volt*2 (damit kein float anfällt). Ist aber auch 0 das Schwarz auf 0V kalibriert werden soll.
Code:
void initRetinaParams( void )
{
_retinaParams.mode = grey;
_retinaParams.enhancement = false;
_retinaParams.enhancementRatio = 50;
_retinaParams.invertImage = false;
_retinaParams.exposureTime = 4500;
_retinaParams.offsetVoltage = 0000;
_retinaParams.outputVoltageRef2 = 0;
_retinaParams.outputGain2 = 104;
_retinaParams.boostGainBy6dB = true;
}
Das führt bei mir zu folgenden Registerwerten:
0: 0x80
1: 0x10
2: 0x01
3: 0x19
4: 0x01
5: 0x00
6: 0x01
7: 0x00
Ich baue im Momemt noch eine Routine für's Binning (Reduktion der Bildauflösung). Sobald die fertig ist (hoffentlich morgen) kommt der ganze Code hier ins Forum. Das Bild ist dann zwar nur noch 24x24 Pixel groß, dafür wird es aber mit der vollen ADC Rate eingelesen und es ist noch genügend Platz im SRAM des 168 um Bildverarbeitung und diversen anderen Kram zu berechnen.
Für meine Zielapp werde ich eher auf den 162 wechseln, da der ein externes Speicherinterface hat, so das man ein komplettes Bild in maximaler Auflösung halten kann. Ausserdem sollte ein externer ADC ran, der die 500KHz Samplerate bringt.
Angenehmen Abend.
Ingo
BTW: Besteht Interesse am Code in C++ oder machen hier alle C?
Lesezeichen