Lok24 Posted July 9, 2023 Author Posted July 9, 2023 Sorry, perhaps a missunderstanding,I removed it (as far as I remember) when it did'nt work any more, and I had no time to look for the problems. 5 minutes ago, Marlow said: I would have thought, that that is the best way to distribute it and also to gather all bugs/bugfixes/suggestions in one place, Yes, that's why I published it there, an there was no feedback at all about bugs, suggestions or something. And again I have no idea why it did not work again now ;-) Assume something like motor(port). ..... Latest Version was MotorControl2_9.py from January 2023. Quote
Marlow Posted July 9, 2023 Posted July 9, 2023 (edited) 8 minutes ago, Lok24 said: And again I have no idea why it did not work again now ;-) Assume something like motor(port). ..... The initial fix for it to run on firmware 3.2 according to @and_ampersand_and was to comment out line 255: " Motor(port).control.limits(speed=dspeed,acceleration=10000) " That's the only line that fails in that script. Obviously, it has some sort of purpose, so a remedy should be found for that using the 3.2 codebase. And it only fails for technic motors, not for train motors. The script continues to work perfectly in 3.2 and 3.3beta, if one uses train motors without changing that one. With that change, all motors work. /M Edited July 9, 2023 by Marlow Quote
Lok24 Posted July 9, 2023 Author Posted July 9, 2023 Thanks, as assumed, the motor(port) command, which was not supported any more. The block looks like that: devs_max_speed = {38:1530,46:1890,47:1980,48:1367,49:1278,75:1367,76:1278 } dspeed = devs_max_speed.get(PUPDevice(port).info()['id'], 1000) motor[i].obj.stop() motor[i].obj.control.limits(speed=dspeed,acceleration=10000) motor[i].setSpeed(dspeed/100*0.9) Seems that you use 2.7 which is not the latest Version.... Have a look: # ----------------------------------------------- # MotorControl # # uses https://code.pybricks.com/ , LEGO City hub, LEGO remote control # connect 1 or 2 motors of any kind to Port A and/or B # # Version 2_9 # -----------------------------------------------/ from pybricks.parameters import * # Color # ----------------------------------------------- # Set user defined values # ----------------------------------------------- # define the two profiles # profil_x = (minimun speed,maximum Speed,accelerate in steps of ..., wait for next acceleration(in ms) Profil_A = (20,100,10,100) #min,max,step,acc Profil_B = (10,500,5,200) #min,max,step,acc # define direction of motors dirMotorA = 1 # Direction 1 or -1 dirMotorB = -1 # Direction 1 or -1 autoacc = False # accelarate continously when holding butten # ----------------------------------------------- # Set general values # ----------------------------------------------- # assign buttons to function1 # syntax: function = "name" # name may be "A+","A-","A0","B+","B-","B0","CENTER" UP = "A+" DOWN = "A-" STOP = "A0" SWITCH = "CENTER" mode=1 # start with function number... watchdog = False # "True" or "False": Stop motors when loosing remote connection remoteTimeout =10 # hub waits x seconds for remote connect after starting hub remoteName = "" # connect this remote only # Color and brightness of Hub LEDs LEDconn = Color.GREEN*0.3 # if Hub connected, color * brightness LEDnotconn = Color.RED*0.5 # if Hub is not connect, color * brightness LED_A = Color.GREEN*0.3 # Remote Profil_A, color * brightness LED_B = Color.RED*0.5 # Remote Profil_B, color * brightness # ----------------------------------------------- # Import classes and functions # ----------------------------------------------- from pybricks.pupdevices import DCMotor, Motor, Remote from pybricks.parameters import Port, Stop, Button, Color from pybricks.hubs import CityHub from pybricks.tools import wait, StopWatch from pybricks.iodevices import PUPDevice from uerrno import ENODEV # ----------------------------------------------- # function 1 / drive motors # ----------------------------------------------- def function1(): vmax = profile[mode].vmax vmin = profile[mode].vmin accdelay = profile[mode].acc step = profile[mode].step global v if CheckButton(UP) and not CheckButton(STOP) : for x in range (1, step + 1): v = v + 1 if v > vmax : v = vmax if v > 0 and v < vmin: v = vmin if abs(v) < vmin: v = 0 drive() wait (accdelay) if v==0: break # further acceleration if button keeps pressed while autoacc == False and CheckButton(UP) : wait (100) # avoid changing direction when reaching "0" while v == 0 and CheckButton(UP): wait (100) if CheckButton(DOWN) and not CheckButton(STOP): for x in range (1, step + 1): v = v-1 if v < vmax*-1 : v = vmax*-1 if v < 0 and v > vmin*-1: v = vmin*-1 if abs(v) < vmin : v = 0 drive() wait (accdelay) if v==0: break # further acceleration if button keeps pressed while autoacc == False and CheckButton(DOWN) : wait (100) # avoid changing direction when reaching "0" while v == 0 and CheckButton(DOWN) : wait (100) if CheckButton(STOP): v = 0 drive() wait (100) class setprofile(): def __init__(self,pr): self.vmin=pr[0] self.vmax=pr[1] self.step=pr[2] self.acc=pr[3] profile = [0,0,0] profile[1] = setprofile(Profil_A) profile[2] = setprofile(Profil_B) # ----------------------------------------------- # function 2 # ----------------------------------------------- ''' def function2(): if CheckButton(UP): timer[1].set(3000) if timer[1].check(): print("Do something") ''' # ----------------------------------------------- # general program routines and classes # ----------------------------------------------- # ----CheckButton ------------------------------------------- def CheckButton(x): try: button = remote.buttons.pressed() if x == "A+" : x = Button.LEFT_PLUS if x == "A-" : x = Button.LEFT_MINUS if x == "A0" : x = Button.LEFT if x == "B+" : x = Button.RIGHT_PLUS if x == "B-" : x = Button.RIGHT_MINUS if x == "B0" : x = Button.RIGHT if x == "CENTER" : x = Button.CENTER if x in button: return True else: return False except: return() # ----delay ------------------------------------------- class delay: def __init__(self,id,time=0,watch=StopWatch(),busy=False): self.id=id self.time=time self.watch=watch self.busy=busy print ("Init Timer",id) # set a timer def set(self,x): if self.busy == False: self.busy = True self.watch.reset() self.time = x print("Timer",timer[1].id, "set to",x) #check if timer is reached, then return "True" def check(self): if self.busy == True: if self.watch.time() > self.time: self.busy = False self.time=0 print("Timer",timer[1].id, "stopped") return(True) else: return(False) # ----drive ------------------------------------------- def drive(): global vold global v print (v) if vold != v: # for each motor 1,2 for x in range(1,3): # set speed and direction s = v*round(motor[x].getDir()) # real motor commands depending on motor type if motor[x].getType() == "Motor" : motor[x].obj.run(s*motor[x].getSpeed()) # in 2.7 if motor[x].getType() == "DCMotor" : motor[x].obj.dc(s) if v == 0 and motor[x].getType() != "---": print("stop",x) motor[x].obj.stop() #if motor[x].getDir() != 0 and motor[x].getType() == "DCMotor" : motor[x].obj.dc(s) vold = v # ----portcheck ------------------------------------------- def portcheck(i): # list of motors, 1 +2 contain string "DC" devices = { 1: "Wedo 2.0 DC Motor", 2: "Train DC Motor", 38: "BOOST Interactive Motor", 46: "Technic Large Motor", 47: "Technic Extra Large Motor", 48: "SPIKE Medium Angular Motor", 49: "SPIKE Large Angular Motor", 75: "Technic Medium Angular Motor", 76: "Technic Large Angular Motor", } port = motor[i].getPort() # Try to get the device, if it is attached. try: device = PUPDevice(port) except OSError as ex: if ex.args[0] == ENODEV: # No device found on this port. motor[i].setType("---") print(port, ": not connected") return ("---") else: raise # Get the device id id = device.info()['id'] # Look up the name. try: # get the attributes for tacho motors if "Motor" in devices[id] and not("DC" in devices[id]): motor[i].setType("Motor") motor[i].obj = Motor(port) #new in 2.7 # if motor[x].getDir() != 0 and motor[x].getType() == "Motor" : motor[x].obj.run(s*motor[x].getSpeed()) # in 2.7 devs_max_speed = {38:1530,46:1890,47:1980,48:1367,49:1278,75:1367,76:1278 } dspeed = devs_max_speed.get(PUPDevice(port).info()['id'], 1000) motor[i].obj.stop() motor[i].obj.control.limits(speed=dspeed,acceleration=10000) motor[i].setSpeed(dspeed/100*0.9) # and set type for simple DC Motors if "DC" in devices[id]: motor[i].setType("DCMotor") motor[i].obj = DCMotor(port) except KeyError: motor[i].stype("unkown") print(port, ":", "Unknown device with ID", id) wait(100) print ("--") print(port, ":", devices[id], motor[i].getType(),motor[i].getSpeed(),motor[i].getAcc()) # ---- device ------------------------------------------- class device(): # store the device infos for each motor def __init__(self,port,dir): self.port = port self.dir = dir self.type="" self.speed=99 self.acc=99 self.obj="" def setType(self,x) : self.type = x def setSpeed(self,x): self.speed = x def setAcc(self,x) : self.acc = x def getType(self) : return self.type def getPort(self) : return self.port def getDir(self) : return self.dir def getSpeed(self) : return self.speed def getAcc(self) : return self.acc # ----------------------------------------------- # globals # ----------------------------------------------- v = 0 vold = 0 #remoteConnected = False # ----------------------------------------------- # Ininitialize # ----------------------------------------------- hub = CityHub() #define timers timer = [0,0,0] timer[1] = delay(1) timer[2] = delay(2) #define motors motor = [0,0,0] motor[1] = device(Port.A,dirMotorA) motor[2] = device(Port.B,dirMotorB) # get the port properties portcheck(1) portcheck(2) # ----------------------------------------------- # remote connect # ----------------------------------------------- hub.light.on(Color.RED) print (hub.system.name()) try: remote = Remote(name=remoteName,timeout=remoteTimeout*1000) except OSError as ex: hub.system.shutdown() # ----------------------------------------------- # main loop # ----------------------------------------------- while True: # --check if remote is connected --------------------------------- try: button = remote.buttons.pressed() hub.light.on(LEDconn) remoteConnected = True except OSError as ex: hub.light.on(LEDnotconn) print("Remote not connected") remoteConnected = False if watchdog == True: v=0 drive() try: # reconnect remote remote = Remote(timeout=1000) wait(100) print("Remote reconnected") remoteConnected = True except OSError as ex: print("Remote not connected") if CheckButton(SWITCH): mode = mode+1 if mode > 2: mode = 1 print (mode) if mode == 1 : remote.light.on(LED_A) if mode == 2 : remote.light.on(LED_B) while CheckButton(SWITCH): button = remote.buttons.pressed() wait (100) if mode == 1 : function1() if mode == 2 : function1() wait(10) Quote
UltraViolet Posted July 9, 2023 Posted July 9, 2023 I was greatly interested in this project, but as I'm not much of a programmer, and also don't know German, I didn't have much luck with it early on and hoped others would 'pick up the torch' and grow it. Obviously I have even more interest now that I've had it working for the first time. I hope you don't feel that your work was not appreciated. I have written a single Arduino program ever, relying heavily on example code and existing libraries. Python, in this context, is very similar, but as with any other programmable controller platform and language, syntax and lack of key technical knowledge are the killer when starting out. I will do my best to experiment and learn now that I have a concrete example that is working for me on my hardware. I really hope others with in-depth knowledge of the LEGO-specifics and more fluency in Python can help drive this project forward and give it a permanent home. The problems you ran into which you described above are exactly the kind of thing I'm talking about. Even someone with experience such as yourself ran into trouble debugging code after the firmware side of it changed (essentially why the Linux Kernel drives me insane), enough so to quit in frustration. As a rudimentary-level coder, I'm not equipped to help with that, but I can understand enough to test others' end product. LEGO themselves should have offered an official solution to do exactly what this project accomplished. The only thing even close is how the default program on the six-port hubs allows you to run motors up and down in speed using just the arrow buttons on the hub itself. This is a joy on the design workbench, as I can just manipulate physical parts when building and testing MOCs without the need for programming in the PoweredUp app or a mobile device. It is also the only realistic scenario for many children to use the PuP platform outside the bounds of the pre-defined models, but perhaps also for many adults as well! Quote
Marlow Posted July 9, 2023 Posted July 9, 2023 16 minutes ago, Lok24 said: Thanks, as assumed, the motor(port) command, which was not supported any more. The block looks like that: devs_max_speed = {38:1530,46:1890,47:1980,48:1367,49:1278,75:1367,76:1278 } dspeed = devs_max_speed.get(PUPDevice(port).info()['id'], 1000) motor[i].obj.stop() motor[i].obj.control.limits(speed=dspeed,acceleration=10000) motor[i].setSpeed(dspeed/100*0.9) Seems that you use 2.7 which is not the latest Version.... Have a look: Yes, 2.7 was the version @BatteryPoweredBricks had a copy off. I've just loaded your version 2.9 onto a hub using firmware 3.2 and that works with both train motors and also a Technic L motor without errors. Reconnect of the remote also works, but only if the remote name is set. That was the same behavior on 2.7 for me. I could never reconnect with firmware 3.1. As of firmware 3.2 it works, as long as the remote name is set in the script. /M Quote
Lok24 Posted July 9, 2023 Author Posted July 9, 2023 (edited) 12 minutes ago, UltraViolet said: I hope you don't feel that your work was not appreciated. No, I don't, but I don't use it any more (I have no application for such a program at all, as for the two others of the "family") I not very familiar with Python, that's why the program is a little bit -hm- tricky? The intention I explained already. And I'm really trying to support, the issue mentioned her was fixed in 2.9 and I reported that in April here at Eurobricks. 5 minutes ago, Marlow said: Reconnect of the remote also works, but only if the remote name is set. That was the same behavior on 2.7 for me. Spooky! I'm sure that I never had set this value (cause I only have on remote). Edited July 9, 2023 by Lok24 Quote
Marlow Posted July 9, 2023 Posted July 9, 2023 (edited) 12 minutes ago, Lok24 said: And I'm really trying to support, the issue mentioned her was fixed in 2.9 and I reported that in April here at Eurobricks. The issue most likely wasn't an issue for most, as 2.7 continued to work on firmware 3.2, at least for those with train motors. So those would not have updated, as long as everything is working. I only came across the issue, once I tried to install the script in the hub of my crocodile, that uses a Lego Technic L-Motor. And by then, I had no way of updating seeing the download links were dead. Also, your download link still indicates, that 2.7 was the last version. 12 minutes ago, Lok24 said: No, I don't, but I don't use it any more (I have no application for such a program at all, as for the two others of the "family") No trains anymore ? That would be sad. /M Edited July 9, 2023 by Marlow Quote
Lok24 Posted July 9, 2023 Author Posted July 9, 2023 4 minutes ago, Marlow said: No trains anymore ? That would be sad. I never had any layout, just built some locos. The idea to that program came up with the crocodile ...... It should be useful for those, who used any motor(s) with the city hub. (not for me ;-) ) And as, mentioned, "Battery box" uses the same base. 8 minutes ago, Marlow said: And by, I had no way of updating seeing the download links were dead. Yes, but it was mentioned here: Anyway if there are a few "Python experts" we could discuss how to devolop that for further applications. Quote
Marlow Posted July 9, 2023 Posted July 9, 2023 (edited) 15 minutes ago, Lok24 said: The idea to that program came up with the crocodile ...... It should be useful for those, who used any motor(s) with the city hub. (not for me ;-) ) It's useful for the Crocodile, but also for any of the steam locos, which generally are build that way and then for those of us, who use 2 motors in a loco to pull a little bit more railcars than normal. With PF, at least one could stack the connectors and just put a reverse polarity switch in for the 2nd motor. That doesn't work with PU anymore. Your script solves that for those. 15 minutes ago, Lok24 said: Anyway if there are a few "Python experts" we could discuss how to devolop that for further applications. @and_ampersand_and and myself are already looking at, how we get lights or color sensors to work. Well, mostly lights. Because that would be the next thing one may want in a Crocodile or steam loco. /M Edited July 9, 2023 by Marlow Quote
and_ampersand_and Posted July 9, 2023 Posted July 9, 2023 1 hour ago, Lok24 said: Anyway if there are a few "Python experts" we could discuss how to devolop that for further applications. Thanks for providing the updated script! I updated my github repo with it. I plan on getting Lights working with the script at some point. Quote
Lok24 Posted July 9, 2023 Author Posted July 9, 2023 2 minutes ago, and_ampersand_and said: I plan on getting Lights working with the script at some point. You should then add them to the device list in "def portcheck(i)" and then apply to the "drive()" routine. As a first idea..... Quote
UltraViolet Posted July 20, 2023 Posted July 20, 2023 Now that I've been able to have the connection working, I've started testing some build scenarios to see how everything behaves. I've immediately run into a challenge which raises interesting questions about the possible different approaches to driving and managing the motors with Pybricks versus standard firmware functions. I have a train motor bogie built from a WeDo motor. When using basic variable speed coding in the Powered Up app through a City hub with stock firmware, the motor starts and runs fine. On the other hand, If I use the Pybricks firmware and the code we are discussing here, the motor cannot overcome the gearing resistance to start spinning without me forcing it by hand, and it will stall fairly easily. That got me thinking about how many modes or 'strategies' there are available in Pybricks (and in the hubs in general) to generate the variable voltage output to the motors. The stock config audibly emits the pulse-width modulation sound we are familiar with from the Powered Up and Power Functions hub outputs. The Pybricks code in our discussion, however, does not make this sound, or if it does, not at a level I can hear. Taking a loosely educated guess, it seems like the Pybricks code is not using full voltage as the basis for the PWM output. Can anyone with enough knowledge of the code comment on this? Is there any way to have the code modified to produce the PWM output in the way the stock firmware is generating it? I read through the code again, and I gather this is buried in one of the Pybricks pre-defined functions which is being called. So is it a matter of calling an alternate function, or does the content of the function itself need to be altered? I vaguely recall something from another coding situation about 'speed' control versus 'power' control. Would this have anything to do with it? I'd greatly appreciate if someone were able to figure this out. Quote
Toastie Posted July 20, 2023 Posted July 20, 2023 1 hour ago, UltraViolet said: I vaguely recall something from another coding situation about 'speed' control versus 'power' control. Would this have anything to do with it? I won't be of any help here, but just this: Speed vs power control would result in exactly the contrary result. 1) Using speed control: If the motor (at low initial power setting) cannot reach the speed you want, then the hub increases power = PWM level (= on vs off time = more on time) and I'd expect wheel slip rather than motor stalling. Control means that the firmware monitors the rpm of the motor. When too low = not correct speed, then increase power = on vs off ratio towards more on time. And vice versa. 2) Using power "control": This is a selected = fixed PWM level - there is no control. The firmware just applies a fixed on vs off time to the motor, regardless of speed, which changes with load. Now, when you cannot hear this hissing sound, then something is very odd. Does your WeDo motor produced that sound when using PUp firmware? The thing is, PWM means applying full DC voltage to the motor for a certain time and then go to zero voltage for another time. Rather quickly = generating that sound. As far as I know, none of the hardware available would allow reducing the voltage applied during a PWM on-time. But I may be wrong and others (like @Pybricks) have to switch on the light here. All the best + good luck, Thorsten Quote
UltraViolet Posted July 20, 2023 Posted July 20, 2023 The PWM sound is loud and clear when using Powered Up app with stock firmware, and completely absent as far as I can hear when using Lok24's code with Pybricks. I wish I had an oscilloscope so I could tell what was different about the waveform, other than perhaps amplitude. This is using two otherwise identical City Hubs, with a Keybrick One as the power source swapped back and forth between them. Maximum output voltage on both hubs, measured with a digital multimeter, is 6.04V. I devised a method to test for the presence of PWM. I used PV Productions adapter cables to patch an old 9V studded light bulb in parallel in the middle of the line. This type of bulb blinks when fed reverse polarity. The blinking interacts with the PWM signal, creating a variable flickering effect dependent on pulse width (this can also be used to create the lighting effect for a campfire, candle, or even a welder - You're welcome!). The two hub configurations both exhibit the flickering light effect running in reverse direction, therefore PWM is the basis of the motor control either way, although I figured that must be the case. Something is still clearly different between the two, though. Perhaps the stock firmware/code alters the PWM effect at slower speeds to prevent stalling and improve starting torque, much like the software option available on the PFX Brick. Something similar was available on straight-DC model railroad transformers, usually called "pulse power". It was only active at low speeds for exactly the same reasons. Someone much more familiar with device handling and code functions within Pybricks is going to have to comment on this. It's entirely possible the same behavior as stock can be activated with a single flag in code. I should add, if it helps explain any of this technically, that with Powered Up/stock firmware, if you start the output low enough that the motor is stalled, you will hear a pure 1200Hz tone. Once the motor starts spinning, the tone gets interfered with and kinda warbles. The loudness of the tone seems to decrease with speed increase. This may be the frequency of the low-speed assist control, or it could be the main PWM signal. That's as much as I have the tools to observe. This tone is entirely absent on the Pybricks setup I'm comparing it to. Quote
ejayb Posted July 21, 2023 Posted July 21, 2023 PyBricks uses a different PWM frequency which is quieter https://github.com/pybricks/pybricks-micropython/commit/030dd66fc0066290a1ab842fd387d11e8a8a2aac Have you tried creating PyBricks script from scratch? Quote
Lok24 Posted July 21, 2023 Author Posted July 21, 2023 Hi, correct, all motors use the Pybricks routines, "run" or "dc", depending on the device ID (which depends on the cable in DC-Motor cases here is an extract : Portcheck: # detect motor id if "Motor" in devices[id] and not("DC" in devices[id]): motor[i].setType("Motor") # and set type for simple DC Motors if "DC" in devices[id]: motor[i].setType("DCMotor") drive: # send the real commands to the devices if motor[x].getType() == "Motor" : motor[x].obj.run(s*motor[x].getSpeed()) # in 2.7 if motor[x].getType() == "DCMotor" : motor[x].obj.dc(s) Quote
UltraViolet Posted July 21, 2023 Posted July 21, 2023 13 hours ago, ejayb said: PyBricks uses a different PWM frequency which is quieter https://github.com/pybricks/pybricks-micropython/commit/030dd66fc0066290a1ab842fd387d11e8a8a2aac Have you tried creating PyBricks script from scratch? Thank-you very much for finding this information. Changing the PWM frequency that much dramatically higher could certainly explain the difference in motor response. They actually directly stated this change would affect the torque curve. If I read right, this change was committed in the version 3 Pybricks firmware. I'd really like to know if anyone testing multiple versions can replicate my observations. If the change in frequency was the culprit, it certainly should have been implemented in a way that allowed you to keep the old frequency if you wanted, rather than just forcing it to the new way and assuming everything would be fine. I don't care whether or not I hear the PWM frequency - I just want the same motor performance. I actually appreciate hearing the PWM because it allows me to tell whether the hub port is on at low speed steps and whether the motor is stalled. Do you guys feel this should be reported as an issue in the Pybricks GitHub? The thing I don't understand is why an even higher frequency would work on the EV3 and not on PUP with a similar one. There must be some other factor(s) at play in the operating parameters for the PUP devices which would result in weak motor response. Quote
and_ampersand_and Posted November 4, 2023 Posted November 4, 2023 (edited) Hi all, wanted to let you know that I've added support for 88005 Powered up Lights to Lok24's script. You can find the script here: https://github.com/and-ampersand-and/PyBricks-Train-Motor-Control-Script Lights will work plugged into either (or both) ports. The B side of the controller will always control them, while the A side controls any motors. Holding up or down will increase/decrease the brightness. The red button turns the lights off or fully own. By default, the lights start off, but you can change that by modifying `lightValue` in the user defined values section of the code. Shoutout to @BatteryPoweredBricks for help testing the script! Edited November 18, 2023 by and_ampersand_and Quote
BatteryPoweredBricks Posted December 10, 2023 Posted December 10, 2023 I'm sure many of the folks here are quite familiar with using PyBricks but I made a tutorial for those that haven't used it before. Sharing this with folks new to PyBricks should prove a lot easier than sending messages back and forth Quote
UltraViolet Posted December 10, 2023 Posted December 10, 2023 10 minutes ago, BatteryPoweredBricks said: I'm sure many of the folks here are quite familiar with using PyBricks but I made a tutorial for those that haven't used it before. Sharing this with folks new to PyBricks should prove a lot easier than sending messages back and forth Huge kudos to you for presenting this in a way that should allow just about anyone to get over the knowledge or fear barrier of using this (or PyBricks in general). It is such a relief to see this project still in development, so much thanks again also to the rest of you guys working on the coding! I'm wondering if it's possible to add another parameter to the code. One of my build applications is single-ended trams. Under normal circumstances, no 'driver' should ever be permitted to move in the reverse direction. Is there a way to provide a hard code flag that could enable/disable reverse direction (even if two motors set opposite are connected)? Alternatively, or in addition to this, can an additional parameter be provided where a separate maximum speed level can be set for each direction, so by this I could at least heavily limit the reverse speed? These parameters would help me 'get over the fear barrier' of handing the remote to my young nephews or to anyone at a show, as otherwise someone's quickly going to do a lot of damage no matter what I try to tell them. Quote
zephyr1934 Posted December 10, 2023 Posted December 10, 2023 1 hour ago, BatteryPoweredBricks said: I'm sure many of the folks here are quite familiar with using PyBricks but I made a tutorial for those that haven't used it before. Sharing this with folks new to PyBricks should prove a lot easier than sending messages back and forth Nice! Quote
SpiderFan44 Posted December 19, 2023 Posted December 19, 2023 On 12/10/2023 at 3:27 PM, BatteryPoweredBricks said: I'm sure many of the folks here are quite familiar with using PyBricks but I made a tutorial for those that haven't used it before. Sharing this with folks new to PyBricks should prove a lot easier than sending messages back and forth Well, I was not, new it existed, but not having and advanced usage that would have needed programmation didn't looked further into it until you showcased it in your video. I've got a custom engine that uses two motors, I was doing fine with the turning remote and press both button trick, but this is so much better. Hadn't loaded a programm in a brick since the RCX era. And yeah, I'm a programmer, could have looked into this earlier, but I'm also lazy, and you're video was the right push. Thanks. Quote
Lok24 Posted February 22, 2024 Author Posted February 22, 2024 Hi I just checked the hub-to.hub communication The idea was to use a "master"-hub and a remote to control two trains with the remote. As the master only uses one channel I submit a user-ID and hub-ID to address the "slaves" Here's the code: MASTER from pybricks.hubs import TechnicHub from pybricks.pupdevices import Motor, Remote from pybricks.parameters import Port, Button from pybricks.tools import wait hub = TechnicHub(broadcast_channel=1) my_remote = Remote() userID = "Lok24" hubID_A = "HUB1" hubID_B = "HUB2" vA = 0 vB = 0 vAold = 0 vBold = 0 while True: pressed = my_remote.buttons.pressed() vAold = vA vBold = vB if Button.LEFT_PLUS in pressed : vA = vA + 100 if Button.LEFT_MINUS in pressed : vA = vA - 100 if Button.LEFT in pressed : vA = 0 if Button.RIGHT_PLUS in pressed : vB = vB + 100 if Button.RIGHT_MINUS in pressed : vB = vB - 100 if Button.RIGHT in pressed : vB = 0 if vA != vAold: hub.ble.broadcast([userID,hubID_A,vA]) wait(100) if vB != vBold: hub.ble.broadcast([userID,hubID_B,vB]) wait(100) wait(10) SLAVES from pybricks.hubs import CityHub from pybricks.pupdevices import Motor from pybricks.parameters import Color, Port from pybricks.tools import wait hub = CityHub(observe_channels=[1]) motorA = Motor(Port.A) userID = "Lok24" hubID = "HUB2" # <<<<< must be different for each slave while True: data = hub.ble.observe(1) if data is None: hub.light.on(Color.RED) else: hub.light.on(Color.GREEN) uID,hID,v = data if uID == userID and hID == hubID: motorA.run (v) wait(100) Quote
and_ampersand_and Posted February 22, 2024 Posted February 22, 2024 4 hours ago, Lok24 said: The idea was to use a "master"-hub and a remote to control two trains with the remote. As the master only uses one channel I submit a user-ID and hub-ID to address the "slaves" Nice, I like the implementation of including hubId in the data so each hub knows which commands are for it. I was planning on looking into two trains on one remote as well, but was probably going to have the first train broadcasting to a second train, instead of a central hub broadcasting to two different trains. You way would solve the problem of the two trains getting to far away from each other and out of broadcast range as you could just move the master hub closer. Although I don't really know the broadcast range these hubs have or how far apart they'd have to be for the broadcast to fail. Quote
Lok24 Posted February 26, 2024 Author Posted February 26, 2024 In any way you could install a watchdog routine by sending a broadcast every x seconds and stop the train, if no broadcasts received within the last x+a seconds. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.