Jump to content
THIS IS THE TEST SITE OF EUROBRICKS! ×
THIS IS THE TEST SITE OF EUROBRICKS!

Recommended Posts

  • Replies 446
  • Created
  • Last Reply

Top Posters In This Topic

Posted

After running the initial sends to activate and wake up the Interface B I get the following response:

b'\x00\x00\xff\xc8\x95L\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xa1'
b'\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xb7'
b'\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xb7'

After that I don't see any changes if I press a button connected to input port 1.

Why is the first line b'\x00\x00\xff\xc8\x95L\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xa1'

And what is it trying to tell me?

OK I got it now but will take a bit to read the data and translate it.

Here is the basic python read code:

import serial
import time
ser = serial.Serial(port='/dev/cu.PL2303G-USBtoUART24110')
ser.write(b'p\0###Do you byte, when I knock?$$$')
#ser.read(16)
print(ser.read(31))
ser.flushInput()
ser.flushOutput()

while True:
    ser.write(b'2')
    #time.sleep(1)
    #ser.read(16)
    print(ser.read(19)) # Must always be 19 bytes
    #print(ser.read(2))
    ser.flushInput()

The following is a sample of the code reading the touch sensor on port 1

'\xcc3\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0b@\xff'
b'3\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0b\x00\xff\xcc'
b'\x03\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0b\x00\xff\xccs'
b'0\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0b\x00\xff\xccs\x00'
b'\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0b@\xff\xcc3\x00\x00'
b'\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0b\x80\xff\xcc\xf3\x00\x00\xff'
b'\xc8\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0c\x00\xff\xccr\x00\x00\xff\xc8'
b'\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc\x0c\x80\xff\xcc\xf2\x00\x00\xff\xc8\xff'
b'\xee\xc8\xff\xcc\xff\xc8\xff\xcc\r\x80\xff\xcc\xf1\x00\x00\xff\xc8\xff\xcc'
b'\xc8\xff\xcc\xff\xc8\xff\xcc\x14\xd8\xff\xcc\x92\x00\x00\xff\xc8\xff\xcc\xff'
b'\xff\xcc\xff\xc8\xff\xcc\x98\x88\xff\xcc^\x00\x00\xff\xc8\xff\xcc\xff\xc8'
b'\xcc\xff\xc8\xff\xcc\xfe\xc8\xff\xcc\xb8\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff'
b'\xff\xc8\xff\xcc\xff\x08\xff\xccw\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc'
b'\xc8\xff\xcc\xff\x08\xff\xccw\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff'
b'\xff\xcc\xff\x08\xff\xccw\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8'
b'\xcc\xffH\xff\xcc7\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff'
b'\xf7\xc8\xff\xcc\xb7\x00\x00\xff\xc8\xff\xcc\xff\xc8\xff\xcc\xff\xc8\xff\xcc'

 

  • 3 weeks later...
Posted

Instead of starting a new thread I figured I would just post here.  @diegobaca has made a few custom software solutions in the past for the DACTA Control Lab, well he's at it again.  This time you can interface with the Control Lab using a Raspberry Pi Zero W (or other models) and control the motors through a web browser.  This has to be one of the smallest footprints required to use the Control Lab.  I'll link his website below which has everything you'll need to try it out including a bill of materials.  The parts required shouldn't cost much, the Raspberry Pi Zero W sells for $20 (From Amazon In the US, subject to change over time).  I've created a video showing a quick overview of the steps to get it going and a couple use cases.  In the video I talked about how much power the Control Lab can provide, I should have tried using a beefier transformer as that did help a lot with the GBC layout.  There's more to share there but I may start a new thread, especially if I end up making modifications. 

Diego's website
https://controllab.io/

 

Posted

Wow, how cool is this!!!

Thank you very much for sharing and walking through the installation process, @BatteryPoweredBricks. Also, very nice video!

And congratulations to @diegobaca - simply incredible work.

I don't have an Interface B - these are for sure excellent pieces of LEGO engineering. Too bad, they forgot how to make such fantastic electronic devices :pir-skel:

All the best,
Thorsten   

Posted
On 11/3/2024 at 2:03 PM, BatteryPoweredBricks said:

Instead of starting a new thread I figured I would just post here.  @diegobaca has made a few custom software solutions in the past for the DACTA Control Lab, well he's at it again.  This time you can interface with the Control Lab using a Raspberry Pi Zero W (or other models) and control the motors through a web browser.  This has to be one of the smallest footprints required to use the Control Lab.  I'll link his website below which has everything you'll need to try it out including a bill of materials.  The parts required shouldn't cost much, the Raspberry Pi Zero W sells for $20 (From Amazon In the US, subject to change over time).  I've created a video showing a quick overview of the steps to get it going and a couple use cases.  In the video I talked about how much power the Control Lab can provide, I should have tried using a beefier transformer as that did help a lot with the GBC layout.  There's more to share there but I may start a new thread, especially if I end up making modifications. 

Diego's website
https://controllab.io/

 

I watched this yesterday, thanks for sharing.

I'm planning to control mine over python or Micropython depending on which device I have to had at the time hence why I'm looking at low level 

On 11/3/2024 at 7:01 PM, Toastie said:

