Hallo Roboterfans
Beim Aufräumen/Ausräumen der Zimmer meiner inzwischen flügge gewordenen Kids habe ich eine sagenhafte Entdeckung gemacht:
http://worldbricks.com/de/lego-anlei...opers-Kit.html
Das ist das Lego-Steuermodul Micro-Scout aus dem Droid Developers Kit von Lego (für alle, die es wie ich nicht auf Anhieb erkennen ;). Es war der erste Bausatz der Mindstorms-Serie aus dem Jahre 1999 mit einem 4-Bit-Kontroller, Lichtsensor und eingebautem Motor. Neben den festen 7 Programmen hat das Modul auch die Möglichkeit, eigene Programme mit bis zu 15(!) Befehlen zu Speichern und auszuführen. Das wurde von Lego mit einem Hinweis auf die Website in der Aufbauanleitung auch erwähnt, wurde aber offiziell nie unterstützt. (Das Wissen habe ich mir alles angelesen, ich bin mit FT aufgewachsen ;)
Wie zu erwarten, das wollte ich natürlich genauer untersuchen. Der Baustein kann über seinen Lichtsensor Daten empfangen, Lego verwendet dafür den sogenanten Visual Light Link (VLL). Das ist ein einfaches serielles Protokoll mit 7 Datenbits und ca. 25 Befehlen. Dabei werden noch direkte Befehle und Scriptbefehle unterschieden. Ursprünglich sollten diese Daten über Barcodes eingelesen werden, aber das hat wohl nie richtig funktioniert. Ein paar Infos zum Code (auf diese Seite verweist auch die Lego-HP):
http://www.elecbrick.com/vll
Das Innenleben des Moduls:
http://www.abs-robotics.com/internals/microscout.htm
Und noch ein Dos-Programm zum VLL-Programmieren über LPT (mit Basic-Quellcode, einfachem Schaltplan und vielen Infos):
http://www.users.bigpond.com/grant.wells/homepage.htm
Mit diesen Informationen habe ich mir ein kleines Programm für meinen 8Mhz-ATMega32 (RP6) zusammengebastelt:
PHP-Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#define led_init DDRA |= 2
#define led_on PORTA |= 2
#define led_off PORTA &= ~2
unsigned int vll_code[35];
volatile uint16_t time;
void init(void)
{
cli();
TCCR0 = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0 |= (0 << COM00) | (0 << COM01); // ohne OCR-Pin
TCCR0 |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE0); // Interrupt ein
OCR0 = 200;
led_init;
led_off;
sei();
// MicroScout direct (immediate) VLL commands
vll_code[0]=0b1110000000; // Fwd
vll_code[1]=0b1100000001; // Rwd
vll_code[3]=0b0110001010; // Stop_Motors
vll_code[4]=0b0100000100; // Beep1
vll_code[5]=0b0010000101; // Beep2
vll_code[6]=0b0000000110; // Beep3
vll_code[7]=0b1110000111; // Beep4
vll_code[8]=0b1010001000; // Beep15
vll_code[33]=0b1000100001; // Run_Script
vll_code[34]=0b0110100010; // Delete_Script
// MicroScout VLL scripting commands
vll_code[16]=0b0100010000; // Fwd05
vll_code[17]=0b0010010001; // Fwd10
vll_code[18]=0b0000010010; // Fwd20
vll_code[19]=0b1110010011; // Fwd50
vll_code[20]=0b1010010100; // Rwd05
vll_code[21]=0b1000010101; // Rwd10
vll_code[22]=0b0110010110; // Rwd20
vll_code[23]=0b0100010111; // Rwd50
vll_code[24]=0b0000011000; // Beep1
vll_code[25]=0b1110011001; // Beep2
vll_code[26]=0b1100011010; // Beep3
vll_code[27]=0b1010011011; // Beep4
vll_code[28]=0b0110011100; // Beep5
vll_code[29]=0b0100011101; // WaitLight 4
vll_code[30]=0b0010011110; // SeekLight 3
vll_code[31]=0b0000011111; // Code 7
vll_code[32]=0b1010100000; // KeepAlive 5
}
void delay_10ms(uint16_t millisec10)
{
time=millisec10;
while(time);
}
void send_vll(uint8_t code)
{
/*
Each VLL command consists of:
init, start, 3 checksum bits, 7 data bits, and stop
checksum is 7-(data + data/4 + data/16)
Light beam structure:
"off" equates to BLACK on a barcode; or light OFF
"on" equates to WHITE on a barcode; or light ON
Bars/light pulses are in multiples of 10ms;
ie: "off 2" is off for 20ms
init on 40
start off 2
stop on 2 off 6 on 12
0 on 4 off 2
1 on 2 off 4
*/
uint8_t bitnr=9;
led_on; // init
delay_10ms(40);
led_off; // start
delay_10ms(2);
do{ // 3 Bit Checksumme und 7 Datenbits
if(vll_code[code] & (1<<bitnr))
{
led_on; // Bit=1
delay_10ms(2);
led_off;
delay_10ms(4);
}
else
{
led_on; // Bit=0
delay_10ms(4);
led_off;
delay_10ms(2);
}
}while(bitnr--);
led_on; // stop
delay_10ms(2);
led_off;
delay_10ms(6);
led_on;
delay_10ms(12);
led_off;
delay_10ms(40); // fertig
}
int main(void)
{
init();
delay_10ms(200);
send_vll(0); // direkt fwd
delay_10ms(50);
send_vll(1); // direkt rwd
delay_10ms(50);
send_vll(4); // direkt ton1
delay_10ms(100);
send_vll(17); // script fwd10
send_vll(21); // script rwd10
send_vll(18); // script fwd20
send_vll(22); // script rwd20
send_vll(24); // script ton1
delay_10ms(200);
send_vll(33); // run
delay_10ms(500);
send_vll(34); // delete
while(1);
return(0);
}
ISR(TIMER0_COMP_vect)
{
static uint16_t count;
if(count<50) count++; else { count=0; if(time) time--; }
}
Nach fast 10 Jahren habe ich noch alle Teile des Bausatzes gefunden, der Zusammenbau ist für ungeübte extrem nervig. Aber der R2D2 ist einfach genial, der Aufwand hat sich gelohnt:
Bild hier Bild hier
http://www.youtube.com/watch?v=VVQhpPnTY-8
http://www.youtube.com/watch?v=8HNKmT5NHtU
Möge die Macht mit euch sein...
mic
Lesezeichen