MrYsLab / pymata-aio

This is the second generation PyMata client.
https://github.com/MrYsLab/pymata-aio/wiki
GNU Affero General Public License v3.0
155 stars 51 forks source link

Ctrl-C to shutdown doesn't work with board.sleep #15

Closed fisherds closed 9 years ago

fisherds commented 9 years ago

I'm not sure if it is supposed to or not, but in the old version of Pymata that used time.sleep you could hit Ctrl-C to get a reset (which is now called shutdown). If I hit Ctrl-C during a board.sleep the shutdown command it's actually doing a shutdown on the Arduino. Ctrl-C works to print messages and shutdown is called, but there is no actual reset happening on the Arduino.

Running the code below does this...

    davids-mbp:Projects fisherds$ python3 simple_drive.py 
    pymata_aio Version 1.4  Copyright (c) 2015 Alan Yorinks All rights reserved.
    Using COM Port:/dev/tty.usbserial-A601LFJ9
    Initializing Arduino - Please wait... Auto-discovery complete. Found 20 Digital Pins and 6 Analog Pins
    Simple drive
    Straight
    Left!
    ^C
    You pressed Ctrl+C
    Shutting down ...

But then the motors all keep running whatever the current state is. Is there a way to get back the Ctrl-C feature while using board.sleep? Here is the complete code...

    #!/usr/bin/env python3
    """
    Copyright (c) 2015 Alan Yorinks All rights reserved.
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU  General Public
    License as published by the Free Software Foundation; either
    version 3 of the License, or (at your option) any later version.
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
    You should have received a copy of the GNU General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    """

    import sys
    import signal
    import time

    from pymata_aio.pymata3 import PyMata3
    from pymata_aio.constants import Constants

    BOARD_LED = 13

    # RedBot motor pins (from RedBot.h)
    L_CTRL_1 = 2
    L_CTRL_2 = 4
    PWM_L = 5

    R_CTRL_1 = 7
    R_CTRL_2 = 8
    PWM_R = 6

    board = PyMata3()

    def signal_handler(sig, frame):
        print('\nYou pressed Ctrl+C')
        if board is not None:
            board.shutdown()
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C to shutdown

    def setup():
        """Setup pins"""
        print("Simple drive")
        board.set_pin_mode(BOARD_LED, Constants.OUTPUT)
        board.set_pin_mode(L_CTRL_1, Constants.OUTPUT)
        board.set_pin_mode(L_CTRL_2, Constants.OUTPUT)
        board.set_pin_mode(PWM_L, Constants.PWM)
        board.set_pin_mode(R_CTRL_1, Constants.OUTPUT)
        board.set_pin_mode(R_CTRL_2, Constants.OUTPUT)
        board.set_pin_mode(PWM_R, Constants.PWM)

    def loop():
        print("Straight")
        board.digital_write(BOARD_LED, 1)
        board.digital_write(R_CTRL_1, 1)
        board.digital_write(R_CTRL_2, 0)
        board.analog_write(PWM_R, 245)
        board.digital_write(L_CTRL_1, 1)
        board.digital_write(L_CTRL_2, 0)
        board.analog_write(PWM_L, 245)
        board.sleep(2.0)

        print("Left!")
        board.digital_write(BOARD_LED, 0)
        board.digital_write(R_CTRL_1, 0)
        board.digital_write(R_CTRL_2, 1)
        board.analog_write(PWM_R, 245)
        board.digital_write(L_CTRL_1, 1)
        board.digital_write(L_CTRL_2, 0)
        board.analog_write(PWM_L, 245)
        board.sleep(2.0)

        print("Right")
        board.digital_write(BOARD_LED, 1)
        board.digital_write(R_CTRL_1, 1)
        board.digital_write(R_CTRL_2, 0)
        board.analog_write(PWM_R, 245)
        board.digital_write(L_CTRL_1, 0)
        board.digital_write(L_CTRL_2, 1)
        board.analog_write(PWM_L, 245)
        board.sleep(2.0)

        print("Stop")
        board.digital_write(BOARD_LED, 0)
        board.digital_write(R_CTRL_1, 1)
        board.digital_write(R_CTRL_2, 0)
        board.analog_write(PWM_R, 0)
        board.digital_write(L_CTRL_1, 1)
        board.digital_write(L_CTRL_2, 0)
        board.analog_write(PWM_L, 0)
        board.sleep(5.0)

    if __name__ == "__main__":
      setup()
      while True:
        loop()
MrYsLab commented 9 years ago

I am seeing the same thing and will investigate.

MrYsLab commented 9 years ago

I have a temporary work-around that will turn off the motors, but will throw some benign exceptions on exiting. Modify your signal handler to:

def signal_handler(sig, frame):
        print('\nYou pressed Ctrl+C')
        if board is not None:
            board.reset()
        sys.exit(0)

An original design goal was to provide an internal working Control-C handler, which is clearly not the case. I will leave this issue open until I come up with a workable solution in code or coding guidance.

fisherds commented 9 years ago

I can live with that.

Also as an FYI this is a non-issue when I run the Python script from Eclipse. Even without any signal_handler code at all. When I hit the red stop button on the Eclipse Console the wheels shutdown correctly. It's like magic. The wheels stop, there are like four quick flashes on LED 13, a quick flash on the Rx LED and the thing is shutdown. No logs shown, but the Adruino is properly shutdown. Is that your attempt at the internal Control-C handler working??? Just tell everyone to use Eclipse instead of running scripts from the command line. :) 100% reliable.

image

MrYsLab commented 9 years ago

Thanks for the feedback. The flashing L13 is how Firmata announces its version number( in addition to sending out the serial port), so that is correct. There is signal handling code built into pymata_core that is supposed to handle control-c detection. It sees the signal, but does not shutdown cleanly, so I will be investigating.

MrYsLab commented 9 years ago

I retested with version 2.1 and when I press ctrl-c the motors stop. I removed the signal handler code from the example, and retested, and again, the motors stop from the internal ctrl-c handling within pymata_core. Therefore I am closing this issue.