Wow, how cool is this!!!

Thank you very much for sharing and walking through the installation process, @BatteryPoweredBricks. Also, very nice video!

And congratulations to @diegobaca - simply incredible work.

I don't have an Interface B - these are for sure excellent pieces of LEGO engineering. Too bad, they forgot how to make such fantastic electronic devices :pir-skel:

All the best,
Thorsten   

I ordered mine from Germany!

Posted
18 minutes ago, AJB2K3 said:

I ordered mine from Germany!

Heehee - me too - this very morning! For €80 from a BL seller located in Northern Germany ... we'll see "what" actually arrives :pir-huzzah2: He camouflaged the interface as "electric programmable" - never ever expected it there, I mean, it is electric, but not programmable - only to realize that the "Code Pilot Bar Code Sheet, laminated, 2 sided (paper size A3)" is listed in that category as well. I guess I am too narrow-minded :pir-wink:

Well, I don't like to play with smart devices that much - born a couple of years before the ARPANET was invented, I like to play with 8- or 16-bit machines running QBASIC programs, I love CP/M and MS-DOS <4.0. Well, the programming is much more comfortable on a modern laptop with DOS emulation, but then I copy the programs to the real machines.

So if all goes well, I shall code a QBASIC/QuickBASIC program for that beautiful machine ... and then run it on my IBM XT. As that one has no HD installed, the program length is a bit limited, but then 100kByte of compiled QuickBASIC code represents a sheer endless litany of code lines and subroutines :pir-laugh:

This is going to be fun!

All the best,
Thorsten

  • 2 weeks later...
Posted
On 11/4/2024 at 9:01 PM, Toastie said:

So if all goes well

Well - it all went well :pir-huzzah2: Just as a summary:

  • Tom's C# exe (LEGOInterfaceB.exe) - runs flawlessly on Win11/64; needs a freshly powered CLI and freshly started LEGOInterfaceB.exe. On a second attempt connecting to the CLI, it says "wrong reply". Power down the CLI and restarting LEGOInterfaceB.exe does the trick.
  • Anders Isaksson's Delphi exe (BrickLab.exe) runs flawlessly on Win11/64.
  • TLG's Control Lab DOS software runs flawlessly within DOSBox-X. My absolute preference :pir-stareyes:

What to say, serial ports, particularly RS232, rule.

  • BTW, the CLI has a PCB trace from pin 6 of the 9-pin DSub socket (DSR, data set ready) into the innards of the thing; this is not even mentioned in the corresponding CLI documents. Here, only pins 2, 3 (RX/TX), and 5 (GND) are referenced, as confirmed by many in this thread. I guess TLG wanted to make sure that as many as possible computers recognize that the CLI is always "ready", some hardware may check DSR.
  • The RCX serial IR tower cable + RS232 1:1 gender changer (male/male) work fine. This cable is essentially a null modem cable.
  • GND of the RS232 terminal and GND of the CLI power supply (9V, unregulated DC) are not connected, i.e., there is a complete electrical isolation of computer (RX/TX/GND/DSR) and CLI, as done in Interface A as well. A bit of an overkill, but who knows what teachers such as @JopieK come up with. Or me ... AND YES, I AM JOKING :pir-huzzah2:

Next up: Testing on my Toshiba 4090 laptop and the IBM XT, the latter will most probably fail: 256 kByte of memory ... ctrlab.exe has become a memory monster - DOS making windows ... in 1993 ... 

All the best,
Thorsten

Posted

I think the Windows 95 Control Lab software from LEGO is still the best choice, in terms of usability :) The Mac version doesn’t make full use of the display, being limited to a fixed window size. The DOS version is clever (looks like it’s emulating a Mac) but same applies, you run out of space on the screen fairly quickly when writing actual code and designing a button interface.

Posted
On 11/15/2024 at 10:40 PM, Toastie said:

Well - it all went well :pir-huzzah2: Just as a summary:

  • Tom's C# exe (LEGOInterfaceB.exe) - runs flawlessly on Win11/64; needs a freshly powered CLI and freshly started LEGOInterfaceB.exe. On a second attempt connecting to the CLI, it says "wrong reply". Power down the CLI and restarting LEGOInterfaceB.exe does the trick.
  • Anders Isaksson's Delphi exe (BrickLab.exe) runs flawlessly on Win11/64.
  • TLG's Control Lab DOS software runs flawlessly within DOSBox-X. My absolute preference :pir-stareyes:

What to say, serial ports, particularly RS232, rule.

  • BTW, the CLI has a PCB trace from pin 6 of the 9-pin DSub socket (DSR, data set ready) into the innards of the thing; this is not even mentioned in the corresponding CLI documents. Here, only pins 2, 3 (RX/TX), and 5 (GND) are referenced, as confirmed by many in this thread. I guess TLG wanted to make sure that as many as possible computers recognize that the CLI is always "ready", some hardware may check DSR.
  • The RCX serial IR tower cable + RS232 1:1 gender changer (male/male) work fine. This cable is essentially a null modem cable.
  • GND of the RS232 terminal and GND of the CLI power supply (9V, unregulated DC) are not connected, i.e., there is a complete electrical isolation of computer (RX/TX/GND/DSR) and CLI, as done in Interface A as well. A bit of an overkill, but who knows what teachers such as @JopieK come up with. Or me ... AND YES, I AM JOKING :pir-huzzah2:

