Giter VIP home page Giter VIP logo

juanmf / steppermotors Goto Github PK

View Code? Open in Web Editor NEW
16.0 3.0 0.0 2.76 MB

Python stepper motor library with customizable acceleration strategies and responsive, interruptible motor operations.

Home Page: https://github.com/juanmf/StepperMotors

License: MIT License

Python 100.00%
stepper-motor stepper-motor-control stepper-motor-driver event-driven motor-controller multiprocess multiprocessing parallel-computing python3 raspberry-pi motor-benchmark drv8825 nema17 nema23 tmc2209 tmc2208 tmc2226

steppermotors's Issues

Logging reentrant lock attempt

Upon exit on Ctrl-C, sometimes I get.
this error occurs while handling an error.
I might be triggering this by waiting too long to print buffers. Still a bug in logging lib.

Logging error (RuntimeError("reentrant call inside <_io.BufferedWriter name='<stderr>'>"), 
               'Traceback (most recent call last):\n  
                File "/usr/lib/python3.11/logging/__init__.py", line 1113, in emit\n    
                      stream.write(msg + self.terminator)\n
                RuntimeError: reentrant call inside <_io.BufferedWriter name=\'<stderr>\'>\n\n
                During handling of the above exception, another exception occurred:\n\n  
                Traceback (most recent call last):\n    
                    File "/home/juanmf/projects/turret/env/lib/python3.11/site-packages/stepper_motors_juanmf1/ThreadOrderedPrint.py", line 71, in flush_streams\n      
                        logging.info(out)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 2148, in info\n      
                        root.info(msg, *args, **kwargs)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 1489, in info\n      
                        self._log(INFO, msg, args, **kwargs)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 1634, in _log\n      
                        self.handle(record)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 1644, in handle\n      
                        self.callHandlers(record)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 1706, in callHandlers\n      
                        hdlr.handle(record)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 978, in handle\n      
                        self.emit(record)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 1118, in emit\n      
                        self.handleError(record)\n    
                    File "/usr/lib/python3.11/logging/__init__.py", line 1031, in handleError\n      
                        sys.stderr.write(\'--- Logging error ---\\n\')\n    
                RuntimeError: reentrant call inside <_io.BufferedWriter name=\'<stderr>\'>\n')

the error handling code in logging.Handler.handleError() [[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/logging/init.py]:

        if raiseExceptions and sys.stderr:  # see issue 13807
            t, v, tb = sys.exc_info()
            try:
                sys.stderr.write('--- Logging error ---\n')  # <<<< This one, in prior [ line 1031, in handleError\n   ]
                traceback.print_exception(t, v, tb, None, sys.stderr)
                sys.stderr.write('Call stack:\n')
    def handle(self, record):
        """
        Conditionally emit the specified logging record.

        Emission depends on filters which may have been added to the handler.
        Wrap the actual emission of the record with acquisition/release of
        the I/O thread lock. Returns whether the filter passed the record for
        emission.
        """
        rv = self.filter(record)
        if rv:
            self.acquire()  # this acquire that happens 1st might be interfering with the error handle fn. [, line 978, in handle\n      ]
            try:
                self.emit(record)
            finally:
                self.release()
        return rv

Job Chain does not work with StaticNavigation

A client that is also a BlockingQueueWorker that has two motorsDrivers on StaticNavigation fails to start a job Chain, at the client BlockingQueueWorker when it has to block on both Drivers' jobs before continuing with its own job chain.
Each link in the chain starts jobs for downstream Drivers. At some point upstream BlockingQueueWorker and downstream MotorDrivers (also BlockingQueueWorker) when using static nav fails.

Sounds like Corner case since Chains are designed for non-blocking situations like DynamicNavigation, but shouldn't fail.

Builders don't make it through multiprocess spawning, thus only factory methods work for now on MP.

    def _initMpDrivers(self, controllerFactory: MultiProcessingControllerFactory):
        azimuthDriverShared = Value(ctypes.c_int, 0)
        elevationDriverShared = Value(ctypes.c_int, 0)

        azimuthObserver = MultiprocessObserver(eventObserver=partial(self.childProcessEventObserver, "azimuth"),
                                               eventPublisher=self.sharedDataProcessing,
                                               sharedMemory=azimuthDriverShared)
        elevationObserver = MultiprocessObserver(eventObserver=partial(self.childProcessEventObserver, "elevation"),
                                               eventPublisher=self.sharedDataProcessing,
                                               sharedMemory=elevationDriverShared)

        nema = Nema17_42Ncm_17HS4401(True)

        # This builder works on mono process only:
        builder = (ControllerBuilder.getBasicBuilder(stepperMotor=nema, directionGpioPin=8, stepGpioPin=25,
                                                     enableGpioPin=1)
                   .withTorqueCurve(None)
                   .withNavigationStyleSynchronized()
                   .withCustomTorqueCurveAccelerationAcceleration()
                   .withClientMultiprocessObserver(elevationObserver))

        self.azimuthDriver, self.elevationDriver = (controllerFactory
                .setUpProcess()
                # Todo: Add builder to MP scenario.
                .withDriver(multiprocessObserver=azimuthObserver,
                            factoryFnReference=controllerFactory.getMpCustomTorqueCharacteristicsDRV8825With,
                            stepperMotor=PG35S_D48_HHC2(True), directionGpioPin=13, stepGpioPin=19, sleepGpioPin=12)
              
                .withDriver(multiprocessObserver=elevationObserver,
                            factoryFnReference=controllerFactory.getMpCustomTorqueCharacteristicsTMC2209With,
                            stepperMotor=nema, directionGpioPin=8, stepGpioPin=25, enableGpioPin=1)
                # Alternative:
                # .withDriverBuilder(builder=builder, builderMethodRef=builder.buildTMC2209StandaloneDriver)

                .spawn())

When I run .withDriverBuilder(builder=builder, builderMethodRef=builder.buildTMC2209StandaloneDriver) nothing fails but the motor driver is not getting the jobs in child process.

OrderedDict not sorted.

misuse of OrderedDict, need to implement SortedDict instead.
OrderedDict.popitem() used in sync navigation is introducing slight timing issues in pulses due to not sorting pulse timestamps.

Benchmark broken after cumulative changes since previous releases.

Step 3:

[20:22:37.329256] 3) Starting from minPPS will try to jump to greatest next PPS that you observe not to fail with.
[20:22:37.329261]             'y': Notify the system about successful Speed Boost
[20:22:37.329267]             'n': Notify the system about failed Speed Boost
[20:22:37.329273]             'r': Repeat Speed Boost

Accepting (speed bump) 'y' and rejecting 'n' has chaotic behavior now:

[20:23:22.173311] Enter pressed, setting picked True!!!
[20:23:22:685233] Max Speed: 520 <<===
@end thread dump MainThread =========================================
===================================================================================
Thread prints Dump Complete =======================================================
INFO:root:
@start thread dump MainProcess => MainThread ========================================
==========================================================================
[20:23:22.686475] 
[20:23:22.686515] FINDING SPEED BOOSTS FOR MOTOR.
[20:23:22.686532] 
[20:23:23.186991] stepperMotor: <stepper_motors_juanmf1.StepperMotor.PG35S_D48_HHC2 object at 0x7fb81a38d0>, steppingModeMultiple 1
[20:23:23.187153] 
[20:23:23.187196] speedBoosts: [(150, 5)]
[20:23:23.187217] 
@end thread dump MainThread =========================================
===================================================================================
Thread prints Dump Complete =======================================================
INFO:root:
@start thread dump MainProcess => MainThread ========================================
==========================================================================
[20:23:27.388531] PASSED speed boost: cPPs: 155 last Speed: 150
[20:23:27.388587] Restarting cycle.
[20:23:27.388641] Doubling Delta: new delta: 10
[20:23:27.388664] 
[20:23:27.388679] FINDING SPEED BOOSTS FOR MOTOR.
[20:23:27.388694] 
[20:23:27.889107] 
[20:23:27.889201] speedBoosts: [(150, 5)]
[20:23:27.889221] 
@end thread dump MainThread =========================================
===================================================================================
Thread prints Dump Complete =======================================================
INFO:root:
@start thread dump MainProcess => MainThread ========================================
==========================================================================
[20:23:29.105490] PASSED speed boost: cPPs: 160 last Speed: 150
[20:23:29.105539] Restarting cycle.
[20:23:29.105587] Doubling Delta: new delta: 20
[20:23:29.105610] 
[20:23:29.105625] FINDING SPEED BOOSTS FOR MOTOR.
[20:23:29.105661] 
[20:23:29.606077] 
[20:23:29.606172] speedBoosts: [(150, 5)]
[20:23:29.606191] 
@end thread dump MainThread =========================================
===================================================================================
Thread prints Dump Complete =======================================================

INFO:root:
start thread dump MainProcess => MainThread ========================================
=========================================================================
[20:23:30.687948] PASSED speed boost: cPPs: 170 last Speed: 150
[20:23:30.687997] Restarting cycle.
[20:23:30.688047] Doubling Delta: new delta: 40
[20:23:30.688070] 
[20:23:30.688085] FINDING SPEED BOOSTS FOR MOTOR.
[20:23:30.688099] 
[20:23:31.188454] 
[20:23:31.188515] speedBoosts: [(150, 5)]
[20:23:31.188535] 
...

currentPPS (cPPs): 387 & last Speed: 150 implies a speed jump of 237
yet new Limit: 5; newDelta: 5; prevDelta: 5.0 does not reflect it.

==========================================================================
[20:24:15.510391] FAILED speed boost: cPPs: 387 last Speed: 150
[20:24:15.510446] Restarting cycle.
[20:24:15.510497] new Limit: 5; newDelta: 5; prevDelta: 5.0
[20:24:15.510541] 
[20:24:15.510559] FINDING SPEED BOOSTS FOR MOTOR.
[20:24:15.510574] 
[20:24:16.010925] 
[20:24:16.010983] speedBoosts: [(150, 5)]

PONG

Hello,
My senior design team and I (we are seniors in an EE program) are working on a display for the game PONG using two stepper motors and the CoreXY methodology. We are using your code to run the motors simultaneously to decrease the jerkiness of the motion. We are having a hard time figuring out where the "Move Complete" flag is stored. We'd like to use it as a flag to start the next movement.
Can you help?

Support for Adafruit Motorkit

Do you have plans to add support for the Adafruit Motorkit?

I am using this extensively in a project, but the supplied MotorKit libraries are fairly rudimentary. I would be happy to help test on my hardware.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.