Cool Danke ich werds mal versuchen \:D/
Lg Alex
Druckbare Version
Cool Danke ich werds mal versuchen \:D/
Lg Alex
Hallo
Trotz Mitmachprojekt finden sich immer noch keine Anwendungen für diese einfache und kostengünstige Kameralösung. Weil ich die Kamera aber für mein RA2-Projekt verwenden möchte und mir gleichzeitig eher zufällig ein zur Kamera passendes sehr grobpixeliges Display in die Hände gefallen ist, habe ich eine Variante für einen 8MHz-ATMega8 geschrieben. Aufgrund der Erkenntnisse aus dem Mitmach-Thread verwende ich als Basis das einfache 24x16 Pixel-Programm. An das Display angepasst werden nur 12 der 16 möglichen x-Pixel angezeigt, die y-Auflösung wurde auf 10 Zeilen reduziert. Der ADC rennt zwar immer noch mit Prescaler /2 im Dauerlauf, aber da nun auf das Ende der AD-Wandlung gewartet wird, ist das Einlesen eines Bildes so entspannt, dass man dazu nicht mal mehr die Interrupts sperren muss:
Wie gehabt wird der ADC mit Prescaler /2, rechtsbündig und mit interner 2,56V-Referenz betrieben. Nach der Erkennung des Bildstarts werden 30 Zeilen überlesen, dann werden in einem Rutsch die 16 Pixel einer Zeile eingelesen. Nach jeweils einem Zeilensprung von 24 Zeilen werden dann schließlich die restlichen 9 Zeilen eingelesen. Das alles passiert innerhalb eines Halbbildes und mit freigegebenen Interrupts!Code:uint8_t bild[4][160];
uint8_t Bild_aufnehmen(void)
{
static uint8_t bildnummer=0;
uint8_t *bildzeiger;
uint8_t zeile, sync, c;
bildnummer = (bildnummer+1) & 3; // Bildnummer von 0 bis 3
zeile=30; // 30 Zeilen am Bildanfang überlesen
bildzeiger = &bild[bildnummer][0];
do{sync=0;while (ADCH > 20);while (ADCH < 30) sync++;}while (sync < 40);
for(c=0; c<10; c++) // 10 Zeilen einlesen
{
sync=15; // 15 Werte sollen am Stück gelesen werden
while(zeile--){while (ADCH > 20);while (ADCH < 30);} // auf Zeile warten
*bildzeiger++=ADCH; // erster Wert!
ADCSRA |= (1<<ADIF);
while(sync--) // Werte 2-16 einlesen
{
while(!(ADCSRA & (1<<ADIF)));
*bildzeiger++=ADCH;
ADCSRA |= (1<<ADIF);
}
zeile=24; // 24 Zeilen überlesen (30+ 24*10 = 270 Zeilen)
}
return(bildnummer);
}
Der Bildspeicher ist 16x10=160 Bytes groß, ich verwende davon vier Stück die ich nacheinander mit den Kameradaten fülle. Die Einlesefunktion verwendet die Bildspeicher als Ringspeicher. Die Auswertefunktion bildet das Mittel aus den einzelnen Bildspeichern und stellt die Pixel auf dem Display dar:
Bild hier
http://www.youtube.com/watch?v=ngim6DzIcGQ
Mein ungeputzter Arbeitscode:
GrußCode:// Kamera und acht Helligkeitsstufen mic 29.12.2010
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <inttypes.h>
#define colors 8 // Anzahl der Farbebenen (8 ist Maximum!)
// Variablen ------------------------------------------------------------------
volatile uint8_t ebene=0, col = 0; // Bildaufbau der LED-Matrix mit Timer2-ISR
uint8_t x, y, z, bildspeicher[colors][15];
uint8_t bild[4][160];
uint16_t counter=0;
uint8_t attrib=1;
prog_uint8_t font[5][17]={ // Zeichensatz für 3x5 7-Segmentanzeige 0 bis F und Blank (Speicherplatz im Flash)
{ 0b111, 0b001, 0b111, 0b111, 0b100, 0b111, 0b100, 0b111, 0b111, 0b111, 0b111, 0b100, 0b111, 0b001, 0b111, 0b111, 0b000},\
{ 0b101, 0b001, 0b001, 0b001, 0b101, 0b100, 0b100, 0b001, 0b101, 0b101, 0b101, 0b100, 0b100, 0b001, 0b100, 0b100, 0b000},\
{ 0b101, 0b001, 0b111, 0b111, 0b111, 0b111, 0b111, 0b001, 0b111, 0b111, 0b111, 0b111, 0b100, 0b111, 0b111, 0b111, 0b000},\
{ 0b101, 0b001, 0b100, 0b001, 0b001, 0b001, 0b101, 0b001, 0b101, 0b001, 0b101, 0b101, 0b100, 0b101, 0b100, 0b100, 0b000},\
{ 0b111, 0b001, 0b111, 0b111, 0b001, 0b111, 0b111, 0b001, 0b111, 0b001, 0b101, 0b111, 0b111, 0b111, 0b111, 0b100, 0b000} \
};
prog_uint8_t * fnt = (prog_uint8_t *) font; // Zeiger für den Zugriff auf den Zeichensatz (für plot_byte())
// Funktionen -----------------------------------------------------------------
void init(void);
void cls(void);
void plot_byte(uint8_t x, uint8_t y, uint8_t ziffer); // Ziffer von 0 bis F
void write_byte(uint8_t a, uint8_t z); // z=0 ist oben, z=1 ist unten
uint8_t Bild_aufnehmen(void);
void Bild_darstellen(uint8_t level);
void Bild_Info(void);
// Einen Bildpunkt an x, y setzen. Werte für c: 0 ist aus, 1 ist dunkel, 4 ist hell
void set(uint8_t x, uint8_t y, uint8_t c);
// Potiwert P2 an ADC6 einlesen als Byte! Kanal 7 ist die Cam
uint8_t readADC6(void);
// WatchDog beim Initialisieren ausschalten
// https://www.roboternetz.de/phpBB2/vi...=531597#531597
void kill_WD(void) __attribute__((naked)) __attribute__((section(".init3")));
void kill_WD(void) { MCUSR = 0; wdt_disable(); }
// Hauptschleife --------------------------------------------------------------
int main(void)
{
init();
for(x=0; x<12; x++)
for(y=0; y<10; y++)
set(x, y, (colors-((x+y)/3)%colors)); // Helligkeitsstufen anzeigen
_delay_ms(2000);
cls();
while(Bild_aufnehmen()); // Bildspeicher füllen
// Bild_Info(); // min - max - mitte - durchschnitt
while(1)
{
if(!col)
{
z=readADC6();
if(attrib)
{
for(y=5; y<10; y++)
for(x=0; x<12; x++) set(x, y, z/29); // 255/29 ergibt 8,8
}
else
{
while(Bild_aufnehmen());
Bild_darstellen(z);
}
if(z==0) if(attrib) { attrib=0; Bild_Info(); } // Bit0: Zeile
if(z==255) if(!attrib) { attrib=1;};
if(attrib) write_byte(z, attrib);
}
counter++;
}
return (0);
}
// Definitionen der Funktionen ------------------------------------------------
uint8_t Bild_aufnehmen(void)
{
static uint8_t bildnummer=0;
uint8_t *bildzeiger;
uint8_t zeile, sync, c;
bildnummer = (bildnummer+1) & 3; // Bildnummer von 0 bis 3
zeile=30; // 30 Zeilen am Bildanfang überlesen
bildzeiger = &bild[bildnummer][0];
do{sync=0;while (ADCH > 20);while (ADCH < 30) sync++;}while (sync < 40);
for(c=0; c<10; c++) // 10 Zeilen einlesen
{
sync=15; // 15 Werte sollen am Stück gelesen werden
while(zeile--){while (ADCH > 20);while (ADCH < 30);} // auf Zeile warten
*bildzeiger++=ADCH; // erster Wert!
ADCSRA |= (1<<ADIF);
while(sync--) // Werte 2-16 einlesen
{
while(!(ADCSRA & (1<<ADIF)));
*bildzeiger++=ADCH;
ADCSRA |= (1<<ADIF);
}
zeile=24; // 24 Zeilen überlesen (30+ 24*10 = 270 Zeilen)
}
return(bildnummer);
}
void Bild_darstellen(uint8_t level)
{
uint8_t x, y, temp;
uint8_t bild_temp[160];
uint16_t temp16;
for(x=0; x<160; x++)
{
temp16 = bild[0][x] + bild[1][x] + bild[2][x] + bild[3][x];
bild_temp[x] = temp = temp16/4;
}
if(level)
{
for(y=0; y<10; y++)
for(x=0; x<12; x++)
{
temp= bild_temp[16*y+x+2];
if(temp<level) set(x, 9-y, colors); else set(x, 9-y, 0);
}
}
else
for(y=0; y<10; y++)
for(x=0; x<12; x++)
{
temp= bild_temp[16*y+x+2];
set(x, 9-y, (temp-20)/8);
}
}
void Bild_Info(void)
{
uint8_t min=225, max=0, temp;
uint16_t durchschnitt=0, temp16;
for(x=0; x<160; x++)
{
temp16 = bild[0][x] + bild[1][x] + bild[2][x] + bild[3][x];
temp = temp16/4;
if(temp > max) max=temp;
else if(temp>20) if(temp < min) min=temp;
durchschnitt += temp;
}
durchschnitt /= 160;
cls();
write_byte(min, 1);
_delay_ms(1000);
cls();
write_byte(max, 0);
_delay_ms(1000);
cls();
write_byte((min+max)/2, 1);
_delay_ms(1000);
cls();
write_byte(durchschnitt, 0);
_delay_ms(1000);
}
void cls(void)
{
uint8_t x, y;
for(y=0; y<colors; y++)
for(x=0; x<15; x++)bildspeicher[y][x] = 0;
}
void set(uint8_t x, uint8_t y, uint8_t c)
{
uint8_t ebene;
y = 9-y; // Koordinatennullpunkt unten links
if(y < 8) // y 9 bis 2
for(ebene=0; ebene<colors; ebene++)
if(c>ebene) bildspeicher[ebene][x] |= (1 << y);
else bildspeicher[ebene][x] &= ~(1 << y);
else // y 1 und 0
for(ebene=0; ebene<colors; ebene++)
if(c>ebene) bildspeicher[ebene][12+(x>>2)] |= (1<<((x%4)*2+(y&1)));
else bildspeicher[ebene][12+(x>>2)] &= ~(1<<((x%4)*2+(y&1)));
}
void plot_byte(uint8_t x, uint8_t y, uint8_t ziffer)
{
uint8_t c, f1=colors, f2=0, fontbyte=0;
for(c=0; c<5; c++)
{
fontbyte = pgm_read_byte_near(fnt+17*c+ziffer); // Zeichensatz ist im Flash
if(fontbyte & 4) set(x , y-c, f1); else set(x , y-c, f2);
if(fontbyte & 2) set(x+1, y-c, f1); else set(x+1, y-c, f2);
if(fontbyte & 1) set(x+2, y-c, f1); else set(x+2, y-c, f2);
if(fontbyte & 0) set(x+3, y-c, f1); else set(x+3, y-c, f2);
}
}
void write_byte(uint8_t a, uint8_t z) // z=0 ist oben, z=1 ist unten
{
uint8_t c, temp=1;
c=0;
while(a >= 100) {a-=100; c++; }
if(c) plot_byte(0, 9-5*z, c); else { plot_byte(0, 9-5*z, 16); temp=0; }
c=0;
while(a >= 10) {a-=10; c++; }
if(c || temp) plot_byte(4, 9-5*z, c); else plot_byte(4, 9-5*z, 16);
c=0;
while(a >= 1) {a-=1; c++; }
plot_byte(8, 9-5*z, c);
}
uint8_t readADC6(void)
{
uint8_t adc6, dummy;
ADCSRA = (0 << ADEN);
dummy=ADCH;
// A/D Conversion (aus der asuro-Lib)
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); // clk/32
ADMUX = (1<<ADLAR) | (1 << REFS0) | (6);// AVCC reference with external capacitor
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
adc6=ADCH;
ADCSRA |= (1 << ADIF); // clear ADCIF
ADCSRA = (0 << ADEN);
dummy=ADCH;
// rechtsbündig, interne 2,56V-Referenz (0:1 5V, 1:1 2,56V) , Kanal 7
ADMUX = (1<<ADLAR) | (1<<REFS1) | (1<<REFS0) | 7;
// enable, start conversion, freerunning, prescaler /2
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
return(adc6);
}
void init(void)
{
cli();
DDRB = 0xff;
DDRC = 0x0f;
DDRD = 0xf0;
TCCR2 = (1<<CS21) | (0<<CS20); // 8-bit Timer mit 1/8 Vorteiler
TCCR2 |= (1<<WGM21) | (1<<WGM20); // Fast PWM
TCCR2 |= (0<<COM21) | (0<<COM20); // no OC2-Pin
OCR2 = 100; // 0=dunkel, 255=hell
TIFR = (1<<OCF2) | (1<<TOV2); // Clear old flags
TIMSK |= (1<<TOIE2) | (1<<OCIE2); // overflow and compare interrupt
// rechtsbündig, interne 2,56V-Referenz (0:1 5V, 1:1 2,56V) , Kanal 7
ADMUX = (1<<ADLAR) | (1<<REFS1) | (1<<REFS0) | 7;
// enable, start conversion, freerunning, prescaler /2
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
sei(); // Interrupts erlauben
}
// ISR ------------------------------------------------------------------------
SIGNAL (SIG_OUTPUT_COMPARE2)
{
OCR2 = (1<<ebene)-1; // hihi
PORTC &= ~0x0f; // Die Pins der Displaymatrix werden wieder auf Low gesetzt
PORTD &= ~0xf0;
PORTB &= ~0x03;
}
SIGNAL (SIG_OVERFLOW2)
{
uint8_t ledval, portb;
// Spalten
if(col) PORTB |= (1<<4); /* Danach Einsen hinterherschicken (PB4 = 1) */
else PORTB &= ~(1<<4); /* Bei der ersten Spalte eine 0 ausgeben (PB4 = 0) */
PORTB |= (1 << 3); /* PB3 = 1 (cl) */
PORTB &= ~(1 << 3); /* PB3 = 0 (!cl) */
PORTB |= (1 << 2); /* PB2 = 1 (str) */
PORTB &= ~(1 << 2); /* PB2 = 0 (!str) */
// Zeilen
ledval = bildspeicher[ebene][12+(col>>2)]; // y 1 und 0
portb = (ledval >> (col%4)*2) & 0x03;
ledval = bildspeicher[ebene][col]; // y 9 bis 2
PORTC |= ledval & 0x0f;
PORTD |= ledval & 0xf0;
PORTB |= portb;
col++;
if(col>11)
{
col=0;
ebene++;
if(ebene == colors) ebene=0;
}
}
mic
Hi mic,
das ist ja mal wieder genial!
Ich hole mir dieses PingPong erst mal vom großen C.
Ich wußte gar nicht, dass da ein M8 drin sitzt...
Gruß Dirk
Gibt es einen aktuelleren Quellcode?
Ich möchte dieses Projekt für mein nächstes verwenden.
Das ist der aktuellste Quellcode. Der ADC wird zwar auch hier gnadenlos übertaktet, aber beim Einlesen einer Bildzeile wird nicht mehr stur eingelesen sondern auf den Status des ADC geachtet. Es ist die aktuell schnellste Lösung, alle Pixel werden innerhalb eines Halbbildes eingelesen. Basis ist diese Version:
https://www.roboternetz.de/phpBB2/ze...=500285#500285
Bedeutend höhere Auflösungen sind auch möglich, allerdings wird so pro Halbbild nur ein Pixel pro Zeile eingelesen:
https://www.roboternetz.de/community...l=1#post458253
https://www.roboternetz.de/community...l=1#post457599
Was soll die Kamera bei deinem Projekt erkennen?
Die Kamera soll drei IR Laser Orten um die Landung eines Quadrocopters autonom erfolgen zu lassen. Wenn ich fertig bin werde ich mal ein Video posten (wahrcheinlich erst in den Sommerferien).
Danke für den aktuellen Quellcode. Mit was hast du den denn Compiliert?
LG Matthias
Hallo,
ist es mit der von dir beschriebenen Methode denn auch möglich Farben zuverlässig zu unterscheiden?
Wie kalibrierst du die Kamera? Machst du das manuell, indem du werte im Programm änderst oder geht das automatisch?
Gruß
Hallo
Mit Farberkennung habe ich noch keine Versuche unternommen. Eventuell kann man mit Filterscheiben arbeiten?
Da die Kamera einen automatischen Weisabgleich macht, braucht man eigentlich nichts kalibrieren. Zur Zeit spiele ich mal wieder mit einem Linienfolger, diesmal aber mit dem asuro und in Bascom:
http://www.youtube.com/watch?v=usS3a3Ud_vo
Es klappt zwar noch nicht so gut, aber es ist auch eher als Einstieg in eine echte Bildverarbeitung gedacht.
Gruß
mic
Hallo
Gleich vorweg die Warnung: Dieser Beitrag ist nur für die wirklich harten Kamera-Fans geeignet.
Zur Zeit versuche ich die Kamera auch mit Bascom in den Griff zu bekommen. Das klappt auch ganz gut:
http://www.youtube.com/watch?v=sr-7kZ68qDo
Basis ist der eigentlich schon getestete Code für den RP6. Wie üblich hangelt sich der Code an den Syncs zum Bildanfang und dann zur Zielzeile, in meinem Programm zur 50. Zeile. Dann wird laufend geprüft, ob die Helligkeit größer einer bestimmten Schwelle ist. Die Anzahl der Prüfungen wird mitgezählt und das Ergebnis ist dann der Wert für die Position der Kante der Linie:
Wichtig ist nun diese kleine und eigentlich unscheinbare Funktion:Code:Do ' Auf Bildanfang warten
B = 0
While Adch > 30 ' solange kein sync
Wend
While Adch < 50 ' solange sync
Incr B ' syncs zählen
Wend
Loop Until B > 40 ' mehr als 40 bedeutet Bildanfang
B = 50 ' die zu lesende Zeile
While B > 0 ' Zeilen zählen
While Adch > 30 ' solange kein sync
Wend
While Adch < 50 ' solange sync
Wend
Decr B
Wend ' Zeile gefunden
B = 0
While Adch > 65 ' Hell/Dunkel-Schwelle
Incr B ' warten und zählen bis Schwellwert erreicht wird
Wend
Linie = B ' Rückgabewert kopieren
Was mache ich da? Der Pegel des Videosignals in ADCH ist beim Sync deutlich unter 30, alles was größer als 50 ist, wird als Bildinformation interpretiert. Alle Werte über der Schwelle von 65 werden als "Hell" gewertet, ein Wert unter der Schwelle bedeutet die Kante der Linie ist gefunden.Code:B = 0
While Adch > 65 ' Hell/Dunkel-Schwelle
Incr B ' warten und zählen bis Schwellwert erreicht wird
Wend
Eigentlich hätte ich nun erwartet, dass bei einem 8MHz-RISC-Kontroller der Zähler sofort in die Höhe schießt, denn die Ausführung der kleinen Scheife dauert nur ein paar Takte. Dem ist aber nicht so! Wenn ich mit Adch > 50, quasi alles was nicht Syncpegel ist, als Bildbereich gelten lassen, komme ich auf Zählerstände von maximal 27. Das ist auch das, was man im Video oben sieht und hört: Wenn der Linienwert >26 ist wird keine Linie erkannt, weil sie außerhalb des Sichtbereichs der Kamera ist. Aber warum ist der Wert so unerwartet niedrig? Ich vermute, Bascom wartet intern bis der ADC mit der Wandlung fertig ist bevor der Wert von ADCH gelesen werden kann. Das würde also 26 echte Positionen bedeuten, was allerdings zu den in C ermittelten maximalen 16 nicht ganz passt. Hier muss man noch etwas weiter forschen, aber ich schweife auch ab....
Wirklich spannend ist nun folgendes: Wenn man die Schwelle nicht als absoluten Wert angibt sondern als Variable, dann verändern sich die gemessenen Werte:
Dim Schwelle As Byte
...
Adch > Schwelle
...
So komme ich nur noch auf Maximalwerte von ca. 23! Irgendwas an der Art der Zuweisung scheint so länger zu dauern als in der Variante mit Konstanten. Sehr seltsam. Was Basom da übersetzt sollte man mal disassemblieren.
Gruß
mic
Hallo
Da ich mal wieder an meiner ewigen Kamerabaustelle arbeite, kann ich nun quasi die Version 2.0 der Minimalkamera als Beta vorstellen.
Bisher hatten wir das Problem, dass wir zwar die Syncs gefunden haben, aber die Flanken wurden nicht richtig erkannt. Deshalb "zitterte" der Zeilenanfang beim Einlesen der Bilddaten. Das sieht man deutlich bei den HiRes-Bildern:
Bild hier Bild hier Bild hier
(Bilder aus https://www.roboternetz.de/community...l=1#post458253)
Nun bin ich schon vor einiger Zeit im Datenblatt der AVRs über diesen Satz in der Beschreibung des analogen Komparators (Analog Comparator) gestolpert:
Frei übersetzt: Der Status der Komparators wird innerhalb von 1 bis 2 Taktzyklen (!) im ACO-Bit dargestellt.Zitat:
The output of the Analog Comparator is synchronized and then directly connected to
ACO. The synchronization introduces a delay of 1 - 2 clock cycles.
Blöderweise sind aber die Pins des Komparators bei meinen Fertigrobotern schon belegt, deshalb habe ich diesen Ansatz bisher nicht weiterverfolgt. Eher zufällig ist mir nun aufgefallen, dass mein asuro-probot genau diese Pins nicht verwendet, wenn ich die Sensorplatine nicht einstecke. Dadurch kann ich nun AIN0 und AIN1 nutzen. Als zusätzliche Hardware erzeuge ich mit einem 10k-Poti eine einstellbare Spannung an AN0 als Schwelle für den Sync-Pegel, die Erweiterung der Software beschränkt sich auf das Umschalten zwischen ADC- und AC-Betrieb und der geänderten Sync-Erkennung:
Da der ADC wie gehabt im Dauerlauf gestartet wurde, schaltet die Funktion zuerst den ADC aus und den AC ein. Dann hangelt sich die Funktion durch die Syncs über den Bildanfang bis zu der Zeile, die sich vor der gesuchten Zeile befindet. Wenn am Ende dieser Zeile der Sync erkannt wird, schaltet die Funktion von AC auf ADC zurück und startet die erste Wandlung des ADC noch während des Syncs. So wird der Zeilenanfang mit einer bisher noch nicht gekannten Genauigkeit getroffen. Dieses einfache DemoCode:Sub Readline(byval Zeile As Word)
Local Znr As Word
' AC einschalten Vergleich zwischen AIN0 (PD6) und ADC-Kanal 4 (PC4)
Reset Adcsr.aden ' ADC dissable
Reset Acsr.acd 'enable analog comparator ACSR bit 7 = 0
Portd.4 = Acsr.aco ' Status zeigen: Warten auf Bildstart
Do ' Auf Bildanfang warten
Znr = 0
While Acsr.aco = 0 ' solange kein sync (PC4 > PD6)
Wend
While Acsr.aco = 1 ' PC4 < PD6 = Sync
Incr Znr ' syncs zählen
Wend
Loop Until Znr > 60 ' mehr als 60 (mit AC!) bedeutet Bildanfang
Znr = Zeile ' die zu lesende Zeile
While Znr > 1 ' Zeilen zählen
While Acsr.aco = 0 ' solange kein sync
Wend
While Acsr.aco = 1 ' solange sync
Wend
Decr Znr ' eine Zeile vor dem Ziel...
Wend
While Acsr.aco = 0 ' solange kein sync
Wend
' ADC einschalten
Set Adcsr.aden ' ADC Enable
Set Adcsr.adsc ' ADC Start Conversion
Portd.4 = Acsr.aco ' Status zeigen: Zeile gefunden
Set Adcsr.adif ' ADIF-Bit rücksetzen !!! Nur schreibend zugreifen !!!
While Adcsr.adif = 0 ' warten bis ADC fertig mit Wandeln
Wend
Znr = Adch ' erste Lesung ist noch Sync
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(01) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(02) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(03) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(04) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(05) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(06) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(07) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(08) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(09) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(10) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(11) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(12) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(13) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(14) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(15) = Adch
Set Adcsr.adif
While Adcsr.adif = 0
Wend
Linienspeicher(16) = Adch
Set Adcsr.adif
End Sub
erzeugt diese Ausgabe:Code:While X = X
Readline 50
For X = 1 To 16
Print Linienspeicher(x) ; " ";
Next X
Waitms 300
Wend
Werte<70 sind der Strich, <ca. 40 ist der Sync am Ende der Zeile. Es sind also ca. 13 Werte pro Zeile die gelesen werden.Code:Bascom-Spielereien mit der Kamera
96 102 103 103 103 103 99 79 57 99 99 96 96 46 6 35
96 102 103 103 103 102 99 56 57 99 97 96 96 15 3 35
96 103 103 103 103 102 99 56 60 99 97 96 96 9 3 35
96 102 103 103 103 102 99 71 57 99 99 96 96 39 6 35
96 102 103 103 103 102 99 57 57 97 97 96 96 39 6 35
96 102 103 103 102 102 99 57 57 97 97 96 96 19 3 35
96 102 103 103 103 102 99 57 56 99 97 96 96 39 6 35
96 102 103 103 103 103 99 63 57 99 99 96 96 39 6 35
96 102 103 103 103 102 99 56 56 97 97 96 96 39 6 35
96 102 103 103 103 102 99 76 56 99 99 96 96 41 6 35
97 103 103 103 103 102 99 60 60 99 97 96 96 15 3 35
88 102 102 103 102 102 99 79 56 99 99 96 96 54 6 35
97 103 103 103 103 102 99 56 62 99 97 96 96 9 3 35
87 103 103 103 103 102 99 60 60 99 97 96 96 30 4 35
96 102 103 103 103 103 99 76 56 99 99 96 96 44 6 35
86 102 103 103 103 102 99 70 57 99 99 96 96 39 6 35
96 102 103 103 103 102 99 78 56 99 99 96 96 44 6 35
96 103 103 103 103 102 99 57 57 99 97 96 96 19 3 35
96 102 103 103 103 102 99 56 57 99 97 96 96 14 3 35
Gruß
mic