corneliusmunz / legoino

Arduino Library for controlling Powered UP and Boost controllers
MIT License
257 stars 34 forks source link

Example to directly control Duplo train? #52

Closed fredlcore closed 3 years ago

fredlcore commented 3 years ago

First of all: Thanks for this great library! I'm relatively new to these "new" Lego Duplo trains and was looking a way to control them via my ESP32 instead of the Lego App. I'm just a bit confused about the concepts of "(Train)Hubs" and therefore not sure which example I could use as a starter to control our son's Duplo train to make it drive forward/backwards/stop/fill up etc. Also how to figure out how to specify which of the trains should be the target of communication (we have two trains) would be important I guess.

If there are any examples that already exist that do (part of) what I'm looking for, I'd be happy if someone could point me towards it. Otherwise, if someone has already used it in this conjunction and could provide an example, that would also be great.

Thanks a lot!

fredlcore commented 3 years ago

I managed to adapt "DuploTrainBase.ino" and it generally works. However, while I receive the speed via parseSpeedometer(), I realized that neiter setBasicMotorSpeed() (and probably also stopBasicMotor() ) work. The port variable is defined as DuploTrainHubPort::MOTOR - is this the correct/only value possible or can I try other ports? Since it's possible to control the speed via the app, I assume that I don't send the correct value to the train?

fredlcore commented 3 years ago

Ok, it seems that the value is correct because every once in 10 tries, it works. I experience the same erratic behaviour with playing the sounds of the train. The only thing that works reliably is changing the color of the LED. This is the code-snippet I'm using in the DuploTrainBase.ino example after myHub.isConnected():

      delay(200);
      // connect color sensor and activate it for updates
      myHub.activatePortDevice((byte)DuploTrainHubPort::SPEEDOMETER, speedometerSensorCallback);
      delay(200);
      // connect speed sensor and activate it for updates
      myHub.activatePortDevice((byte)DuploTrainHubPort::COLOR, colorSensorCallback);
      delay(2000);
      Serial.println("Moving...");
      myHub.setLedColor(GREEN);
      myHub.playSound((byte)DuploTrainBaseSound::HORN);
      myHub.setBasicMotorSpeed(motorPort, 50);
      delay(5000);
      myHub.setLedColor(RED);
      myHub.playSound((byte)DuploTrainBaseSound::STATION_DEPARTURE);
      myHub.setBasicMotorSpeed(motorPort, -50);      
      delay(5000);
      myHub.setLedColor(GREEN);
      myHub.playSound((byte)DuploTrainBaseSound::STEAM);
      myHub.stopBasicMotor(motorPort);
      delay(5000);
      myHub.setLedColor(RED);
fredlcore commented 3 years ago

Ok, I think I found the cause of the problem. It seems that some commands are not received correctly by the train, and interestingly some kind of commands more often than others. Changing the LED seems to be quite reliable while controlling the motor not so much. What I did now is to send each command 10 times in a for-loop. The only case where this is not feasible is when playing the sounds of the train because they will be started several times and/or interrupting each other.

Does the train by any chance send a response whether the command was received? If this was the case, it would be easy to just send the command until a confirmation is received. If not, then I'm a bit lost how to deal with this problem...

fredlcore commented 3 years ago

The 10-times for-loop has proven to be mostly reliable (a few drops here and there, but I guess that's fine). I have now written a small train control sketch which can be accessed via the Arduino IDE's serial monitor which I attach to this issue. Feel free to add it to the examples if you like, I'd be honored :). Thanks a lot again for this great library!

DuploTrainControl.ino.zip

corneliusmunz commented 3 years ago

Hi @fredlcore Sorry for the late delay and many thanks for your feedback! You have found the correct Example sketch DuploTrainBase.ino 👍 Cool idea to control the Train via the IDE's serial monitor. I will test it on my side and try to add it in the next release. So thanks for that contribution.

Regarding the loop of commands i have some concerns. Normally the BLE connection is quite fast but if you flood it with messages the command queue on the hub will maybe overflow. For other Motors of the Lego PoweredUp universe (e.g. Large Technic Motor) there exists some feedback mechanism to be informed if the command is executed properly. But i have not found it for the Basic Motors and i have even not implemented it for the larger Motors. So i will try it out at home with my Duplo Train why it does not respond to each command. I have seen this before for the sounds (as you have also figured out) but i have not seen this behaviour for the motors.

So i will give it a try and give you feedback

fredlcore commented 3 years ago

Thanks for the feedback, @corneliusmunz, I'm now using a workaround that I will send the speed parameter periodically every 100ms, so it's not flooding too much but also fast enough so that dropped commands will not likely be noticed. The problem remains with changing the lights and sounds because you can't continually send these commands. OTOH, I have not experienced problems with an overflowing hub (or at least I didn't notice).

One other solution I had in mind was to compare the desired speed with the speed measured through parseSpeedometer(), but the two values don't seem to be comparable because the latter sometimes is three times as high as the desired speed.

I'm also wondering if the dropped packages have to do with my ESP32-NodeMCU because I saw this problem mentioned in one the other issues here. But then it should be a problem with all commands, not just a specific type, shouldn't it?

yschroeder commented 7 months ago

In case someone ends up here and is puzzled about the retry idea to make it more reliable. The actual fix is discussed here: https://github.com/corneliusmunz/legoino/issues/44