Next up: Testing on my Toshiba 4090 laptop and the IBM XT, the latter will most probably fail: 256 kByte of memory ... ctrlab.exe has become a memory monster - DOS making windows ... in 1993 ... 

All the best,
Thorsten

Haha ;) good thinking @Toastie. B.t.w. I wish I still had those old machines. Sometimes my hang for innovation takes too much control and I tend to loose 'deprecated' things.

@BatteryPoweredBricks I'm a little too much engaged with my PhD stuff at the moment and part time teaching, but I might try to find a student who can try your marvelous work as a "free project" (80 hours) e.g. for open days etc.

  • 2 weeks later...
Posted (edited)
On 10/13/2024 at 5:10 AM, AJB2K3 said:

Here is the basic python read code:


import serial
import time
ser = serial.Serial(port='/dev/cu.PL2303G-USBtoUART24110')
ser.write(b'p\0###Do you byte, when I knock?$$$')
#ser.read(16)
print(ser.read(31))
ser.flushInput()
ser.flushOutput()

while True:
    ser.write(b'2')
    #time.sleep(1)
    #ser.read(16)
    print(ser.read(19)) # Must always be 19 bytes
    #print(ser.read(2))
    ser.flushInput()

 

 

Hello @AJB2K3,

I do have a Lego interface B that I try sometimes to "interface" with it using modern technology :-)

I did some VB Net, C# try out in the past.
But if you want to do Control Logics that have outputs and inputs interacting together, it is not that simple.
Blocky based programming may be more appropiate though...

I was planning to try interfacing the Lego Interface B with an ESP 8266 or better, ESP32.

ESP32 is cheap and has WIFI, Bluetooth, UART (Serial) etc... 

So I decided to go ahead after your posts :-)

I have a M5Stack Core2 (ESP32 and M5Stack have UIFlow programming IDE that uses blocky) and I have many ESP32 Dev Board as well.
So I started with an ESP32 Dev Board and flashed it with the latest MicroPython Binary.
I'm using Thonny as an IDE but I guess there are many others good IDE.

Since ESP32 UART is TTL and Lego Interface B is RS232, you need to get a RS232 to TTL converter module (MAX3232):
Like this ONE.
The cable I use is a straight DB9 to DB9, not nul modem in this case.  Between a PC and the Lego Interface, I needed a null modem cable...

 

About your code and my experience with the Serial Protocol of the Interface B:

- Before writing the lego start string to the serial port, I empty the read buffer.
- after sending the lego start string I check the read buffer until there are at least 31 bytes available because the successful started string reply has 31 characters long.
You may implement a timeout to make things better.
- After Lego has sent the "###Just  a bit off the block!$$$" started string, it will start to fill the RS232 read buffer with 19bytes long block of data.
(You should not "Flush" the read (or write) buffer.at this point..)

# MicroPython code for ESP32

import machine
from machine import UART
uart = UART(1, baudrate=9600, tx=17, rx=16)
uart.init(9600, bits=8, parity=None, stop=1, txbuf=256, rxbuf=1000)
uart.read()
uart.write(b'p\0###Do you byte, when I knock?$$$')
while uart.any()<31:
    pass
LegoReply=uart.read(31)
if LegoReply==b'###Just a bit off the block!$$$':
    print('Lego STARTED')


- If there are no glitches on your serial link, your code could just wait until Read buffer has at least 19 bytes than you read the 19 bytes, treat them and loop...

while True:
	if uart.any()>=19:
		LegoReply=uart.read(19)
		print(LegoReply)

- To be full proof, It would be better to program some validation, like the checksum of the 19 bytes that should be "FF" hex (0xFF or  \xFF)
If checksum not good, then discard first byte and read another one to make it 19 byte again and recheck the checksum.  Loop if necessary.
To check the sum: IF (sum(LegoReply) & 0xFF == 255).  (& 0xFF: Sum will be 2 bytes long but only first byte is needed to be check against 255 (FF hex))

- Some lego lab docs says the block of 19 bytes always starts with "\x00\x00" so you could also seach the block of 19 bytes for ""\x00\x00"", if not at position 0, then, read the missing number of bytes out of the serial.
For example, if you read 19 bytes, but "\x00\x00" is at position 3, discard the first 3 bytes and read 3 more bytes.
- Unfortunately, lego lab docs do not always mention it clearly but the 19 bytes block does not always start with "\x00\x00".
It can start with "\x10\x00" if the big red stop button is pushed on the interface while communicating. (Red led above the red button blinking fast).
- Also, the second byte is not always \x00. In fact, every bit of this byte represent the status of output ports command.  For ex.:, Sending command to activate Output A and C, the second read byte should be \x05 (00000101).
So you will need more validation code here but this would make the process stronger.

 
Hope this might help some...

Edited by Bliss
Posted

Hi @Bliss,

3 hours ago, Bliss said:

I do have a Lego interface B that I try sometimes to "interface" with it using modern technology :-)

