Recommended Posts

I am very happy about all the feedback and contributions which take the library to that step. Today version 1.0.0 of the legoino library is released! 

After over a year of learnings and feedback i have reworked the library to be more consistent and to make some things easier. Unfortunately this was not possible without breaking changes. This means some functions and methods has to be removed or renamed.

To make the migration of your sketches easier, just have a look into the Migration guide provided on the github project page: Migration guide

New features

  • Duplo Train support
  • Enriched Motor commands (maxPower, brakingStyle)
  • Support of setAbsoluteMotorPosition, setAbsoluteMotorEncoderPosition
  • Callbacks for changes on hub properties and sensor values
  • PowerFunction (IR) functions included
  • Hub Emulation (powered up to powerfunction translator)
  • Adding of getHubName
  • rework of log messages to the standard log_d, log_w, log_xx messages. Log levels could now be switched via the Arduino environment

 

Contribution

I am very happy about the whole community who participates in that library and contributes with ideas and your cool projects that uses the legoino library. If you have any questions, ideas or need help, you can just contact me.

Looking forward to all the cool stuff you are building with the new version of the library.

Cheers,

Cornelius

Share this post


Link to post
Share on other sites

Hi Cornelius,

welcome to EB!

I am so glad you're here. Working with your software for some time now - it is incredible - has made me so happy. Learned about ESP32's, and the really flawless operation with the PUp devices I have.

Now I am really looking so much forward to install 1.0.0 of Legoino. Will take some time as the virus keeps me a little busy ... but I bet it will make the difference.

Thank you very much for doing all your work for the LEGO community.

Best wishes,
Thorsten

Share this post


Link to post
Share on other sites

Hi Cornelius,

Im just getting into the arduinos and controlling lego trains. I recently bought the mega 2560 with the HM-10 Bluetooth module. Would this be compatible with your library?

Share this post


Link to post
Share on other sites

Folks, sorry for necro-bumping this thread.

I tried to PM Cornelius to no avail. Guess the 10 msgs thing is trapping this - or @Cornelius is not frequently checking in.

Maybe others know as well, though ...

OK the thing is: I believe an ESP32 fitted with Cornelius latest Legoino software (1.1.0) may replace the NXT bricks + HiTechnic IR receivers on my layout (both have abandoned their LCD screens - yes there are fixes, I know, but ...). I am using the NXT for capturing "train IDs" broadcasted by my VB6 (and more recently a 1985 ZX Spectrum BASIC;)) control program, and translate the corresponding "speed data byte" submitted subsequently to PF IR code via the HiTechnic sensor. Now, the PF IR signals are - as usual for LEGO stuff - 38 kHz modulated. So far so good.

Tested the Legoino PF features, all good (IR LED via resistor on selected pin of an ESP32 board bolted to GND). However, the pin signal 38kHz modulated. I just need the pure non-modulated "PF data signal". Does anyone know if this is the right place to hack? The file is PowerFunctions.cpp in the Legoino/src directory:

// Send a bit
void PowerFunctions::send_bit()
{
  for (uint8_t i = 0; i < 6; i++)
  {
    digitalWrite(_pin, HIGH);
    delayMicroseconds(PF_HALF_PERIOD);
    digitalWrite(_pin, LOW);
    delayMicroseconds(PF_HALF_PERIOD);
  }
}

I would simply set the second "_pin, LOW" to "_pin, HIGH" and then add "digitalWrite(_pin, LOW) after the loop, before exiting. The pin should then be high for the duration of the signal. That goes into an OOK RF transmitter, is received by an OOK RF receiver and fed into the PF receiver. I know that latter part works.

Does that software hack make sense? I know, I can try - but C++ is as far away from BASIC as Earth from Alpha Centauri (where the home of the Galactic Hyperspace Planning Council is - and you all know what that means!).

Best
Thorsten

Share this post


Link to post
Share on other sites

Yes, it works:

// Send a bit non-modulated ------------------------------------------------------
void PowerFunctions::send_bit()
{
  //Changed here to send 6 cycles of 38kHz as 1 high signal to be fed into TXM OOK
  digitalWrite(_pin, HIGH);
  delayMicroseconds(12 * PF_HALF_PERIOD);
  digitalWrite(_pin, LOW);
}

This signal is of course as long as 6*PF_HALF_PERIOD (HIGH) + 6*PF_HALF_PERIOD (LOW).

When I feed this data line into a LINX TXM433 on-off-keyed (OOK) RF transmitter, a LINX RXM (OOK) RF receiver recreates that signal - and that can be plugged in to my modified RF receivers:

 

Alternatively, the RXM receiver output can be re-modulated to original PF IR with any 38kHz signal source (e.g. an Arduino) + an AND gate (or two NAND gates, or so many other things ;))

So again, sorry for necro-bumping this thread.

Legoino rocks, though :pir-huzzah2:.

