Hallo Leute,
für die Experimentierplatine, die wir hier beschrieben haben:
https://www.roboternetz.de/phpBB2/ze...ag.php?t=53424
... und die hier:
http://www.rn-wissen.de/index.php/RP...itmach-Projekt
... gebaut wurde, hier ein zweites Programm für die M32. Es funktioniert ab der Phase 3 des Aufbaus.
Auf dem LCD wird die Zahl der CSync-Flanken bis zur 1. TV Zeile, die Anzahl der TV Zeilen und der Video Pegel der Austastlücke und einer TV Zeile angezeigt.
Viel Spaß!Code:/* * **************************************************************************** * RP6 ROBOT SYSTEM - RP6 CONTROL M32 TESTS * **************************************************************************** * Beispiel: Zählt die Video (TV) Zeilen einer CMOS Kamera * Autor(en): Dirk * **************************************************************************** * Beschreibung: * * Mit diesem Programm kann die Zeilenzahl einer CMOS Kamera (CONRAD 150001) * und die Zahl der CSync Flanken von VSync bis zur ersten TV Zeile auf dem * LCD angezeigt werden. Der Video Pegel der Austastlücke und einer TV Zeile * wird auch angezeigt. * Die Kamera ist an dieses Hardware Projekt (Phase 3 und höher) angeschlossen: * http://www.rn-wissen.de/index.php/RP...itmach-Projekt * Die BAS Video Information (PG3) ist angeschlossen an ADC4 (M32 ADC Stecker, * Pin 3). * Die Synchronisationssignale sind wie folgt verbunden: * * Signal RP6 Name Port Funktion * VSync EINT2 PD3 INT1 * HSync IO_PD6 PD6 ICP1 * Odd/Even EINT3 PB2 INT2 * * ############################################################################ * Der Roboter bewegt sich NICHT in diesem Beispiel! Du kannst ihn einfach auf * einen Tisch neben deinen PC stellen und solltest ihn mit dem PC über das * USB-Interface verbinden! * ############################################################################ * **************************************************************************** */ /*****************************************************************************/ // Einzufügende Dateien: #include "RP6ControlLib.h" // Die RP6 Control Bibliothek. // Muss immer eingefügt werden! /*****************************************************************************/ // Definitionen: #define FALLING 0 // Fallende Flanken #define RISING 1 // Steigende Flanken //------------------------------- #define EDGE FALLING //<== Wähle FALLENDE oder // STEIGENDE Flanken! //------------------------------- #define ODD (1<<EINT3) // Feld 1 #define EVEN 0 // Feld 2 //------------------------------- #define FIELD ODD //<== Wähle Feld 1 oder Feld 2! //------------------------------- #define VIDEO_BLANK 108 //<== Passe den Video Pegel der // Austastlücke an! #define HSYNC (PIND & IO_PD6) #define VSYNC (PIND & EINT2) #define ODD_EVEN (PINB & EINT3) #define IRon() (PORTC &= ~IO_PC6) #define IRoff() (PORTC |= IO_PC6) /*****************************************************************************/ // Variablen: volatile uint16_t edgecnt; volatile uint16_t video; volatile uint8_t tvlevelflag; uint8_t field; uint16_t blankedges; uint16_t tvlines; uint16_t videolevel_1; uint16_t videolevel_2; /*****************************************************************************/ // Funktionen: /** * TIMER1 Capture ISR * * In dieser ISR werden die fallenden/steigenden Flanken des CSync Signals * ab VSync gezählt, und der Video Pegel wird einmal pro Zeile mit ADC4 * gemessen. Im Hauptprogramm muss edgecnt direkt nach der fallenden * Flanke von VSync auf Null zurückgesetzt werden! * Die komplette Zeit der Messung vom Zeitpunkt des "Sample and Hold" bis * zum Ergebnis in ADC liegt in der ersten Hälfte der TV Zeile, weil * einige Impulse in der Austastlücke einen Abstand von ca. 32 µs (eine * halbe TV Zeile) haben. Daher darf die ISR nicht länger als eine halbe * TV Zeile dauern! * Der Video Pegel wird NICHT nach den ersten 10 CSync Flanken nach VSync * gemessen. * * Ausgabe: edgecnt -> CSync Flankenzähler * video -> 10 Bit ADC Wert (Video Pegel) * tvlevelflag -> true: TV Zeile mit Video Inhalt * false: Austastlücke * * ACHTUNG: Die Konstante VIDEO_BLANK muss auf einen Video Pegel * zwischen dem Pegel der Austastlücke und dem einer TV * Zeile in einem völlig dunklen Raum angepaßt werden! * */ ISR (TIMER1_CAPT_vect) {uint8_t h_delay; edgecnt++; tvlevelflag = false; if (edgecnt > 10) { h_delay=15; while (h_delay--) {nop();}; ADMUX = (1<<REFS0) | (1<<REFS1) | (ADC_4<<MUX0); ADCSRA = (0<<ADIE) | (1<<ADSC) | (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADIF); while(ADCSRA & (1<<ADIF)); ADCSRA |= (1<<ADIF); video = ADC; if (video > VIDEO_BLANK) tvlevelflag = true; } } /*****************************************************************************/ // Haupt Funktion - Das Programm beginnt hier: int main(void) { initRP6Control(); initLCD(); showScreenLCD("################", "################"); mSleep(1500); showScreenLCD("<<RP6 Control>>", "<<LC - DISPLAY>>"); mSleep(2500); showScreenLCD(" Video Lines Cnt", " Version 1.00 "); mSleep(2500); clearLCD(); setLEDs(0b0000); // Initialisiere den M32 ICP Pin (PD6) als Eingang: DDRD &= ~IO_PD6; // ==> HSync PORTD |= IO_PD6; // Pullup an // Initialisiere den M32 INT1 Pin (PD3) als Eingang: DDRD &= ~EINT2; // ==> VSync PORTD |= EINT2; // Pullup an // Initialisiere den M32 INT2 Pin (PB2) als Eingang: DDRB &= ~EINT3; // ==> Odd/Even PORTB |= EINT3; // Pullup an // Initialisiere den M32 TOSC1 Pin (PC6) als Ausgang: DDRC |= IO_PC6; // ==> IR IRoff(); // IR LEDs aus // Initialisiere die M32 Timer1 Input Capture Funktion: TCCR1B = (1<<CS10) // Trigger: Kein Vorteiler | (1<<ICNC1); // und Noise Canceler #if EDGE TCCR1B |= (1<<ICES1); // Steigende Flanke #else TCCR1B &= ~(1<<ICES1); // Fallende Flanke #endif /* // Zeige die ADC Werte der Austastlücke und einer TV Zeile: // Wenn man VIDEO_BLANK (für eine andere Kamera) anpassen will, // muss man diese Konstante auf einen Wert setzen, der zwischen // den beiden hier angezeigten Werten liegt. Das muss in einem // dunklen Raum gemacht werden, um einen sehr niedrigen TV // Video Pegel zu erreichen! TIMSK = (1<<TICIE1); // Aktiviere Capture ISR while(true) { while(VSYNC); // Warte auf Seitenanfang TIFR = (1<<ICF1); // Lösche aktiven Interrupt edgecnt = 0; // Flankenzähler zurücksetzen while(edgecnt < 18); // Austastlücke! videolevel_2 = video; // Speichere Pegel der Austastlücke while(edgecnt < 120); // TV Zeilen Bereich! videolevel_1 = video; // Speichere TV Video Pegel setCursorPosLCD(0, 0); writeStringLCD("Video Blank "); writeIntegerLengthLCD(videolevel_2, DEC, 3); setCursorPosLCD(1, 0); writeStringLCD("Video TV "); writeIntegerLengthLCD(videolevel_1, DEC, 3); while(!VSYNC); // Warte auf VSync Highpegel } */ // Zeige die Anzahl der CSync Flanken bis zur ersten TV Zeile, // die Zahl der TV Zeilen, den Video Pegel der Austastlücke und // einer TV Zeile an: // Wenn hier keine realistischen Werte angezeigt werden, muss // die Konstante VIDEO_BLANK (siehe oben!) angepaßt werden. while(true) { while(VSYNC); // Warte auf Seitenanfang nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); TIFR = (1<<ICF1); // Lösche aktiven Interrupt edgecnt = 0; // Flankenzähler zurücksetzen TIMSK = (1<<TICIE1); // Aktiviere Capture ISR field = ODD_EVEN; // Feld Nummer? if ((field && FIELD) || ((!field) && (!FIELD))) { // Gewähltes Feld? tvlevelflag = false; while(!tvlevelflag); // Zähle bis zur ersten TV Zeile blankedges = edgecnt; videolevel_1 = video; // Speichere den TV Video Pegel blankedges--; // HSync der ersten TV Zeile! while(tvlevelflag); // Zähle bis zum Ende der TV Zeilen tvlines = edgecnt - blankedges; videolevel_2 = video; // Speichere Pegel der Austastlücke tvlines--; // Anzahl TV Zeilen! TIMSK &= ~(1<<TICIE1); // Inaktiviere Capture ISR setCursorPosLCD(0, 0); writeStringLCD("Ebn"); writeIntegerLengthLCD(blankedges, DEC, 3); setCursorPosLCD(0, 7); writeStringLCD("Ltv"); writeIntegerLengthLCD(tvlines, DEC, 3); if (field) writeStringLCD(" :O"); // Zeige Odd/Even Feld else writeStringLCD(" :E"); setCursorPosLCD(1, 0); writeStringLCD("Vbn"); writeIntegerLengthLCD(videolevel_2, DEC, 3); setCursorPosLCD(1, 7); writeStringLCD("Vtv"); writeIntegerLengthLCD(videolevel_1, DEC, 3); #if (EDGE == FALLING) writeStringLCD(" :F"); // Zeige Falling/Rising Flanke #else writeStringLCD(" :R"); #endif while(!VSYNC); // Warte auf VSync Highpegel } } return 0; } /****************************************************************************** * Additional info * **************************************************************************** * Changelog: * - v. 1.0 (initial release) 07.05.2010 by Dirk * * **************************************************************************** */ /*****************************************************************************/
Gruß Dirk
Lesezeichen