Dirk
30.04.2010, 20:36
Hallo Leute,
für die Experimentierplatine, die wir hier beschrieben haben:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=53424
... und die hier:
http://www.rn-wissen.de/index.php/RP6_Kamera_-_Mitmach-Projekt
... gebaut wurde, hier ein erstes Programm für die M32. Es funktioniert ab der Phase 3 des Aufbaus.
Ein 32x32 Pixel Bild wird auf dem Terminal ausgegeben. Das ursprüngliche Programm hat radbruch für die RP6Base geschrieben.
Was habe ich geändert:
1. Anpassung an die M32
2. Nutzung der Signale HSync und VSync des Sync-Separators auf der Exp.
/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - RP6 CONTROL M32 TESTS
* ************************************************** **************************
* Example: Grab video pictures and show them on the terminal
* Author(s): radbruch, modified for the M32: Dirk
* ************************************************** **************************
* Description:
*
* With this program (written by radbruch for the RP6Base) the picture of a
* CMOS camera (CONRAD 150001) can be displayed on the terminal.
* The camera is connected to this hardware project:
* http://www.rn-wissen.de/index.php/RP6_Kamera_-_Mitmach-Projekt
* The BAS video information (PG3) is connected to ADC4 (ADC plug, pin 3).
* The synchronization signals are connected as follows:
*
* Signal RP6 Name Port Function
* VSync EINT2 PD3 INT1
* HSync IO_PD6 PD6 ICP1
* Odd/Even EINT3 PB2 INT2
*
* ################################################## ##########################
* The Robot does NOT move in this example! You can simply put it on a table
* next to your PC and you should connect it to the PC via the USB Interface!
* ################################################## ##########################
* ************************************************** **************************
*/
/************************************************** ***************************/
// Includes:
#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!
/************************************************** ***************************/
// Defines:
#define HSYNC (PIND & IO_PD6)
#define VSYNC (PIND & EINT2)
#define ODD_EVEN (PINB & EINT3)
#define IRon() (PORTC &= ~IO_PC6)
#define IRoff() (PORTC |= IO_PC6)
/************************************************** ***************************/
// Variables:
uint8_t bildspeicher[1024], *bildzeiger; // 32*32=1KB * 8Bit Bildspeicher
/************************************************** ***************************/
// Functions:
void bild_einlesen(void)
{
uint8_t pixel[32],*pixelzeiger;
uint8_t i, zeilen, step, lines, rows, h_step, h_delay;
zeilen=32; // Das fertige Bild soll 32 Zeilen haben
step=7; // sichtbares TV-Bild ist ca. 30-260=230/32 ergibt Zeilensprung=7
rows=0; // Anzahl der Spalten (32x32, rechengünstig,aber verzerrt)
do
{
lines=zeilen; // Anzahl der einzulesenden Zeilen
pixelzeiger=&pixel[0]; // Zeiger auf Start Pixelspeicher
cli();
// VSync abwarten (Seitenanfang)
while(VSYNC);
// 40 Zeilen Austastzeit & ein Stück oberen Bildrand überlesen
h_step=40; while (h_step) { while (HSYNC); while (!HSYNC); h_step--; }
// Der Lesecursor befindet sich jetzt oben links im TV-Bild
// ab hier werden in step-Sprüngen in allen Zeilen jeweils das Pixel eingelesen,
// das sich im zeitlichen h_delay-Abstand vom linken TV-Bildrand befinden
// (= eine TV-Bildspalte)
while (lines--)
{
// auf die nächste gültige Zeile warten
h_step=step; while (h_step) { while (HSYNC); while (!HSYNC); h_step--; }
// mit h_delay steuern wir nun den Pixel an
// Nach dem HSync fängt das Bild etwas verzögert an (Schwarzschulter),
// der Zeitpunkt des Auslesens des ADC verteilt sich bei 32 Punkten pro
// Zeile optimal auf den Zeileninhalt mit "h_delay=30+6*rows;". Bei der
// Überprüfung mit Testbild ist ein Offset von 20 aber besser geeignet.
h_delay=20+6*rows; while (h_delay--) {nop();};
*pixelzeiger=ADCH; // letzten ADC-Wert auslesen und wegwerfen
*pixelzeiger++=ADCH; // aktuellsten ADC-Werte speichern
}
sei();
pixelzeiger=&pixel[0];
bildzeiger=&bildspeicher[32*rows];
for (i=0; i<32; i++) *bildzeiger++ = *pixelzeiger++;
} while (++rows < zeilen);
}
/************************************************** ***************************/
// Main function - The program starts here:
int main(void)
{
initRP6Control(); // Always call this first! The Processor will not
// work correctly otherwise.
initLCD(); // Initialize the LC-Display (LCD)
// Always call this before using the LCD!
// Write some text messages to the LCD:
showScreenLCD("################", "################");
mSleep(1500);
showScreenLCD("<<RP6 Control>>", "<<LC - DISPLAY>>");
mSleep(2500);
showScreenLCD("Video Grabber 1 ", " Version 1.00 ");
// Clear the four Status LEDs:
setLEDs(0b0000);
// Initialize the M32 ICP pin (PD6) as input:
DDRD &= ~IO_PD6; // ==> HSync
PORTD |= IO_PD6; // Pullup on
// Initialize the M32 INT1 pin (PD3) as input:
DDRD &= ~EINT2; // ==> VSync
PORTD |= EINT2; // Pullup on
// Initialize the M32 INT2 pin (PB2) as input:
DDRB &= ~EINT3; // ==> Odd/Even
PORTB |= EINT3; // Pullup on
// Initialize the M32 TOSC1 pin (PC6) as output:
DDRC |= IO_PC6; // ==> IR
IRoff(); // IR LEDs off
uint16_t i, j; uint8_t video;
// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4
ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 4;
// setzte free running triggern
SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein interupt, Wandler einschalten, prescaler /4
ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (1<<ADPS1) | (0<<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);
while(true)
{
bild_einlesen();
for (i=0; i<32; i++)
{
for (j=0; j<32; j++)
{
video = bildspeicher[j+32*i];
if (video < 40) writeString_P(" ");
if ((video >= 40) && (video < 50)) writeString_P(":");
if ((video >= 50) && (video < 60)) writeString_P("+");
if ((video >= 60) && (video < 70)) writeString_P("X");
if (video >= 70) writeString_P("#");
// if (bildspeicher[j+32*i] > 55) writeString_P("*");
// else writeString_P(" ");
}
writeInteger(i,DEC);
writeString_P("\n\r");
}
mSleep(200);
}
return 0;
}
/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0 (initial release) 30.04.2010 by Dirk
*
* ************************************************** **************************
*/
/************************************************** ***************************/
Viel Erfolg!
Gruß Dirk
für die Experimentierplatine, die wir hier beschrieben haben:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=53424
... und die hier:
http://www.rn-wissen.de/index.php/RP6_Kamera_-_Mitmach-Projekt
... gebaut wurde, hier ein erstes Programm für die M32. Es funktioniert ab der Phase 3 des Aufbaus.
Ein 32x32 Pixel Bild wird auf dem Terminal ausgegeben. Das ursprüngliche Programm hat radbruch für die RP6Base geschrieben.
Was habe ich geändert:
1. Anpassung an die M32
2. Nutzung der Signale HSync und VSync des Sync-Separators auf der Exp.
/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - RP6 CONTROL M32 TESTS
* ************************************************** **************************
* Example: Grab video pictures and show them on the terminal
* Author(s): radbruch, modified for the M32: Dirk
* ************************************************** **************************
* Description:
*
* With this program (written by radbruch for the RP6Base) the picture of a
* CMOS camera (CONRAD 150001) can be displayed on the terminal.
* The camera is connected to this hardware project:
* http://www.rn-wissen.de/index.php/RP6_Kamera_-_Mitmach-Projekt
* The BAS video information (PG3) is connected to ADC4 (ADC plug, pin 3).
* The synchronization signals are connected as follows:
*
* Signal RP6 Name Port Function
* VSync EINT2 PD3 INT1
* HSync IO_PD6 PD6 ICP1
* Odd/Even EINT3 PB2 INT2
*
* ################################################## ##########################
* The Robot does NOT move in this example! You can simply put it on a table
* next to your PC and you should connect it to the PC via the USB Interface!
* ################################################## ##########################
* ************************************************** **************************
*/
/************************************************** ***************************/
// Includes:
#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!
/************************************************** ***************************/
// Defines:
#define HSYNC (PIND & IO_PD6)
#define VSYNC (PIND & EINT2)
#define ODD_EVEN (PINB & EINT3)
#define IRon() (PORTC &= ~IO_PC6)
#define IRoff() (PORTC |= IO_PC6)
/************************************************** ***************************/
// Variables:
uint8_t bildspeicher[1024], *bildzeiger; // 32*32=1KB * 8Bit Bildspeicher
/************************************************** ***************************/
// Functions:
void bild_einlesen(void)
{
uint8_t pixel[32],*pixelzeiger;
uint8_t i, zeilen, step, lines, rows, h_step, h_delay;
zeilen=32; // Das fertige Bild soll 32 Zeilen haben
step=7; // sichtbares TV-Bild ist ca. 30-260=230/32 ergibt Zeilensprung=7
rows=0; // Anzahl der Spalten (32x32, rechengünstig,aber verzerrt)
do
{
lines=zeilen; // Anzahl der einzulesenden Zeilen
pixelzeiger=&pixel[0]; // Zeiger auf Start Pixelspeicher
cli();
// VSync abwarten (Seitenanfang)
while(VSYNC);
// 40 Zeilen Austastzeit & ein Stück oberen Bildrand überlesen
h_step=40; while (h_step) { while (HSYNC); while (!HSYNC); h_step--; }
// Der Lesecursor befindet sich jetzt oben links im TV-Bild
// ab hier werden in step-Sprüngen in allen Zeilen jeweils das Pixel eingelesen,
// das sich im zeitlichen h_delay-Abstand vom linken TV-Bildrand befinden
// (= eine TV-Bildspalte)
while (lines--)
{
// auf die nächste gültige Zeile warten
h_step=step; while (h_step) { while (HSYNC); while (!HSYNC); h_step--; }
// mit h_delay steuern wir nun den Pixel an
// Nach dem HSync fängt das Bild etwas verzögert an (Schwarzschulter),
// der Zeitpunkt des Auslesens des ADC verteilt sich bei 32 Punkten pro
// Zeile optimal auf den Zeileninhalt mit "h_delay=30+6*rows;". Bei der
// Überprüfung mit Testbild ist ein Offset von 20 aber besser geeignet.
h_delay=20+6*rows; while (h_delay--) {nop();};
*pixelzeiger=ADCH; // letzten ADC-Wert auslesen und wegwerfen
*pixelzeiger++=ADCH; // aktuellsten ADC-Werte speichern
}
sei();
pixelzeiger=&pixel[0];
bildzeiger=&bildspeicher[32*rows];
for (i=0; i<32; i++) *bildzeiger++ = *pixelzeiger++;
} while (++rows < zeilen);
}
/************************************************** ***************************/
// Main function - The program starts here:
int main(void)
{
initRP6Control(); // Always call this first! The Processor will not
// work correctly otherwise.
initLCD(); // Initialize the LC-Display (LCD)
// Always call this before using the LCD!
// Write some text messages to the LCD:
showScreenLCD("################", "################");
mSleep(1500);
showScreenLCD("<<RP6 Control>>", "<<LC - DISPLAY>>");
mSleep(2500);
showScreenLCD("Video Grabber 1 ", " Version 1.00 ");
// Clear the four Status LEDs:
setLEDs(0b0000);
// Initialize the M32 ICP pin (PD6) as input:
DDRD &= ~IO_PD6; // ==> HSync
PORTD |= IO_PD6; // Pullup on
// Initialize the M32 INT1 pin (PD3) as input:
DDRD &= ~EINT2; // ==> VSync
PORTD |= EINT2; // Pullup on
// Initialize the M32 INT2 pin (PB2) as input:
DDRB &= ~EINT3; // ==> Odd/Even
PORTB |= EINT3; // Pullup on
// Initialize the M32 TOSC1 pin (PC6) as output:
DDRC |= IO_PC6; // ==> IR
IRoff(); // IR LEDs off
uint16_t i, j; uint8_t video;
// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4
ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 4;
// setzte free running triggern
SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein interupt, Wandler einschalten, prescaler /4
ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (1<<ADPS1) | (0<<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);
while(true)
{
bild_einlesen();
for (i=0; i<32; i++)
{
for (j=0; j<32; j++)
{
video = bildspeicher[j+32*i];
if (video < 40) writeString_P(" ");
if ((video >= 40) && (video < 50)) writeString_P(":");
if ((video >= 50) && (video < 60)) writeString_P("+");
if ((video >= 60) && (video < 70)) writeString_P("X");
if (video >= 70) writeString_P("#");
// if (bildspeicher[j+32*i] > 55) writeString_P("*");
// else writeString_P(" ");
}
writeInteger(i,DEC);
writeString_P("\n\r");
}
mSleep(200);
}
return 0;
}
/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0 (initial release) 30.04.2010 by Dirk
*
* ************************************************** **************************
*/
/************************************************** ***************************/
Viel Erfolg!
Gruß Dirk