Best
Thorsten

 

Share this post


Link to post
Share on other sites

OK, again, sorry for bumping this topic, but this is "the" Legoino-thread, isn't it?

Let's assume it is :pir-wink:

I have a question regarding the Legoino library (1.1.0) running on a JoyIt ESP32 nodeMCU, programmed with the Arduino IDE. All is good - except using "tacho" motors (in this case a PUp L-motor) in "speed" mode:

      TrainHub180.setAccelerationProfile(port180A, 5000);
      TrainHub180.setDecelerationProfile(port180A, 5000);

doesn't change the "behavior" of the L-motor, when calling

TrainHub180.setTachoMotorSpeed(port180A, PercentSpeed, 100, BrakingStyle::BRAKE);

it just jumps to full speed for PercentSpeed = 100 and breaks after sending 0 as speed, as a "dumb" motor would do.

According to the LPW3.0 protocol, up-to 8 profiles can be used; the command is "SetAccTime (Time, ProfileNo)" and then applies to all motor commands): "The selected profile will be used in all motor based commands if the UseProfileFlag is set TRUE. The Time and Profile Number set for the profile is ignored if the UseProfile-Flag is set FALSE."

According to the LPW3.0 protocol, the tacho motor command is:  "StartSpeed (Speed, MaxPower, UseProfile)"

It can very well be that Legoino always uses "profile 0" and always has the UseProfile flag set to 1 when using tacho motor commands.

Has anyone encountered this problem as well? Maybe @Lok24? I believe @Cornelius is not on this board anymore.

Thanks a lot and best wishes!

Thorsten

 

Share this post


Link to post
Share on other sites
On 10/19/2020 at 9:29 PM, Cornelius said:

I am very happy about all the feedback and contributions which take the library to that step. Today version 1.0.0 of the legoino library is released! 

...

Cornelius

Hello,

What in the LIB has to be updated to work also on a Arduino Nano 33 BLE (using a nRF52840 ) ?

Is there planned an update to support also :

  • Spike Essential
  • Brick to Brick Comminication (by BLE Advertising Broadcast)
  • Luigi Brick
  • Motors & Sensors from Spike & Inventor Sets

Jo

Share this post


Link to post
Share on other sites

Hello, I am the Necro Bumper :pir-skel:

I found the answer to my question above about the weird behavior of the

myTrainHub.setTachoMotorSpeed(port, speed, maxPower)

function. I have no clue, but are you using Legoino at all @Lok24 anymore? I believe you have migrated to PyBricks, right? I am still excited about Legoino and the things you can do with this software.

It appears as if there are two little bugs in Legoino library "LPF2Hub.cpp" file, which need to be edited before it works:

(1) For the setTachoMotorSpeed function in Legoino, @Cornelius used accidentally the sub-command 0x01 (StartMotorPower) but not the required 0x07 (StartMotorSpeed) sub-command of the LWP3.0 Output Command 0x81. Also, the sub-command 0x07 does not recognize any BrakingStyle::FLOAT/BRAKE, as it can't go to 0% speed; the minimum is 1%. I believe the speed regulating algorithm in the Hub's firmware does not like to go to zero, as it can't regulate anything at 0. This is also noted in TLGs (outdated!) LWP3.0 document on GitHub:
" If FLOAT or BRAKE should be used e.g. when a slider is set to 0 (zero) the user has to use either StartPower(0 or 127)."  Note: StartPower (0x01)

I believe it is generally a good idea to clearly separate "power" and "speed"; it makes things much clearer. As far as I know, the former works for all PUp motors, the latter naturally only for "TachoMotor", e.g. the PUp L motor etc.

(2) The Legoino "stopTachoMotor(port)" function calls the "setTachoMotorSpeed" function with the argument speed = 0. As dicussed, this can't work. Instead, in Legoino setBasicMotorSpeed(port, 0) must be called to stop the motor. The 0 corresponds to "0 power with brake"; when setBasicMotorSpeed(port,127) is used, this corresponds to "0 power with float".

With these two changes in LPF2Hub.cpp, all the motor output functions (power, speed, speed for time, speed for degrees ...) work perfectly fine!

Here is my messing with LPF2Hub.cpp in that section; it begins around the line 1220:

