jminardi / mecode

GCode for all
MIT License
221 stars 61 forks source link

real time control using mecode.G(direct_write=True, direct_write_mode="serial") with fix #66

Closed DerAndere1 closed 5 years ago

DerAndere1 commented 6 years ago

Steps to reproduce issue

  1. connect your computer (via USB2.0) to a controller board featuring a Microchip Atmega AVR microcontroller that is designed to reset upon serial connection and that runs marlin firmware.
  2. Run a Python3 script (I use the Python 3.7 interpreter CPython under MS Windows 10 64 bit) which contains a mecode.G(direct_write=True) command, e.g. listing 1:
    import mecode
    g = mecode.G(direct_write=True, direct_write_mode="serial", printer_port="COM3", baudrate=115200)   # realtime communication via serial communication at port COMx (with x=3) under MS Windows. See https://github.com/jminardi/mecode/blob/master/mecode/main.py .
    g.write("M302 S0")   # send g-Code. Here: allow cold extrusion. Danger: Make sure extruder is clean without filament inserted 
    g.move(10, 10, 10)   # move 10mm in x and 10mm in y and 10mm in z
    g.retract(10)   # move extruder motor

    Expected behaviour:

    • I expected that all stepper motors would move
    • I would like to find documentation on how to create a socket and get its port number in order to use it with mecode.G(direct_write=True) as an alternative

Observed behaviour:

Possible Solution: Use my fork of mecode which provides fixes (see branch serial_fix) and add the following lines of code after the last command of the Python script that communicates with the controller board (e.g. append to listing 1, see above):

import time
time.sleep(12)

If someone confirms my issues I can create a pull request

jminardi commented 6 years ago

The following works for me:


    # mecode object
    g = G(
            print_lines=False,
            aerotech_include=False,
            direct_write=True,
            direct_write_mode='serial',
            printer_port="/dev/tty.usbmodem1411",
            #printer_port="COM13",  #use for windows host machine
    )

This is on python 2.7, although I think it should work with python 3.x

What is the fix you mentioned to get it to work?

DerAndere1 commented 6 years ago

The diff is here: https://github.com/jminardi/mecode/compare/master...DerAndere1:serial_fix

I think for python 2/3 compatibility, my key change was to copy the decode2To3() and encode2To3() definitions from main.py to printer.py and change printer.py line 358 from line = self.s.readline() to: line = decode2To3(self.s.readline())

And change printer.py line 340 to: self.s.write(encode2To3(line))

My second problem is better handled in a sparate fork as it seems to be MCU dependent: Your loop in printer.py line 125 did not recognize when my MCU finished restarting and the timeout stoped the serial connection. So I removed that loop and instead changed printer.py line 114 from:
self.s = serial.Serial(self.port, self.baudrate, timeout=3) to:

self.s = serial.Serial(self.port, self.baudrate, timeout=6)
sleep(5)
DerAndere1 commented 6 years ago

I updated my serial_fix branch and edited my comment above accordingly. Tested with Python3 only but It uses decode2To3 so Python 2 should also work.

DerAndere1 commented 5 years ago

At least with Python 3.x, pySerial's serial.readline(data) and serial.write(data) requires that data to be transferred is a bytes object (or compatible type such as bytearray) . That is why for all occurances of s.write() and s.readline() in mecode, the data to be sent should first be encoded like this: data.encode('utf-8') and received byte data has to be decoded to obtain unicode strings: data.decode('utf-8'). Along those lines, the tests have to be adjusted to make all data is always a byte object.I would add the following changes to PR https://github.com/jminardi/mecode/pull/68 : https://github.com/jminardi/mecode/blob/13eef1e2a173584badf9a3ac0f231497fd5945c6/mecode/tests/test_printer.py#L24 should read self.p.s.readline.return_value = encode2to3('ok\n')


https://github.com/jminardi/mecode/blob/13eef1e2a173584badf9a3ac0f231497fd5945c6/mecode/tests/test_printer.py#L60 should be self.p.s.write.assert_called_with(encode2to3('N1 no new line*44\n'))


https://github.com/jminardi/mecode/blob/13eef1e2a173584badf9a3ac0f231497fd5945c6/mecode/tests/test_printer.py#L66 should become self.p.s.write.assert_called_with(encode2to3('N2 with new line*44\n'))

jminardi commented 5 years ago

@DerAndere1 Do you believe your suggested changes are still needed? I do not current have access to a serial connected 3d printer