very nice description of your work! Thank you very much! I am looking forward to seeing further progress on your side - I love ESPs as well. And they are very good for stand-alone automation tasks!

Now, currently I do something similar (interface interface B :D with my rather modern laptop) but I try to make it such that the resulting "code" can run on an IBM XT or Win 98 (and below ;) machines.

So my approach is using MS QBasic (1.1) or MS QuickBasic (4.5), the latter just to compile my program to COM/EXE files, the XT loves so much. Basic runs within DOSBox-X (not DOSBox though as a) the former is actively developed and b) runs rock solid as a "simple" Windows(64) app plus provides full and stable access to USB ports which then interface well with interface B).

What I found through some multiple hour long stress tests is that there was (so far) no glitch at all regarding the serial link. I thus simply strip the two leading bytes and the last byte of the 19 byte frame. My interface B is also happy with receiving a "stay alive" character (any, as others have said) every three seconds. I just have two "interrupt" handlers: One is ON COM and the other ON TIMER; this then works like a charm for hours. I need to make the handler as fast as possible, as XT's are a bit on the slow side :D, thus it looks a bit weird, I guess. The main DO/LOOP runs "on its own" and just watches the IDproc array to decide what to do. IDproc content changes only when there is something new ...

'----------------------------------------------------------------------------
'Interrupt handlers
'----------------------------------------------------------------------------
ComHandler:
  'input#  raw byte# raw byte pair#
  '  1       15+16          7
  '  2       11+12          5
  '  3        7+ 8          3
  '  4        3+ 4          1
  '  5       17+18          8
  '  6       13+14          6
  '  7        9+10          4
  '  8        5+ 6          2
  'Resolution of inputs = 10 bit for A/D; rotation sensor is different
  'First byte = high 8 bit, bit 7+6 of second byte = low 2 bit
 
  IF LOC(1) < 19 THEN RETURN   'record not complete; 2x18 (etc.) work as well
  r$ = INPUT$(2, #1)           'dump first 2 zeros
  FOR x% = 1 TO 8              'read 8x2 data bytes and process them
    IF IStype(x%) = 5 THEN     'rot sensor data treatment
      'IDraw(IDindex(%)) = XYZ
    ELSE                       'all other sensor data treatment
      'data are read from the head of COM buffer (new%), and stored in the
      'respective sensor array data location 1-8, but only if there is a change
      new% = ASC(INPUT$(1, #1)) * 4 + ASC(INPUT$(1, #1)) / 64
      IF new% <> IDraw(IDindex(x%)) THEN 'new<>old
        flag.new% = 1
        ix% = IDindex(x%)      'save interpreter reading time
        IDraw(ix%) = new%      'store new data (as old)
        SELECT CASE IStype(x%) 'process data and store in IDproc
          CASE 1
            'A/D - save data as is for display/programming
            IDproc(ix%) = IDraw(ix%)
          CASE 2
            'TOUCH
            IF IDraw(ix%) < 1023 THEN
              IDproc(ix%) = 1
            ELSE
              IDproc(ix%) = 0
            END IF
          CASE 3
            'LIGHT currently do nothing
          CASE 4
            'TEMP currently do nothing
        END SELECT
      END IF
    END IF
  NEXT x%
  'checksum check goes here
  r$ = INPUT$(1, #1)
  r$ = "" 'Dump checksum or check goes here
RETURN

KeepAlive:
  'Send some char every 2s (official time)
  'official value to be sent is &H2(?); any value works; CHR$() not required
  PRINT #1, 0;
RETURN

This is all very preliminary, but so far I will use this code to create a small text based "UI" and then come up with some programs for "robotics" or the like.

Best,
Thorsten   

 

Posted (edited)

Hi @Bliss,

oh wait! Now, this is nice information:

17 hours ago, Bliss said:

It can start with "\x10\x00" if the big red stop button is pushed on the interface while communicating. (Red led above the red button blinking fast).
- Also, the second byte is not always \x00. In fact, every bit of this byte represent the status of output ports command.  For ex.:, Sending command to activate Output A and C, the second read byte should be \x05 (00000101).

I did not read about that anywhere! In other words, the non-zero condition of byte #1 in the 19 byte frame could be used for emergency like behavior, e.g., stop all outputs, right?

And byte #2 of the frame is then identical to what they did on interface A: You always have the status of the outputs available. NICE!!!

Now interface B is then really a modernized version of interface A:

  • Both have a STOP button (physically stopping of all outputs of interface A and software information delivered in case of interface B - the interface still sends the full frame set of data back at the same speed, regardless of the blinking - I was wondering about that! Thank you for that information!)
  • Both have inputs and outputs accepting different sensors (interface A touch and light/rotation and interface B touch, light, temp, rotation)
  • Both have a permanently activated output for testing (4V on interface A and 9V on interface B)

Interface B has of course more inputs and outputs than interface A, but the operational philosophy is essentially the same. With the exception that you always have to ask interface A for its sensor and output status, interface B delievers that information every so many ms. Plus, PWM signals have to be generated by the attached computer using interface A, whereas interface B is providing that on board.

I thus changed my COM ISR code accordingly to:

- SNIP -
IF LOC(1) < 19 THEN RETURN   'record not complete; 2x18 (etc.) works as well
  IF ASC(INPUT$(1, #1)) <> 0 THEN 'red STOP button pressed once (LED blinks)
    flag.stop% = 1             'Turn off all outputs
  ELSE
    flag.stop% = 0             'resume normal output operation
  END IF
  OStatus% = ASC(INPUT$(1, #1)) 'bit encoded HGFEDCBA; 0=off, 1=on
- SNIP -  

Works perfectly well! Again, thank you very much!!! Your post really clarified a lot of things.

All the best,
Thorsten

Edited by Toastie
Posted

Dear LEGO interface B enthusiasts :pir-huzzah2:

As said in a post above, I am playing with the interface B hooked up to DOS/QBasic or QuickBasic either on my laptop within DOSBox-X or on true DOS machines (Toshiba Satellite 4090 or IBM XT).

So far all is good - on all machines the QBasic code runs flawlessly.

However, I am a bit confused regarding the serial protocol, i.e., the information stored in the 19 byte data frames, #9751 cranks out at about 50 Hz. Or more precise: There seems to be contradictory information on the web ...

Question is the following correct/complete?

1280x600.jpg

Does anybody have further information? I have a hard time believing that the white (=unused) bits are exactly that: Not used bits in the protocol. Byte #1 could be some sort of start byte with 6 zero bits leading but hey ... also, in byte 4 (6, 8, ...) bits 5-3 are not used OR there is more. For example, there is some information out there that the light sensor is sampled with 12 bit resolution (rightmost 12 bits) but that gives confusing results on my side. In addition, how should the hardware of interface B know which sensor is attached? Sure, I can tell my software which one it is, but the interface hardware does not, or does it? I can put a touch sensor on a blue powered or a yellow non-powered input: Same result. A light sensor needs power, so does not work on yellow inputs but on blue of course. Am I missing something, or is this "it"? As said, I am happy with that, but just want to make sure I don't drop data.

Secondly: The A/D converted 4 voltage levels of the rotation sensor (depending on its internal rotor blade positions, see here: https://philohome.com/sensors/legorot.htm) are converted to the three lower bits of the second byte (of each powered = blue input); bit 2=direction of rotation, bits 1 and 0=number of rotation ticks since last frame was sent. 16 ticks=one full 360° turn. The other bits naturally don't mean much, as they represent the last analog value reafd from the rotation sensor. With two bits, the max. "changed ticks number" is 3. When we assume that the 19 byte frame repetition rate is 50 Hz = 50 s-1 (I read that somewhere ...) then the max. full 360° rounds per second of a rotation sensor that can be resolved are: 3*50/16 = 9 s-1 in other words about 10 Hz. Which is not that much, I must say; interface A does much better! OK, but does not know the direction of rotation. Is this what others observe as well?

Thanks a lot in advance!

Best regards,
Thorsten 

Posted (edited)
1 hour ago, BrickTronic said:

On this Web-Page there you might find detailed information

Hi Jo,

been there; Anders' Delphi code (version 3, but version 1 is doing the same regarding sensor reading) as well as the information he lists on that page from 1994 (Newsgroups:rec.toys.lego, Andy Carol). However, on Tom's LGauge page (https://www.lgauge.com/technic/LEGOInterfaceB/9751.htm) there is a table that lists for the light sensor a different protocol (12 rightmost bits of a 2-byte sensor word = light data). But just looking at the non-used bits in the protocol I put into semi-graphical format above, I thought this could very well be. But I don't get it to work that way ...

But thank you for your help!

All the best,
Thorsten

P.S.: I am in touch with Tom; he said he will take a look into his C# code again, when he finds time - this is all so long ago. It could also be that there are different versions of interface B out there.

Edited by Toastie
Posted (edited)
On 12/4/2024 at 7:11 AM, Toastie said:

1280x600.jpg

 

Hello @Toastie,

For Light Sensor, leftmost 10 bit are definitely the analog value, not the 12 rightmost bits...

I noticed that bit 4.3, for light sensor, will go "1" when light is blocked (or not enough light) and go to "0" when light source not blocked.  It looks like the interface use this bit to turn ON/OFF the input led.
But it's more tricky than just blocking the light, if you block the light source slowly, this bit wont change. (or if you unblock slowly as well).
Also, Bit 4.4 goes 1 for one scan after 4.3 changes from 0 to 1 or from 1 to 0.

In short, if you have a part that moves slowly in front of the light source, bits 4.3 will stay 0.  It might stay 1 if you moved fast enough to block the light (goes to 1) then move slowly out of the light source.
If a long part goes fast, bit 4.3 will go to 1 and when the long part unblock the light, this bit will go to 0.

4.0 & 4.1 seems to go to 1 at the same time for one scan when something block, unblock the sensor (Must not be too far away).

Original instruction says Light Sensor can be used to:
- Count using a pulley wheel (Could be the use for the 4.0, 4.1 bits?),
- Work as an electric eye.
- Sort color (grey scale)

Bit 4.2 of light sensor, for me, remains zero at the beginning and then after having a very bright light like a bright flashlight near the sensor and removing this bright light from the sensor, this bit will go to ONE.  After that, it will reset to zero if I bring back the bright light near the sensor.
Bit 4.0 goes to ONE for one scan at every change of state (0->1 or 1->0) of the bit 4.2.
I'm not sure there is any use for this bit 4.2 really...

Bits 4.5, I do not know yet if it is of some use.

I'm still testing...

 

About the 4.3 bit, It appears that this bit for the rotation sensor is also used the same way as for the light sensor. 
It toggles the interface input led (1=Led off, 0= led on).  This bit changes every 1/8 turn.
For the Rotation Sensor, the bit 4.4 goes 1 for one scan after 4.3 changes from 0 to 1 and from 1 to 0.

 

Edited by Bliss
Posted

@Bliss

Thank you very much for all these findings!!! I am particularly happy that the light sensor signal is A/D converted in the same way as the non-powered sensors.

With these new findings, interface B's behavior is more and more like that of the RCX - which is, as far as I am concerned, the "follow-up" control device. On the RCX the threshold values (on, off, hysteresis) for sensors can be user defined/calibrated, which is extremely helpful.

Very nice research results!

All the best,
Thorsten 

Posted (edited)

@Bliss

You are not alone :pir-huzzah2: I am also testing.

Managed to get a QBasic program up and running, "servicing" all inputs and outputs (i.e., not only manual control, but full program control, e.g. setting the power of n outputs in parallel to on/off and all the other things).

As far as I am sampling input data (19 byte@9600 baud), the rotation sensor is responding (naturally) with the lowest rate; counts swiftly "lose it" when rotating too fast. On the other hand, the rotation sensor bits 4.0 - 4.2 give you the direction and incremental count (max. 3 per 19 byte data frame sent + internal conversion rate). However, individual light or simple A/D conversion bits can change at the full 19 byte@9600 baud transmission rate, with no further internal conversion in the way. These bit changes are thus much faster reported than the 1/16th rotation increments. This also reflects the behavior of interface A, which just provided the digital level (bit) at its sensor ports; no direction provided, just the light/no light state, and the program had to sample these changes.

More research underway, using your bit resolved information!

Best wishes,
Thorsten

Edited by Toastie
Still checking
Posted (edited)

Dear all,

I just wrote a summary of findings related to the serial data emitted by interface B (#9751), when different sensors are attached to the sensor ports. This is solely meant to be a reference and not any kind of new reporting. There are some minor new results below I did not find anywhere else, but this work is based on all the entries in this thread, as well as on data available on the web.

Sensor ports of #9751

Sensor ports 1 – 4 (yellow) are passive analog inputs

Sensor ports 5 – 8 (blue) are powered analog inputs; power is supplied, when A/D sampling is not active within #9751.
Voltage supplied during powered state: 9V with a 15 mA current source (should the sensor ports of #9751 behave as RCX ports do, see corresponding circuit diagrams for powered RCX inputs here: https://brickshelf.com/cgi-bin/gallery.cgi?i=1067044, author Mark Bellis)
The sensor port voltage range is 0 – 5V.

Sensor port impedance/resistance is 10 kOhm internally tied to +5V for all sensor ports (when not in power delivery phase), should the sensor ports of #9751 behave as RCX ports do (see corresponding A/D reading vs. applied input port resistance here https://brickshelf.com/cgi-bin/gallery.cgi?i=1088015, author Mark Bellis). Note that the response to resistance change is highly non-linear (logarithmic abscissa scale used in the diagram).
When no sensor is attached, the A/D reading “1023” corresponds to 5V. Short-circuiting the sensor port leads to an A/D value of “0” corresponding to 0V. However, the latter is not achievable with 9V touch sensors, as these have an internal resistance > 0 Ohm. There are different versions of touch sensors, in addition, they do age. The resistance of some of my touch sensors is about 500 – 1000 Ohm when tightly pressed. This results in an A/D response between “100” and “200”, which is in full accord with Marc Bellis’ findings for the RCX ports.

When an external voltage is supplied to a #9751 sensor port (e.g., by an active sensor or any other suitable voltage source) in the range 0 – 5 V, it needs to have an internal resistance low enough to compete with the +5V/10kOhm internal pull up voltage supply to generate reasonable changes in the A/D converted data. Important: When doing so, pay attention to polarity!!! GND of the external voltage needs to be connected to 0V/GND of the sensor port. When the external voltage supply has a very low resistance (e.g., a laboratory 10A power supply), then the voltage to A/D value response is almost linear.

Characteristics of the (serial) sensor data continuously emitted by #9751

The emitted data from #9751 regarding sensor readings are composed of 2 bytes (high byte first, low byte next, denoted as bytes “3” and “4” in the diagram below, corresponding to a 16 bit long word.

Generally, there appear to be 2 data “segments” within the 16 bit word:
Segment 1: First 10 bits = A/D converted “raw” value of the voltage present at the sensor input port shortly before serial data emission. When no sensor is attached: 5V internal pull up = “1023” = 1111 1111 11 (referenced as bits 3.7-3.0 and 4.7+4.6). Anything attached to a port with either a resistance or a voltage/current power supply in the range 0 – < 5V results in a smaller value. These values are completely independent of sensor used: All touch sensors produce almost the same A/D value returned, regardless of yellow (passive) or blue (powered) sensor port used. Active sensors naturally work only on blue (powered) sensor ports, as they need power (9V/max 16 mA, see above) to provide a voltage/current source at their output.
Segment 2: Remaining 6 bits (referenced as bits 4.5 – 4.0) are encoded by the microcontroller of #9751 depending on states and changes or transitions occurring within the several A/D values sampled by the microcontroller between two 19 byte data emission cycles. They also depend on the order these transitions occur. This means changes from/to defined voltage levels are processed. They are done for all 8 inputs.

#9751 does not know what type of sensor is attached to which port (I don’t believe is senses anything like “active sensor” or even more specific: “rotation sensor” or “light sensor”). The serial data emitted by #9751 simply need to be interpreted by the program controlling the interface: After several internal sensor “scan(s)”, #9751 always sends out the 10 “raw” A/D bits and the 6 “further processed” bits for each of the 8 sensor ports, in the format 2 bytes + 2x8=16 sensor bytes + 1 checksum byte.

Attaching a (passive) touch sensor to an active sensor port does thus lead to rather “confusing” readings regarding bits 4.5 - 4.0: #9751 internally processes the raw A/D values it scanned several times during the period until a next 19 byte data emission cycle occurs.
(All following data regarding the rotation sensor are taken from Philo’s website: https://www.philohome.com/sensors/legorot.htm). As an example, when input voltages transition from about 1.3V -> 3.3V, this is evaluated by #9751 as one rotation click (1/16th of a full turn) in clockwise (cw) direction. Thus, bit 4.0 = 1 (one click), 4.1 = 0, and 4.2 = 1 (cw). A rotation sensor always provides these voltage levels. When further transitions (3.3V -> 2.0V, 2.0V -> 4.5V) are detected, they remain (unequivocally) cw and are thus added up to a max. value of 3 (bits 4.0 and 4.1 = 1). This results in a max. resolution of 3 ticks x 50 data emissions/s = 150 ticks/s for rotation sensor counts. Higher rounds per second lead to data loss, as experimentally verified.
Furthermore, this suggests that bits 4.0 – 4.2 make only “sense” when a rotation sensor is attached. However, they will also change when a light or touch sensor is attached, but they don’t mean anything valuable as certain light levels (and thus voltage level) transitions will cause arbitrary 4.0 to 4.2 bit changes.

That leaves us with the 3 “processed” bits 4.5 – 4.3 for other sensors, i.e., the temperature, touch and light sensors; I believe back in the days (1993 onwards) no other active 9V sensors were available. I did some “bit masking” experiments and so on, and arrived at these conclusions:
Temperature sensor: This seems to be a PTC-type sensor; the higher the temperature, the lower the resistance and thus lower the raw data value
As there are no fast resistance transitions when the temperature changes, bits 4.5 – 4.0 have no real meaningful values. They do change though upon temperature change. In this context, "fast" is a change between "valid" states during the internal scans, #9751 performs between two serial data emission cycles. 
Touch sensor: In addition to the raw data value there is another bit, that does yield information: Bit 4.3 is 1 when the sensor is “open” (port LED off, high resistance) and 0 when “closed” (port LED on, low resistance) – and remains as such. In other words: The user control program has only to check this one bit for deciding “touch sensor closed” or “open”. Downside: The internal threshold and hysteresis of #9751 is (yet) not known. But we’ll find out! Secondly: Maybe threshold and hysteresis can be programmed into #9751 – who knows what other commands as reported are available. This needs also close inspection of the #9751 manuals! The RCX allowed such (powerful) manipulations
Light sensor: Well, touch sensor behavior must be observed with all other sensors as well. And it does: Bit 4.3 is 1, when the light sensor’s A/D value is regarded by #9751 as “dark” = high resistance; the LED at the sensor port is off. It turns to 0, and remains there, when the A/D value is regarded at “bright”; resistance is low, LED is on. This behavior can be mimicked with a touch sensor, see above.
Bits 4.5 and 4.4 represent numbers of transitions from bright to dark and dark to bright since last 19 data byte emission, encoded as 2 bit word (see rotation sensor). There is no direction bit, as the light sensor cannot provide such information. This also works with a touch sensor; however, the internal sensor scan time of the microcontroller inside #9751 is really short; it will certaily detect one "push" and report that (bit 4.4 = 1), but in the next data emission cycle, (most probably) this bit is 0 again, as only transitions are detected. The same holds true for the release transition. With a really "noisy" switch, the on/off jitter should lead to some bit 4.5 and 4.4 changes (e.g. bin 11 = dec 3) when the switch was ringing 3 time in a way that the on/off threshold and off/on threshold was three times crossed and the microcontroller's A/D converter caught that.

Fun fact (I just read the microcontrollers data sheet more closely): The Siemens SAB 80C515 chip used as brain inside #9751 (an 8-bit CMOS microcontroller with factory mask-programmable ROM), features an 8-bit A/D converter with 8 multiplexed inputs - but wait - reports 10 bit A/D converted values. Huh???
Well, the A/D converter has programmable internal reference voltages; as far as I understand the data sheet, if a higher resolution than 8 bit is wanted, the thing makes a dual scan, first coarse and then, with adjusted reference voltages, a more precise scan in a narrowed voltage range. OK, maybe it is like that, I am not sure :pir-blush:.

But wait there is more, there always is, we’ll see … tonight a shall break out my lab power supply (yes, it is a power supply I will be snatching from the lab :pir-grin:) and see whether my "linear 0 - 5V scale" claim is true or not. Will report back here.

Here is the updated little bit diagram for #9751 data traffic:

1280x773.jpg

All the best,
Thorsten

Edited by Toastie
Jo's correct number of 50 data frames sent per second
Posted (edited)
15 hours ago, Toastie said:

...

This results in a max. resolution of 3 ticks x 45 data emissions/s = 135 ticks/s for rotation sensor counts
...

All the best,
Thorsten

Hello,

45 data emissions ????
where does this 45 come from ?

9600Bd is 104,16us per Bit, Start + 8-Data + No-Parity + Stop are 10 Bit per Byte and 19 Bytes (190 Bit). So 19,7916ms for a Data-Frame.
-> so 20ms repetition of the Frame

3 detected 1/16 rotations every 20ms (50Hz) is 50*3/16 rotations = 9,375Hz (rotations) or 562,5 rpm
 

Can you tell me how you evaluated 135 of 1/16-ticks per second instead 150 ?


Jo

Edited by BrickTronic
Posted (edited)
2 hours ago, BrickTronic said:

Can you tell me how you evaluated 135 of 1/16-ticks per second instead 150 ?

Hi Jo,

well, I simply wrongly assumed 2 stop bits, as I said in the little bit sheet. So I have to multiply my (rounded) 135 value with 11/10 = 1.1; this yields 148.5 ...

Yeah, I blew it again. This is how I do initialize the COM port in QBASIC:

OPEN ComPort$ + ":9600,N,8,1,CD0,CS0,DS0,OP0,RS,TB2048,RB2048" FOR RANDOM AS #1

Guess what, the 1 stands for 1 stop bit ...

So I stand correct and will make the changes did change the text and also the bit sheet.

Thank you very much for pointing that out!!!

All the best,
Thorsten

Edited by Toastie
Posted

Dear All,

quick update: passive #9751 sensor ports have a bias voltage of 5.0V. This will be the same for powered sensors during the sampling time of the internal A/D converter, as the same touch sensor applied to a passive (yellow) port gives exactly the same reading when pressed, as attached to an active (blue) port 

In addition, as speculated, the voltage scale of #9751 sensor ports is linear. Used a lab power supply to take some readings:

800x477.jpg

The little deviation around 0V is because my power supply did not like the 5V bias voltage from the sensor port; it showed 0.02 V on its display, but that seems to be off a bit. A 9V lamp attached to the port (acting as "almost" short) gives a reading of 4, so we know a reading of 0 is very close to 0 V. The data point size in the diagram reflects experimental uncertainties.

Furthermore, at 0.02 V applied (which is not exactly that, see above, it is a little more), the external power supply sinks 0.48 mA. In this case, the voltage drop across the internal #9750 resistor(s) is 4.98 V (or a little less), assuming the internal resistance of my meter is 0 Ohm, which is also not true. But all that does not matter: Simply taking the numbers as they are yields: R(internal) = U/I = 4.98V/0.48E-3A=10375 Ohm, or 10k, as speculated.

Conclusion: #9751 sensor ports behave as RCX sensor ports do. Not that much of a surprise :pir-laugh:

Best,
Thorsten

Posted (edited)

Dear all,

more timing and some other data on #9751:

  1. A serial port buffer is filled with 8192 bytes in about 9.6 +/- 0.2 s (used my QBasic program and watched for IF LOC(1) > 8191 THEN STOP with a 8192 long serial input buffer, did not read anything, just waited for the program stop along with my cell phone timer. Took a few replicates ... this is absolutely not elegant but quick ...
    In other words, 8191/19 = 431 19 byte long data frames are emitted in 9.6 s = 45 frames per second. Every 22 ms such a frame arrives.
  2. One 19 byte data frame is (see above) 20 ms long.
  3. #9751 samples the input ports for 130 us every 3.3 ms (used my very low profile digital oscilloscope).
  4. Within 130 us, all 8 inputs of #9751 can be sampled, as the total sampling/conversion time for the microcontroller's ADC is 13 us (as per data sheet).
  5. 3.3 ms x 3 = roughly 10 ms are required for a 3 bit increment in the internal "counters" for the light and rotation sensors.  
  6. During sampling, the input port voltage is 5.0 V (10k internal pull-up resistor, see my last post), the remaining time it is 7.5 V for active sensor "charging".
  7. When "shorting" an active input with a 9V lamp, it "glows" a little; "shortening" it with a current meter results in a current of 15.9 mA which is the max. current provided by each input of #9751, as was reported by Mark Bellis for the RCX inputs.

That's it for the moment :pir-huzzah2: maybe @Bliss, @BrickTronic or anyone else of course may want to check my calculations/assumptions? I tend to screw up such things regulary ...

Best,
Thorsten   

Edited by Toastie

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.

Announcements

  • THIS IS THE TEST SITE OF EUROBRICKS!

×
×
  • Create New...