/**
 * "setBasicMotorSpeed" works; should be renamed to setBasicMotorPower though
 * Many (minor) changes in the following, one bug, some unknown settings as marked
 *
 * From the LPW3.0 protocol:
 * 3.27 Motor Output Command 0x81 - MotorSubCommands [0x01 - 0x3F]
 * StartPower: 0x81, Sub command 0x01                Encoding: WriteDirectModeData
 *             int8_power: Power                     int8_power: 0=FLOAT; 127=BREAK; -1%-100%=255-128; +1%-+100%=1-126;
 *        
 *        Byte|  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 |
 *  SetPower  | 07 | 00 | 81 | ID | 00 | 01 | PWR|
 *  SetPowerAB| 08 | 00 | 81 | ID | 00 | 02 |PWR1|PWR2|
 *  SetSpeed  | 09 | 00 | 81 | ID | 00 | 07 | SPD|MPWR|PROF|
 *  SetSpeedAB| 0A | 00 | 81 | ID | 00 | 08 |SPD1|SPD2|MPWR|PROF|
 *
 *  Byte 1: Length of message
 *       2: Always 0
 *       3: Command
 *       4: Port ID, supplied by hub for virtual ports upon connection
 *       5: 2 Startup/completion 4bit-nibble: ssss cccc; 0x00=0000 0000: buffer if necessary, no feedback
 *          used here: 0x11=0001 0001: Execute immediately, status feedback
 *       6: Subcommand
 *       7: See table, depends on subcommand, SPD=speed; MPWR=max power for controlling speed, PROF=use profile.
 *       8:  -"-
 *       9:  -"-
 *      10:  -"-
 *     
 *    PROF: 0000 0000=none; 0000 0001=use acc profile; 0000 0010=use dec profile; 0000 0011=0x03=use both.
 *          All use profile combinations have been tested and work; in this library, profiles are always used.
 *          The default profile upon hub start-up is acc/dec time=0, which is use no-profile behavior.

 
/**
 * @brief Set the motor >power< on a defined port. 
 * @param [in] port Port of the Hub on which the >power< of the motor will set (A, B)
 * @param [in] speed Power of the Motor -100..0..100 negative values will reverse the rotation
 */
void Lpf2Hub::setBasicMotorSpeed(byte port, int speed = 0)
{
    //byte setMotorCommand[8] = {0x81, port, 0x11, 0x51, 0x00, LegoinoCommon::MapSpeed(speed)}; //train, batmobil
    //CHANGE: startup/completion=0x00 (buffer when necessary, no feedback); motor command 0x01 "setPower"; setMotorCommand array length
    byte setMotorCommand[8] = {0x81, port, 0x00, 0x01, LegoinoCommon::MapSpeed(speed)}; //train, batmobil, and others
    WriteValue(setMotorCommand, 5);
}

/**
 * @brief Stop the motor on a defined port.
 * @param [in] port Port of the Hub on which the motor will be stopped (A, B)
 */
void Lpf2Hub::stopBasicMotor(byte port)
{
    setBasicMotorSpeed(port, 0); //0=BREAK or 127=FLOAT: Tested, both work. Could be an option in Legoino.
}

/**
 * @brief Set the motor >speed< on a defined port 
 * @param [in] port Port of the Hub on which the speed of the motor will set (A, B, AB)
 * @param [in] speed Speed of the Motor -100..0..100 negative values will reverse the rotation
 */
void Lpf2Hub::setTachoMotorSpeed(byte port, int speed, byte maxPower, BrakingStyle brakingStyle)
{
    //Use acc and dec profile (0x03 last two bits set)
    //In the original file, the wrong motor subcommand is used (0x01 = set power):
    //byte setMotorCommand[8] = {0x81, port, 0x11, 0x01, LegoinoCommon::MapSpeed(speed), maxPower, (byte)brakingStyle, 0x03};
    //The set power subcommand does not have a braking style, as it can't go to 0 as argument. Motors need to be stopped with
    //set power subcommand 0x01 with BREAK (power=0) or FLOAT power=127) 
    byte setMotorCommand[7] = {0x81, port, 0x00, 0x07, LegoinoCommon::MapSpeed(speed), maxPower, 0x03};
    WriteValue(setMotorCommand, 7);
}

/**
 * @brief Stop the motor on a defined port.
 * @param [in] port Port of the Hub on which the motor will be stopped (A, B, AB, C, D)
 */
    //There is no "set power = 0" for the sub-commands 0x07 and 0x08. Use set power=0(BREAK)/127(FLOAT) instead 
void Lpf2Hub::stopTachoMotor(byte port)
{
    //setTachoMotorSpeed(port, 0);
    //Tested, works
    stopBasicMotor(port);
}

I will try to get in touch with Cornelius either on his GitHub Legoino repository or elsewhere.

For now all the best,
Thorsten

 

   

Edited by Toastie

Share this post


Link to post
Share on other sites

Hi,

yes I'm not working with ESP any more, cause interest in programming some "libs" was zero,  and this issue was not successful:
https://github.com/corneliusmunz/legoino/issues/38

I have a bunch of "useful" routines for that all, including webserver, read/write parameters  and so on.

As I saw you opend an issue, lets see what happens.

 

 

Edited by Lok24

Share this post


Link to post
Share on other sites

Just a heads-up:

Cornelius has replied on GitHub and will have a look over the holidays, if his time allows that.

Best,
Thorsten

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.