Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using several Lpf2Hub instances possible? #54

Open
fredlcore opened this issue Mar 9, 2021 · 4 comments
Open

Using several Lpf2Hub instances possible? #54

fredlcore opened this issue Mar 9, 2021 · 4 comments

Comments

@fredlcore
Copy link
Contributor

fredlcore commented Mar 9, 2021

First of all, I'm not sure if this is a doublette of #46 - if so, feel free to close this right now.
I'm trying to connect my ESP32 to three Lego Duplo trains. The way I'm doing this is that I setup an array of Lfp2Hub objects like this:

#define HUBS 3
Lpf2Hub* myHubs[HUBS];
Lpf2Hub* myHub;

and then send all of them into init mode in setup():

  for (int x=0; x<HUBS; x++) {
    myHubs[x] = new Lpf2Hub;
    myHubs[x]->init();
  }

Subsequently, I can cycle through them in a for-loop:

  for (int hub=0; hub<HUBS; hub++) {
    myHub = myHubs[hub];
    if (myHub->isConnecting()) {
      ...
    }
  }

However, this only works for the first train to be connected, and this will always be the last element of the myHubs array (2 in this case). Also, once the first connection is made, any subsequent train that is turned on won't connect.

After reading #46, I was wondering if this also has to do with the blocking-/non-blocking approach. But if changing to a blocking model would be necessary to connect multiple hubs, wouldn't that mean that I'd have to a) define how many hubs I want to use and b) make sure that all of these hubs are connected before the code will continue to execute? Because that's what blocking means, isn't it?
My goal would be that my kids can decide whether they put 1, 2 or 3 trains on the track and all active ones could be controlled (I would use the PS3 controller's "SELECT" button to switch between them). However, it seems that with blocking mode, they would have to always use the same number of trains, wouldn't it?

@corneliusmunz
Copy link
Owner

Hi @fredlcore! Connecting to multiple hubs is defenitely possible. Up to now you can have a connection to up to 9 hubs from one esp32. If you want to use more than three hubs, you have to configure the NimBLE-Arduino lib according to the followin procedure: https://github.com/corneliusmunz/legoino#connection-to-more-than-3-hubs

You can find ab example of connections to multiple hubs in the following sketch:
https://github.com/corneliusmunz/legoino/blob/master/examples/MultipleTrainHubs/MultipleTrainHubs.ino

Now the issue #46 comes into place. Adding the non blocking scan has some benefits but also some drawbacks and you can "remove" the non blocking change by changing the following line in the Lpf2Hub.cpp file:

Non blocking scan start: pBLEScan->start(_scanDuration, scanEndedCallback);

Change to blocking scan start: pBLEScan->start(_scanDuration);

With this change the connection procedure should work for multiple hubs and you can check for each hub instance if it is connected with the myHub.isConnected() method. If you know the Hub Ids, you can specifically connect to a known id and can map that to a specific instance

myTrainHub1.init("90:84:2b:03:19:7f"); // initialize the listening train hub 1 // here you have to use your own device ids

You can find an example in the TwoTrainHub.ino sketch

@fredlcore
Copy link
Contributor Author

fredlcore commented Mar 10, 2021

Thanks for the detailed feedback!
I'm not sure if I understand the blocking/non-blocking matters correctly, but looking at the code in MultipleTrainHubs.ino, I'm wondering whether it is not possible to send all three inits at the same time, like I did here: https://github.com/fredlcore/PS3-Lego-Duplo-Train-Control/blob/08bd8fa5e5a7657427cfdf943890201ffecae241/DuploTrainControl/DuploTrainControl.ino#L124-L127
Or is it a must that any subsequent inits can only be started after there has been a successful connection with the previous init?

The reason why I would like to do this with an array of Lpf2Hub objects is that it is easily scalable. So it does not matter whether it's one, two or three hubs one is using (or up to nine with the changes you mentioned above). And it would not require the nested if blocks etc. But maybe that's the reason why yours is working and mine is not.
So in case you'd have the time to look at my code, I'd really appreciate it!

@fredlcore
Copy link
Contributor Author

fredlcore commented Apr 5, 2021

I just figured out the reason why my code was not working properly: I assumed that after issuing an init(), the scan would continuously run until a connection was made. In all these tests, it probably took me more than 10 seconds (the defaul scan duration) to start both Duplo trains, so only the first one got connected. Now that I re-issue init() every 11 seconds, it works and I can control both trains. Working with an array in that respect makes this matter easily scalable and also does not require one to do nested ifs etc.

@fredlcore
Copy link
Contributor Author

@corneliusmunz: I now found a solution that works with non-blocking scan and gives you the freedom to initialize up to nine hubs without adding extra code - just by going through a loop using an array:

#define HUBS 3
for (int x=0; x<HUBS; x++) {
  myHubs[x] = new Lpf2Hub;
  myHubs[x]->init();
}

Later on, in the loop() function, I can use this to both execute individual code for each train as well as restart scanning after the initial scanning period is over, so that any disconnected device can easily reconnect:

for (int hub=0; hub<HUBS; hub++) {
  myHub = myHubs[hub];
  if (myHub->isConnected()) {
... *Do train control stuff here* ...
  } else { // not connected anymore? Then put this instance in scanning mode again
    if (myHub->isScanning() == false && myHub->isConnecting() == false && myHub->isConnected() == false) {
      myHub->init();
    }
  }
}

Maybe this is an (easier) option for your TwoTrainHubs or MultipleTrainHubs examples as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants