Search the Community
Showing results for tags 'vll'.
-
Dear All – just another “vintage LEGO” post … Summary Letting the CodePilot directly look into the light of one of the output LEDs of LEGO Interface A (#9750) makes it happy: A QBasic program for uploading even more complex VLL scripts to this PBrick using only original LEGO hardware (from the 1980’s ) 2 resistors, 2 diodes, 1 red LED, and ½ CD4013 ;) for a total of less than $5: A “serial interface” for directly uploading programs to the CodePilot or the MicroScout PBricks via their VLL optical port using any (ancient to ultra-modern) computer with a serial (and/or USB port). A QBasic program for comfortably interacting with both PBricks via a serial/USB or parallel port, or the #9771 LEGO ISA interface card. It runs on DOS 3.3 machines with real RS232 ports all the way up to Win11/64 bit machines within the DOSBox-X emulator via USB-to-serial adapters without any change to the program, just pressing keyboard buttons required … (See below for details) Video: QBasic program for uploading and running the “Garbage Truck program” (as provided in the Technic CodePilot manual of the Technic set #8479 to the CodePilot PBrick) using an Interface A (#9750) and an IBM XT, controlling the MicroScout, and using a very simple serial VLL interface based on one CD4013 D-flip flop as described further below in this post. Two serial “interfaces”: Today’s modern USB-to-TTL adapter + ½ 74LS74 (top) and 1980’s CMOS (CD4013, bottom) chippies, wiretapping the RS232 lines DTR, GND, TX, no power supply required. Preliminary bread board versions running on RS232 power delivered by the DTR line. Left: “TTL” with 78L05 and 74LS74, Zener diode protection at the D input, diodes for wrong polarity protection; right: “CMOS” with CD4013, no voltage regulation required as the 4000 (B) series runs with +3 … +18 V. (yeah, there always is …) Introduction Decades ago, the LEGO VLL (visible light link) protocol was “deciphered”. In 2000, I heard about it when Doug Eaton posted his findings on programming the MicroScout on lugnet.com (https://news.lugnet.com/robotics/?n=9932; the website mentioned in this post doesn’t work anymore, Doug’s content is “now” here. In 2004, I copied the VLL barcode sheets Doug prepared as postscript file and kept them in a safe place). When I got my Robotics Discovery Set featuring the SCOUT in 2001, the SCOUT software development kit (SDK) became available through LEGO as well. The documentation for the SDK has a list of VLL codes available for controlling/programming the MicroScout PBrick and programming the CodePilot PBrick. The LEGO Mindstorms SDK2.5 (still available here) has a full documentation of the VLL codes, the VLL serial protocol (timing), and much more. There are many ways of generating the (serial) optical VLL code bit stream, which per VLL instruction is comprised of a start bit, 3 checksum bits, 7 data bits, and a stop bit: Any of the RCX PBricks (1.0, 1.5, 2.0) flashed with the LEGO firmware that came with the RCX2.0 (still available here, with an even newer version: https://pbrick.info/index.html-p=74.html), or the SCOUT, or all Spybotics PBricks, natively speak VLL. It also works with Arduinos, ESPs, Feathers, and so on and so forth; there are myriads of links on how to create and send VLL commands to the corresponding PBricks. However, I could not find any references regarding – guess what – running QBasic (on any DOS machine) and more importantly – using the serial port as “LED VLL driver”. Why the serial port? Because it is fun to do so, because it is serial as well ^^. The Recommended Standard 232 (or RS232) was introduced in 1960, and even today lives a very happy life. Folks this is more than 6 decades - as old as I am. Serial also means that I can use my Win11 laptop to “code” and test QBasic programs, before copying them to my IBM XT; all I need is a USB-to-RS232 converter on my Windows machine. Generating VLL bit streams via a true parallel port is even simpler than via a serial port: Only one of the 8(+) parallel lines available needs to be turned on and off – however, parallel ports are gone. The IBM XT and virtually all the other 8-bit wonders feature such a port of course and they can generate VLL bit streams (plus driving an LED) literally out of the box; the additional hardware required is a resistor and an LED. If you want to have it more fancy, just throw in a DB-25 pin connector of which 2 pins are populated; GND and one of the 8 data lines. And yes, there is the beloved #9750 Interface A with its 6 outputs. The LEDs indicating the port status are perfectly suited for emitting VLL codes. All one needs is either a LEGO #9771 ISA card and IBM (compatible) computer or any of the 8-bit wonders having a compatible interface of which I made some (link to Evan Koblentz website). Here is the CodePilot PBrick "resting" on Interface A. Its sensor looks directy into the #output 5 indicator LED used for programming. The 4.5V light brick is also hooked-up to port #5 showing the port status: It needs to be on when VLL programming begins, as the VLL start bit ist "light off"). The light bricks itself has a little light blub inside - the filament is too slow to generate sharp enough 20 ms flashes. An LED with 220 Ohm resistor works also perfectly well for VLL programming using Interface A: A close-up of the sensor position: This is the little bracket holding the CodePilot PBrick in place (it just slides in) - the odd angle of the surface of Interface A makes it a bit slippery: On modern machines, USB-to-TTL adapters work of course as well (see end of this post) but they are not “compatible” with serial ports of the pre-1990 era as they were not invented yet … and thus violate my guidelines for developing LEGO control programs. These guidelines are copied with small changes from Evan’s (@evank) challenge rules posted, see link above: Program must run on computer systems available before 1990 Computer must run operating systems and software published before 1990 Only contemporary and simple hardware additions are allowed to interact with the LEGO device BASIC is the programming language. Yes, BASIC. No C, C++, Python, Java, ALGOL, COBOL, PASCAL (although …), FORTRAN (although …) – no, it is BASIC. Experimental, results and discussion My test rig is an IBM XT from 1985 (two 5 ¼” floppy drives, each 360k, no hard drive, serial, parallel, and 9771 LEGO interface, CGA card) running DOS 3.3 as operating system, and QBasic1.1 as programming software. Yes, using the IBM’s parallel port would have been also possible, but then I can’t use any modern computer, e.g., my Win11 laptop (running DOSBox-X as DOS emulator) for programming and testing, as the parallel ports are gone since long and USB has taken over. With a USB-to-RS232 adapter, I am essentially back in the 1980’s (and even way earlier ...). The LEGO VLL devices I like to program are the MicroScout and the CodePilot PBricks. Programming means writing and storing “VLL scripts” on a computer and then uploading them to the PBricks. This is the same approach I am using for my LEGO Control Center II (#8485), or LEGO Interfaces A/B (#9750, #9751). Using plain vanilla QBasic/DOS imposes another challenge: The minimum time delay directly available in this environment is bound to the 55.6 ms (1/18 s) timer clock, which is simply too long for VLL bit stream generation. VLL is composed of 20 ms time sliced signals: A VLL logic “1” is represented by 20 ms light and 40 ms dark, a “0” by 40 ms light and 20 ms dark. The start bit is 20 ms 0 = dark, preceded by at least 400 ms 1 = light, the stop bit is 20 ms light, 60 ms dark and 120 ms light; this is all well documented, see refs. above. There are multiple ways generating shorter time “delays” than 55.6 ms in DOS/QBasic, e.g., zapping the programmable interrupt timer, using machine code, and so on and so forth – I’d like to keep it stupidly simple: I am running a loop 10000 times and the determine the time it required to finish. Which of course leads to rather different execution times on an IBM XT vs a Dell Precision: The XT executes about 120 “empty” FOR:NEXT loops in one ms as compared to several hundreds of thousands of loops when simulating a Pentium system in DOSBox-X. There is an easy way out: Calibration. What I simply do is: DIM t, dt as DOUBLE: DIM i as LONG t = TIMER ‘store seconds since computer was turned on FOR i = 1 to 10000: NEXT i dt = TIMER – t ‘seconds elapsed after 10000 loops dt/10 = time in ms for one loop – now I can calculate the number of loops required for a 20, 40, 60 etc. ms delay. Works on the IBM and on the Dell/DOSBox-X emulating a 386 system quite precisely. When emulating a Pentium – well that simply leads to division by zero errors and long integer overflows. But I simply don’t care about these systems. I am a Boomer. I usually let DOSBox-X emulate a 286 system running DOS3.3. “Synthesizing” the VLL bit stream and sending it to the RS232 serial port (or USB-to-Serial adapter, same thing) is straight forward: I am setting up a COM port with 9600 baud, 6 data bits, no parity and 1 stop bit. 9600 baud is the maximum an XT can handle without zapping its UART, which is not necessary. The 6 data bits are just for being compatible with Interface A; I made an Arduino based serial to parallel interface, so the present QBasic program does handle that as well, when connected as "serial". To make this as simple as possible, I am not using any RS232-to-TTL signal conversion, e.g. with a MAX232; that would require an external power supply. I am running everything entirely on the RS232 signal side: Here valid voltage levels are +/-3V to +/-15V. All USB-to-RS232 adapters I have, work with close to +/-9V signal levels, the IBM Asynchronous Communications Adapter (=serial card ) works with +/-12V. I am using the DTR (pin 4) and GND (5) line as power source as there is only one LED I need to drive. DTR remains high when hardware handshaking is disabled. When “idling”, the RS232 TX serial line is low; note that this is inverted on the TTL/UART side of things. A (idle=low-) high-low RS232 level pulse is generated by sending &H20, which is binary 00100000, but only 6 bits are transmitted. Since the least significant bit is sent first, this method generates one low-high-low pulse: The serial protocol on the RS232 side is start bit = high, 5x 0 = high data bits, the 6th low bit and then the (low) stop bit (and the other way around on the TTL/UART side). At 9600 baud, the time between the TX line going high and low again is 1/9600 *(1+5) = 0.625 ms, which is much shorter than the minimum duration time for VLL pulses (20 ms). Each of these &H20 transmissions represents a trigger signal for the additional “hardware” required, which is a ½ CD4013 dual D-flip flop/latch (there also two protection diodes, two resistors and one LED). One of the two D-latches in the 4013 CMOS chip is set-up as toggle flip flop (or divider-by-two) by connecting its Q# output to its D input; each time a positive slope on the clock Clk input arrives (i.e. from the TX serial line), it flips its Q and Q# outputs. The Q# output of the toggle flip flop drives a red LED via a 1kOhm resistor which generates enough light for the CodePilot/MicroScout VLL sensors. The max. current flowing in this setup is less than 10 mA through the LED; the 4013 does not burn any noticeable power. Such a current source/sink is safely available on most serial ports and USB-to-serial adapters and for sure on true serial ports. I believe the IBM card can power street lights … ok, maybe not, but its armored with SN75150’s, sourcing sustained >20 mA on RS232 high and sinking 10 mA on RS232 low level (which I do not use). This is a schematic of the – uhm – “serial VLL interface” using the CD4013 (the 10uF capacitor is a pure luxury item - I thought is would look fancier, but did not use it): This is the timing. All what happens is dividing the input clock (positive slope) by two, however the duty cycle of the clock changes widely (as per VLL protocol) – this is the main reason I could not find a way to directly using any Baud rate/serial protocol combination: QBasic program See UI screen shots above; the program has a simple user interface with the arrow keys “navigating” the codes, RETURN fires the VLL code through the serial port and the LED does happy blinking. “U” calls a “user program” for upload. “V” toggles between the code table for MicroScout and CodePilot. The CodePilot sounds OK, NotOK, or the actual sound (truck, valve, robot …) or tone when it received a corresponding VLL code, thus there is a 1s delay between consecutively sent VLL codes, otherwise the CodePilot misses every second command. The MicroScout acknowledges a received VLL programming code with a short beep, thus the delay is not necessary. It also has direct commands for immediate execution, which the CodePilot has not. A program sequence of: a = &H3F8 ‘serial port 1 address o = &H20 OUT a, o DEL20 ‘subroutine: calibrated number of FOR/NEXT loops for 20 ms OUT a, o generates a “calibrated” LED off-on cycle of about 20 ms; the LED is on when “idling”. And with that, the VLL codes can be assembled. The 3 checksum bits (cf. https://www.elecbrick.com/vll/) are calculated each time rather than being hard coded, as I like to interpret the VLL codes as 7-bit decimal numbers for reference. Many sources for VLL code generation have each instruction in the form of a 10 bit hard-coded bit stream (as on the code sheet provided with set #8479); I prefer to “synthesize” things on the fly. The checksum encoding is also available on Doug’s website and consists of some bit shifting. Programs are stored as list of VLL commands in “user programs” A, B, C, … for convenience, I just defined a rather long list of integer constants, e.g. CONST CP.MOTOR.FWD 0, to make programming a little more reading friendly. As others have reported, the CodePilot programming language is essentially comprised of ACTION [SPEED, DURATION] "lines of code", where the latter two arguments are optional. SPEED can be 20, 40, 60 or TACHO, see below. DURATION is .1 to 99. TOUCH IN/OUT halts the program but does not stop an ACTION, this is what STOP (output) or MUTE SOUND (sound) does. There are more nuances but that is fun to find out. The VLL LED needs to be “on” before any VLL code submission; should it be off after program start, pressing “T” turns it on. It does not work the other way around, since the start bit is “light off” for 20 ms … This way I just saved on hardware cost ;) by not adding a reset switch and attach that to the reset input of the 4013 … all inputs other than D(1) are tied to ground. There is also a software pulse generator (activated/deactivated by pressing “P”, frequency change with “+”/”-“ keys), which is useful for testing the sound pitch or output power on a LEGO model operated by the CodePilot PBrick. The CodePilot can use its light sensor for scanning the bar codes also as a “speedometer” or “tacho”. The faster dark/bright changes are detected by the sensor, the higher the pitch of a sound, e.g., sound motor (diesel engine) or the power of the 9V output port. In the CodePilot models which can be built with set #8479, this is accomplished by rotating the #32060 “Technic Gear Timing Wheel 8 Tooth” directly in front of the bar code sensor. I have inspected the behavior of the CodePilot PBrick TACHO function a little closer using the “pulse generator” built into the QBasic program. There are the typical 7 power levels (0 = off), which are enabled with the following frequencies (50% duty cycle, as this seems to be what the #32060 wheel does as well when reflecting the light from the red built-in LED back onto the sensor): The red dots are the calculated frequencies with QBasic (“calibrated” delays), the blue dots are from oscilloscope data I have taken. Power level 7 is reached at about 30 Hz and maxes out. There is of course some jitter and frequencies are slightly off when using the program – but hey, this is emulated DOS in DOSBox-X running a QBasic program in its UI … I’d say not bad and congratulations to the developers of DOSBox-X The sound pitch reacts in even narrower steps – it maxes out at about 24 Hz with the lowest pitch at 1 Hz. The 20, 40, 60 VLL SPEED commands seem to reasonably agree with the regression line, e.g. SPEED 40 = power level 7 * 40%. When using the serial signals on the TTL/UART side, they are inverted and go (high)-low-high – which is irrelevant for the D-flip-flop; it triggers on any positive slope. Since there is only one such slope per “&H20 pulse” and the delay until the next pulse is calibrated, it works perfectly well "on both sides", RS232 or TTL/UART. Summary The CodePilot is a very nice PBrick – the predecessor of the RCX (almost same footprint, one plate less in height, same battery cover and battery power leads, released one year before the RCX – I strongly encourage you to read Blackbird’s Technopedia entry in full (already referenced above) – he is saying what this set and PBrick deserve as a tribute: “Nothing like this set had come before, and nothing like it would ever come again …”. The MicroScout is one sweetheart – its beeping before executing an instruction or when done is really sweet (some say annoying but what do they know). DOSBox-X totally rules, QBasic will live forever – as will the serial port and protocol in its RS232 incarnation! As usual the QBasic program (as QVLL_3.BAS/EXE) and more is on BrickSafe (https://bricksafe.com/pages/Toastie/vll-codepilot-microscout), changes to the code will not change the program name. Have fun Thorsten
- 6 replies
-
- vintage lego
- codepilot
-
(and 2 more)
Tagged with: