Jump to content

Toastie

Eurobricks Dukes
  • Posts

    3,983
  • Joined

  • Last visited

Everything posted by Toastie

  1. Hi Evan, well, as before when this all started, modern computers don't have a parallel interface anymore. At least not anything generic I know. So you need a device that translates the serial data from an USB port (as serial RS232 ports are mostly gone as well ^^) to parallel - preferentially as fast as possible. An Arduino (or virtually any other microcontroller board exposing 8 (I/O) + 2 (COM) I/O pins to the user shall do the trick. They are cheap, readily available, and flexible. It's the same as shown here years ago: For the version of @Bliss, the pinout is different, I believe. I layed it out such that the most of th I/O pins of the board can be directly soldered to the Interface A compatible 20 pin header. Best Thorsten
  2. @Bliss, sorry this message will be merged with the former - stupid me: First read, then think, then write. And not: Read part of it, write, read the rest ... that's me OK, here we go: I believe what you wrote above is the way to go. As you are using the much more sophisticated command type approach for writing/querying the Arduino, there could be a command: What's the sensor X count or the like. As said, TC Logo does that in the 1 ms ISR for free, as well as writing other information into some memory regions: Time since last change and so on. It is all documented in the TC Logo Reference document. This is all crazy cool! The full power of 2026 and the full power of 1996 ... All the best Thorsten
  3. Yes, that was my point: Interface A is not doing anything but providing (transient) 8-bit data on its connector. Bits 6+7 change as they like; when they changed form off to on back to off, but no one monitored that change actively, this information is gone. On the lower 6 bits, it is different, as there was a computer controlled change - I keep a state variable up-to date on my programs so in essence, I do know the value of the lower 6 bits. This is why I am sending out the current "status byte" (bits 7+6=0 + 5-0 bits) as fast as I can in the main loop of my QBasic program. The main loop is only meant to scan for keystrokes as shown on the "UI" or screen mask. A good number of sub programs do take care of the action (the code is on Bricksafe, it's a plain vanilla QBasic program and opens with every text editor: https://bricksafe.com/pages/Toastie/qbasic-programs ; the Q9771_3.BAS serves both, 9750 and 8485 (Control Center II) with my modifications. The EXE file runs directly within DOSBox-X; it starts up in simulation mode, so won't crash because there is no Arduino attached ;) SELECT CASE ComMode CASE COM9771 InputStatus = INP(ADDRESS9771) AND 192 CASE COMSERIAL, COMBLUETOOTH 'Write current IOStatus (as does TCLogo every ms), wait and read the 'reply from Arduino; INPUT$ waits for complete byte transmission. WriteOutputPort 'Read Arduino reply InputStatus = ASC(INPUT$(1, 1)) AND 192 'Read 1 byte, mask bits 0-5 'The full I/O status is ASC(INPUT$(1,#1) without mask. 'The following works, but is too fast, as there is no check for the 'complete transmission of 1 byte -> needs delay (and then works) but 'this becomes machine dependent. 'InputStatus = INP(&H3F8) AND 192 - and all other COM port addresses CASE COMPARALLEL InputStatus = INP(ADDRESSPARALLELPORT + 1) AND 192 'The full I/O status is: 'INP((AddressParallelPort AND 63) OR (AddressParallelPort +1) AND 192) CASE COMSIM InputStatus = 192 '11000000 simulation only END SELECT For this discussion, only case COMSERIAL is interesting ("USB2TTL <-> Arduino" or "USB2Ser <-> serial cable <-> Ser2TTL <-> Arduino"), BT works almost the same: In the main loop, on every loop iteration, "GetSensorBits" is called, see above, that is part of it. When in mode COMSERIAL, WriteOutputPort is called, which just cranks out the 8 bits. The Arduino realizes that, sets outputs on 9750 accordingly (when there is no change, Arduino outputs retain their status and thus 9750's outputs just retain their status), and spits out the return byte, which I then mask off for bits 6+7 = sensor status. The other modes above all run on my IBM XT, as it has a parallel card (TC Logo "P" version provided by @alexGS for this purpose is available, attaches directly to 9750), serial card (TC Logo "S", same thing, needs the Arduino), and a 9771 card, which hooks up directly to 9750 of course. It is pure fun of doing this, there is no reason other than that. 9771 is good enough; however, I do develop my QBasic programs within DOSBox-X + QBasic, and thus need to use USB and the Arduino for testing and playing of course :D As said, this way I can catch sensor changes at about 200 Hz (no keys pressed, which the main loop has to process). The Technic disc has on one side 4+4 b/w segments and on the other 8+8, if I recall correctly (I am in Northern Germany and my LEGO is 540 km away ;) - that means there are 4 or 8 light changes/360° rotation, which the 4.5V sensor may catch, when the changes do not occur too swiftly (this is also sensor HW limited, I noticed that when using my Atari ST 1040 using its "quasi parallel printer port"). The Atari is pretty fast when using GFA Basic, and still 240 Hz or so was the max. response I could get from the 4.5V light change sensor + Technic disk. It wasn't the computer - it was the sensor :D Best wishes Thorsten P.S.: Why didn't I bring the Arduion with me ... I am sitting here with Interfac B the next 8 days ... well will do tests on that one then ...
  4. @Bliss that is absolutely OK! One thought though: In order to catch sensor changes, particularly that of the rotation sensor, TC Logo scanned the inputs with that 1 ms rate. It also accumulates sensor clicks after the last scan and provides these counts to the user. On my QBasic code I am "scanning" the sensors as fast as the main loop runs; this leads to an about 200 Hz "rotation sensor" (=patterned Technic disk + 4.5V light change sensor) resolution, which is good enough for simple machines, and this is also close to the HW limit of the light sensor. I guess the Arduino does that then as well, right? Best Thorsten
  5. Damn ... but this was just the cp'd version from the Arduino IDE, just checked. But thank you very much for noticing, will have to edit that post! Best wishes Thorsten You too!!! And thank you so much for the link - I somehow lost - or its is buried in this thread. Bookmarked now! Best wishes Thorsten
  6. Not me, but yes :D Upon program startup, the original LEGO TC Logo software, as well as the LEGO Lines program and other (for the BBC Micro and so on), do send 0x63 (or any 6 bit pattern) and then immediately reads back the I/O port status. As the Interface cards for the IBM (and others) have latched I/O ports (74LS373, VIAs, PIOs etc.), the value sent out is read back from the 9771 (etc. card). It does that on the IBM at two I/O addresses. If there is no or wrong read back value, the LEGO software assumes there is no such card present and refuses to work. It can't check for the Interface to be present. As I am using an original 9771/9750 combo and the original software on an IBM as well as on DOSBox-X (serial version of TC Logo made by @alexGS) I needed to mimic that behavior for the latter. This way I can do TC Logo/QBasic programming on my laptop with just the Arduino attached. Best, Thorsten P.S.: Yes I knew that website, but I wanted something simple and fast ;)
  7. He-he - this is getting fascinating - having the HW/SW simulators (Arduino etc. based) would really be fun, as you need not have the expensive vintage equipment, could develop cool programs try them out, see what they can accomplish. And then eventually reconsider your saving/buying habits. Yes, I did implement PWM control for 4.5V LEGO as well as Tenka's cubic motors using an ESP Vroom board with some H-bridge breakout board drivers for my suspended train: https://www.eurobricks.com/forum/forums/topic/197590-mod-85007-pantasy-suspended-steam-punk-train-motorized-with-tenka’s-circuit-cubes-elements/#findComment-3687247 The ESP's have so many PWM options, it is crazy. And as you said, your Blocky code then needs to manipulate only the PWM controls ... Best regards, Thorsten
  8. @Bliss This is again wonderful news!!! I also believe that you really don't need an Interface A for experimentation, as you would need a serial to parallel converter anyway, and all modern computers/laptops etc. don't have that anymore (since long). Such a converter can be the smallest Arduino or the like microcontroller with 8 I/O ports and two more for an USB2TTL (or BT2TTL) adapter. The little bit-banging code I wrote some time ago as well as the corresponding interface is here: https://www.eurobricks.com/forum/forums/topic/192941-lego-interface-a-97509771-–-lego-technic-control-1-tc1-referenceideas-thread/page/3/#findComment-3586230 @maehw has modified the code a bit (I am a chemist ^^) to make it even better. With such an interface no 9750 is required at all, as you can see the LEDs of the Arduino flashing as they would exactly on the Interface A. The latter is nothing more than a "motor driver" (6 outputs). In addition, it provides permanently sensor data, converted to TTL on/off level. Whatever you write as 6 bit (0-5) word (e.g., 111111 for all outputs on, or 100000 for output 5 on and outputs 0-4 off) to the 9750 TTL compatible inputs at any time, is directly funneled to the motor output. Whenever you read the status of 9750, you'll get back an 8 bit word, bits 0-5 = output status, bits 6+7 = sensore status (= on/offm, there is no ADC or something like that inside 9750. The software for 9750 (within the LEGO DACTA Technic Control 4.5V universe) does either build on simple output on/off schemes (as well as input is on or off). This holds true for 4.5V touch sensors or 4.5V >light change< sensors. As said, there is no A/D. There is - as far as I know - one exception (@evank and @alexGS know better!) and that is the TC Logo for DOS (and maybe Apple?), which provides PWM control for all 6 outputs. Here is how they did that (sorry for the long read): https://www.eurobricks.com/forum/forums/topic/192941-lego-interface-a-97509771-–-lego-technic-control-1-tc1-referenceideas-thread/page/3/#findComment-3586230 In essence, every 1 ms, a 6 bit word, representing the current PWM state of all 6 outputs (either on or off) is sent to 9750. A full PWM cycle is 8 words, so that the full PWM signature for power settings between 0 and 7 takes 8 ms = 125 Hz. The signature is adjusted to the characteristics of 4.5V motors, I believe. Upon changing power level of one or more outputs, only the 8 variables are changed. Here is a QBasic program, which is way too slow, but shows the idea: 'Program PWM_1.BAS (2023-4-20) 'Simulation of the TC Logo PWM routine => WritePowerOutByte 'In TC Logo, WritePowerOutByte is called every ms by timer interrupt (8) DEFINT A-Z DECLARE SUB WritePowerOutByte (i AS INTEGER) 'Write 8 bit long PowerOut array to 'serial port COM1. DECLARE SUB CalculatePowerOut () 'Called every time the user changes a 'power setting for a 9750 chn. 'Constants DIM SHARED PWMData(0 TO 7) AS INTEGER 'Array with the (const) 8 pwm settings. 'Variables DIM SHARED UserPower(0 TO 5) AS INTEGER 'User power settings (0-5) DIM SHARED PowerPWM(0 TO 5) AS INTEGER 'Calculated from PWMData and UserPower. DIM SHARED PowerOut(0 TO 7) AS INTEGER ' DIM t AS DOUBLE 'For performance checking only. '============================================================================ 'Setup ' 'Prepare (const) pwmdata-power (0-7) array. 'Data arranged as in TCLogo; ' 'MSB LSB 'DATA 0 '0 0 0 0 0 0 0 0 'Always off = pwr 0 'DATA 17 '0 0 0 1 0 0 0 1 ' pwr 1 'DATA 73 '0 1 0 0 1 0 0 1 ' pwr 2 'DATA 170 '1 0 1 0 1 0 1 0 ' pwr 3 'DATA 214 '1 1 0 1 0 1 1 0 ' pwr 4 'DATA 238 '1 1 1 0 1 1 1 0 ' pwr 5 'DATA 254 '1 1 1 1 1 1 1 0 ' pwr 6 'DATA 255 '1 1 1 1 1 1 1 1 'Always on = pwr 7 DATA 0, 17, 73, 170, 214, 238, 254, 255 FOR n% = 0 TO 7: READ PWMData(n%): NEXT n% 'power(n) = array with the actual power data (0-7) of each channel 1-6. 'Every ms, each column is sent via the OUT command to 9750. 'Power 0-7 need to be translated using pwmdata array: ' ' Example only: ' MSB LSB UserPower(0) = 7 ' 1 1 1 1 1 1 1 1 'PWM LSB = ouput 1 UserPower(1) = 6 ' 1 1 1 1 1 1 1 0 UserPower(2) = 5 ' 1 1 1 0 1 1 1 0 'PWM bit structure of output 1-6; UserPower(3) = 4 ' 1 1 0 1 0 1 1 0 'as determined by measurement. UserPower(4) = 3 ' 1 0 1 0 1 0 1 0 UserPower(5) = 1 ' 1 0 0 0 1 0 0 0 'PWM MSB = output 6 ' ------------------------ ' pwm byte: 63 15 23 11 55 15 4 31 '"Added column" result = PWM output. '============================================================================ CLS CALL CalculatePowerOut PRINT "Running" 't = TIMER DO 'Each call = timer interrupt. FOR i = 0 TO 7 'One cycle = 8 bits CALL WritePowerOutByte(i) NEXT i LOOP 'PRINT USING "#.##"; (TIMER - t) SUB CalculatePowerOut powerbit = 1 FOR PowerOutBit = 0 TO 7 pwmbit = 1 FOR chn = 0 TO 5 temppower = PWMData(UserPower(chn)) \ powerbit temppower = temppower AND 1 temppower = temppower * pwmbit PowerOut(PowerOutBit) = PowerOut(PowerOutBit) + temppower pwmbit = 2 * pwmbit NEXT chn powerbit = powerbit * 2 NEXT PowerOutBit END SUB SUB WritePowerOutByte (i AS INTEGER) OUT &H3F8, PowerOut(i) '&H3F8 = I/O address for serail port (COM1) END SUB Do you think it is feasible to create a LEGO Blockly block that just does this: 1 ms repetition time, crank out a byte (only 6 bits used) and immediately read back a byte (status including sensor ports), and power setting blocks for one or multiple outputs? The thing is, on TC Logo that I am running on an IBM XT or the DOSBox-X emulator, 9600 baud is the max baud rate for COM ports (without tricks). For the modern PC/laptop Arduino based serial2parallel conversion, way higher baud rates are possible, so that the 1 ms rep rate is not an issue at all. It is a little on the IBM, as 9600 baud, 8N1 need slightly more time than 1 ms to transmit. This would be so cool! I regard LEGO Blockly as powerful and fast programming environment to drive outputs (Interface A+B, and to some extent Control Center I/II), read inputs, and process the data to do something. RCX and the like want to be programmed and then do stuff on their own, but can be regarded as output drivers and sensor data providers as well. The processing of these data are done on the RCX (etc.) though. That is not the case for Interfaces A+B. They require a brain :D All the best Thorsten
  9. OK, I did some more Blockly code testing, as it is right now (last version, @Bliss published). If I understand this entire Interface B/LEGO Blockly combo correctly, we are experiencing the birth of a new power house for LEGO programming in real time. There is the I/O module and the brain. The I/O module, Interface B, has 8(!) sensor inputs serving the original 9V LEGO Mindstorms sensors - and of course the entire suite of either third party or homebrew sensors of this system. And it features 8 9V PWM controlled outputs. The brain is a modern - and thus in every regard superfast computer, as compared to 1993, when Interface B was introduced. Code on the brain thus runs incredibly fast. The link between brain and interface is serial, with hardware supported sensor data encoding on the interface side (raw, touch, clicks, °C/°F, rotation count encoding), running at 9600 baud; which is - I believe - the "reaction time" bottleneck, but this is a fixed given. As far as I am concerned, this is one of the most attractive LEGO vintage HW / modern SW combo I ever worked with. Here is the thing: With a fast serial to parallel converter, speeding up the serial link to HW limits, whatever it is today, there is - again as far as I know - no reason not to use Interface A with LEGO Blockly. And that would be a killer application. Interface A only knows outputs turned fully on/off, but I wonder if is possible, to do PWM as it is done in TC Logo: An interrupt service routine (=task in LEGO Blockly), called every 1 ms to update the 6 PWM outputs on Interface A/read the 2 inputs, and in between, operational code is executed on the computer. That would be another milestone for vintage LEGO HW control. All the best, Thorsten
  10. @Bliss WOW!!! This is more than I and surely others were hoping for! With these additions, LEGO Blocky becomes the most powerful programming language for the Interface B running blistering fast - on modern machines - and platform independent! Crazy. I will be in Northern Germany the next week, but will have the interface B, an RCX with me for testing. I am pretty sure that everything will work perfectly well! Sensing and turning outputs on/off in response is one thing. Having a full-blown, multitasking language in between is something totally different. This is so unbelievably nice!!! All the best Thorsten EDIT: And there is "Yield" - so nice! This actually makes code look pretty. I have such a procedure on all my VB6 programs: Yield to other processes ...
  11. @Bliss And this is >exactly< what I am looking for!!! I saw today (purely arbitrarily - as I was just clicking and pushing around timer and wait blocks - that some code I had on the Blocky page began producing (text) output from two separate blocks! Until then, the program segment located topmost on the page starts and does things (except for functions, they can be placed anywhere and don't interfere). I checked that with 2 loops, only one started. Pushing them around can make the other start. Which seems to be reasonable - and is good to know. However, I did something with separated wait/timer blocks, and suddenly I got output from both (in the end the "program" crashed and was gone ;) I shall just wait then, as the "Task" block will really open up "RCX analog" programming. I believe this will really benefit the Interface B programming as it has 8(!) in/output and this means rather complex LEGO machines/programs can be built. Using asynchronously running "tasks", and not functions, I do see clearly your point; the latter should be synched. Since all variables are global, there is no need for any semaphores or the like; state variables changed by the tasks are readily available to any main loop. I believe. I also do believe in having understood your examples above. It remotely reminds me (again) to the RCX task approach: They need to be started explicitly, and once they are running, they can't be started a second time: They need to be stopped first, before you can start them again. Well maybe what I write is nonsense. And finally: Havings "Task" blocks would be a nice salute to e.g. the LEGO RCX firmware - even in LEGO's ScriptEd, their SCOUT tool, in NQC, RobotC, and so on "tasks" are a central feature. Well, as far as I have used these languages, of course. Right out of habit, I separate output from input data handling (asynchronously) and have a main loop assembling and processing data from/for the tasks. That most probably is considered bad habit, but it worked so far. And when something works - I'm happy . I would also like to thank you very much for taking your time to writing this all up for a dummy like me! All the best Thorsten
  12. @Bliss Nope, it is the other way around! You are the creator of these tools and thus of course the teacher! For some reason, your visual Blockly interface connects with my brain. I don't know why, as I love BASIC, VB6, some "applied C++". NXT's visual wiring system (NI's LabView based) also worked for me, but it sooner than later always crashed miserably when I was trying to run more complex programs. Inline declaration of variables (a NO GO in informatics), automatic variable type conversions (a NO GO in informatics), functions = subroutines = procedures (a NO, OK, we know), THAT is my world. The reason is: My programs are at best "scripts making it work". I don't do real programming. I do use tools others provide, and try to get away with. So far, it worked ;) At least taking a look at divers programming environments gives you a glimpse of what is possible. And then realizing that there are so many "common things". Well, you have encouraged me to try this Blockly route (and you know I was reluctant) - and you were right! All the best Thorsten While we are at it : With Blockly, is it possible running separate "tasks"? This is what I find so extremely powerful and "enabling" on the various PBricks, including the RCX. As mentioned above, on my RCX driven trains run at least three tasks; one is dealing with handling (asynchronously) incoming messages/replies, another does the PID loop, and a third takes care or everything. In the case of Interface B, the sensor/output handling could be one thing, doing calculation, recording times etc., another. I know, it is most probably too much to ask for, but hey, one can try ;)
  13. Well it is absolute >luxury< that it works as it works right now! When I stop my programs (in QBasic ) to just take a brief look at the code, the Interface disconnects and of course has to be reinitialized every time! So I consider any arbitrary disconnect as absolutely normal, and I am every time surprised that it does not anyway. Best Thorsten @Bliss It does look much prettier - and works. Best Thorsten
  14. Initially I thought the same, but just trying things out really helps. I also like the "it looks prettier" very much! Best Thorsten Absolutely! I love it. I did not know that Blockly was also designed for children! That makes absolutely sense then. Of course, type definition and conversion is somewhat elaborate. However, on super computers such as the C64, TI99/4, the Sinclairs or even on an original XT, integer math really speeds things up. I guess, this is far less of an issue today ... good to know. I have no problem at all with all variables being global - you simply have to pay attention. In addition, you are providing powerful blocks, so that messing around with variables and such is much easier. Thank you very much for the clarification - it renders things much more comfortable. Best wishes Thorsten
  15. I see. Does that mean though that in your example "Sensor" is local to the function? If the definition of the input to a function becomes automatically global, then the inputs to a function are not needed at all, as one can simply define the variables outside the function, right? Here is an example, where I use "Sensor" as a global variable; the same for "OutputFwd" and "OutputRev", which I use as text/integer variables. Variables can take on any format, right? Float, integer, string, etc? Furthermore, I believe you mentioned somewhere, that when using the output commands "LEGO B1 out" with a variable other than given in the drop-down list (A-H), you have to use output numbers either as such or formatted as string, e.g., output A = "1", B = "2", or simply 1 and 2 as integers, and so on, right? At least it works that way in the code below: The first two calls to ChangeOutputs work, the third does not: Best Thorsten
  16. @Bliss this is all simply amazing and incredibly nice work! The functions function One more question regarding functions: Lets say I have this block: which does what it should do, but only with the right variable block attached. Is the variable "Sensor_3" only passed to the function when it is explicitly attached to the function block? If so, what does the information "with: Sensor_3" in the function block mean? Ah, I see! Nice! But how would the Blockly program cope with two contradicting data (lets say Sensor_1 on RCX1 says closed, Sensor_1 on RCX2 says open)? I shall break out two fo my RCX and the serial tower ... And finally: With all you really advanced programming knowledge, do you see any change of reviving the USB tower? It needs a 64bit driver ... All the best Thorsten
  17. Yes, the IR remote does also not check for any reply, so it should turn on the respective output of any RCX/Scout in range. My main point is that you can't directly control individual RCX' when there are more than one in IR range of one or more than one IR towers without running a messaging protocol between RCX' and computer. As far as I know. OK, and when pointing towers into different direction of course, so the RCX' do only see one signal source. As said before, I have many RCX and Scouts doing work on my train layout. Each has an IR/RF transceiver on board, and my computer sends 2 byte messages into the ether, but only one of the PBricks will recognize its ID. Best Thorsten
  18. @Gunners TekZone Wait: "All working as one" means that all three RCX' turn their outputs on, when the program says ouput_X on (with no ID), right? According to https://www.mralligator.com/rcx/opcodes.html#set_motor_on_off the RCX reply to an output_X on command is 0xD6/0xDE, which all three RCX' should send back. @Bliss Does your program read back the RCX replies ("receipts"), which they emit after successful instruction submission? In my VB6 programs based on the IVPBrick COM Interface, this issue (arrival of multiple receipts from different RCX') did clog IR traffic. Also, LEGO software (e.g. ScriptEd) does not recognize the replies as they are not synched, and thus assumes something went wrong. Which also means that all three RCX will emit their sensor data upon request at the same time, wouldn't they? I simply don't get how it should work otherwise. Interesting! Best Thorsten
  19. @Gunners TekZone No, they actually don't. Once you send out IR light through the tower, all RCX' will recognize that call and all will reply (depending on which command you sent). This naturally and instantaneously messes up any traffic ... Even with multiple towers, each RCX in range will reply to each tower light emission. See above ... One way to resolve is: SendMessage(byte). There is no inherent RCX reply, when it receives messages. So this is my workaround: As all my RCX' are running programs to do something, be it run a PID controlled train or switching lights on a display on/off, I included a "receive message task" for each of them. Within that task, each RCX has its personal ID (byte value) and knows about individual commands (byte value), provided through defined variables. Example: There are 2 trains, each operated by an RCX. Train1 has ID 200, and train2 201. The defined commands within each RCX program are 1=this, 2= that, and so on. This and that could be increase speed, decrease speed, turn nose light on, etc. So what I send out is: ID (message 1) and action (message 2). This way only the addressed RCX is "doing" something. They all respond, again via messaging, but only the addressed RCX does and the computer control program knows the message came through. Here is an example (from 2010, oh my ...) //********************************************************************************************************************* task receive_message() { /* Message protocol: 2 bytes. Structure of first byte (address byte): Incoming (own) binary Address = 10 XX XXXX; base 192 Outgoing (own) binary Address = 01 XX XXXX; base 160 101 X XXXX = 5 bit (= 32 adresses) range. Structure of second byte (data byte) : See program header. Range is 95 - 1 due to return byte increment. data_byte is incremented in send_error_message to avoid confusion with the tower echo upon error checking in VBasic. Possible errors are: 223 + 1 = timeout; 224 + 1 = C_BUSY; 225 + 1 = invalid data_byte (send_error_message increments databyte). Due to memory shortage on Scout only minimal error checking is implemented. */ while (true) { ClearMessage(); //Flush message buffer. until (Message() == MYID_IN); //Check if Message = MyID (in) = bin_110_X_XXXX, as #defined. ClearMessage(); //Flush message buffer. ClearTimer(0); //Reset timeout Timer(0). while ((Message() == 0) && (Timer(0) < 10)); //Check for timeout after ID detection (Note: hardly occurs under if (Message() == 0) //remote program control). { //Wait for next message or 1 s timeout (100 ms timer slice): data_byte = C_TIME_OUT; //Timeout occurred; just for preventing brick to "hang". send_error_message(); //either send error message timeout or simply restart loop. continue; // } data_byte = Message(); //Message was not 0; load data_byte with message. SNIP BTW, message commands don't need to have the "repeated command" bit flipped. Best wishes Thorsten
  20. @Bliss I am really enjoying your LEGO Blockly programming environment very much! I have a couple of questions and there will certainly be more - is this the right place to ask? I am just starting with a couple, if it is OK Are newly defined variables always global? So when I call a function, does the function know about variables declared in the main program or do I have to pass them to the function (see below)? What is the substitute in Blockly for a subroutine in QBasic, e.g. "ChangeOutputA(value or variable)". Is that done by declaring a function with no output, if there is no return value? I don't understand how the functions function ;) Let's say I have declared the function "ChangeOutputA". There is the "input" feature, which is by default "x". Is x a local variable to the function, that accepts a passed on value by the main program? The function would say: "to ChangeOutputA with x". Can I use x within the function? Here is an example: When I have this on the UI, and press "Run", it does not work, no outputs are turned on/off. The right function is just on the UI, it is not called, nor does it have a proper name etc. It is just sitting there "in preparation". This is what I usually do in Basic: Write some subroutines, but never call them. The main loop does what it has to do. When I drag the entire function into the trash bin, so only the left loop is on the UI, and then press "Run", it works fine. What am I missing? I bet it has to do with how Blockly wants the blocks arranged? Or do I need to declare a "main" program, so the Blockly knows where to go when pressing "Run"? Thank you very much and all the best, Thorsten
  21. Here is what I do: Once I have programmed a (test)version of any program (with 9751 turned off/lost connection), I save the programit, turn 9751 on/reconnect, load the last program saved and all "No LEGO B" change automatically back to "LEGO B1". Best, Thorsten Yes, and it is used to send back the output commands to the interface. In essence, it just replaces a serial cable: (Win11+built-in BT) <-> (BT2TTL adapter + TTL2Serial adapter). I also have this BT2Ser adapter with no need to do extra TTL2Ser conversion, works as well. Best Thorsten
  22. So nice - update worked with one mouse click! Regarding Control Center I/II (CC): Essentially it is a "closed" Siemens 680X microcontroller driven three 9V output (with no sensor inputs) device, which is recording output activation/deactivation sequences including the pauses in between. There are two programming slots and a total of some 50 steps. It has two keys A/B for output A (fwd/rev) and a yellow dial type button, which can activate any two outputs B/C in fwd/rev direction. @amine had the really cool idea of using CC's three outputs (ABC) connected to any three 9751 inputs as some sort of "key pad", and then record these key sequences. This way, 9751 is mimicking CC, but with way more programming steps available, in addition to program storage. CC can only hold one or two programs internally. Here is one thread on EB, there is so much more out there! @amine's case is special - but nicely aligning with the idea of using old LEGO programmable devices with either old or modern computers. Best Thorsten
  23. @Bliss it IS really like that. It took me about 30 min from "installing" your standalone version (it is really just clicking on "download" on your website and double-click the newly crated desktop shortcut icon), connect to Interface B (which was a mouse click), getting familiar with the environment, left/right mouse buttons, the gear icon, trash bin, and - beginning programming! As said, I looked into the Control Lab (DOS) software - this must have been a blast (and for me still is today) back in the 1990's, as it creates a graphical UI and unleashes the programming power of Logo. However, the Logo program control flow was hard to grasp - for me that is. Interface B (9751) is "just" an 8-channel output driver and an 8-channel sensor (raw and encoded) data provider. So is - partly - Interface A (9750). The big difference is that 9751 spits out the sensor data, like it or not, an 9750 wants to be polled. And of course serial vs parallel is another big challange on vintage machines. In other words: Computer control of 9751 (for me) was so far reading input data and pressing buttons to operate the outputs using QBasic. The real power of any input/output device is the "controller" in between. Which is in case of 9751 and 9750 the connected computer. And which is different for PBricks, as they want to be programmed to take over the controller task. This has now totally changed, as I can use 9751 as a controlled (via your software) device. That is so unbelievably cool. I believe it is the right way to do! This is how it is done elsewhere. The user can decide, when the UI/program needs to breathe! There should maybe a hint in doing so. But I have crashed so many programs on Arduinos and ESPs simply by cutting off their breathing ... That would make things easier, as this is a frequently encountered situation, when working with raw input data. I am aware that "automated" on/off values are making things easier, but there are so many hardware issues that may happen: Touch sensor contacts simply age. Never to the extent that they don't work anymore, but to the extent that built-in software thresholds for on/off with hysteresis shift so much, that they seem not working anymore. This is why I prefer the raw data ("value" in your code) mode for sensors whenever feasible. It is more flexible. I am testing like a maniac - as I am simply so positively fired up! I added the good old "Sensor_2_old" variable (as I do in so many of my QBasic programs to avoid loop execution if not required): If var_old != var then var_old = var do something using var (or var_old) else wait some time endif This reduces traffic on the serial bus (output data) - which may not be any issue on modern computers but frequently is on vintage machines ... Yes and yes. The BT adapter is a simple HC05 + TTL to serial adapter duo (out of 3 that I am using with my LEGO interfaces in addition to a BOLUTEK BT to serial adapter) - they are all nicely lining up in the "connect" dialogue window of your Blockly UI. It is so easy to connect to any of them!!! You know, they are certainly not sufficient, but what should I say: I really believe that I am dreaming! All the best and thank you very much for creating this programming environment Thorsten
  24. @Bliss For me, this is a dream coming true!!! For the very first time, I have successfully "programmed" Interface B - and this was done using your Blockly app, which I downloaded an hour ago as per your instructions. So far I have just trying things out with LEGO's Control Lab software without getting anywhere - the learning curve there is rather steep - for me. I am also simply not good with Logo ... something in my brain refuses to grasp the logic. Well I guess more frequent programming hours and Logo will become logic as well; after all, all programming languages share at least some of the same logic However, the principle logic behind your Blockly code just connected directly to my brain ... I will have a lot to learn, but this is fun. It is just amazing when realizing how elegant and easy it is to get it going! Instead of generating a "Hello world" printout or having the program count from one to one hundred, I made a very simple program, that monitors input B of 9751 and then turns on/off the outputs B and F (as they are in one "column"). In fact, I was doing that using my Control Center II (CC, red output operated by keys A and B) connected with my lill opto coupler interface as briefly described here (this is @amine's idea!): This is "My First 9751 Program" using your code - please bear with me, it is certainly horrible, but it works: This program turns on/off 9751's outputs B and F depending on the raw data value at input 2: When I press button A on Control Center (CC), 9751's output B is turned on, and F off. Button B on CC turns output B on 9751 off and output F on. No button pressed on CC = both outputs B/F on 9751 off. I do visualize this with 9V lamps, this is why I use two 9751 outputs (B is for fwd, F for rev). This is not necessary when "recording" CC key sequences; this is what @amine is looking for, I believe: Storing longer than 50 or so programming steps for a CC model operated with 9751, but using the CC as keypad with is nice big yellow dial and two A/B buttons. @amine you'll love this, it works like a charm! @Bliss For now only one question: When I do not include the "wait 0.001" seconds at the end of the "repeat while true" loop, the program stalls at once. This is absolutely normal behavior, right? With that delay, the response of pressing buttons A/B on CC and B/F lights going on/off on 9751 is almost immediately, this is so impressive!!! The input data have to be received over the BT serial line, processed, and the response has to be sent back over the same connection! Wow. Thank you very much for sharing this phenomenal achievement!!! All the best Thorsten
×
×
  • Create New...