0

Here's a summary of my setup:

  • 3 axis CNC, controllable via a python script running on raspberry pi
  • Windows PC can connect to the pi can run a script

The end goal is for a UI made in C# to initiate an automated test cycle for the CNC to run in. In the python program there is a Cnc object that stores the devices current position and contains methods to position it to a certain place.

The problem is if i run a new script every time i want to move the CNC, I have to re initialize the Cnc instance and it will forget it's position. So I'm wondering if I can have one master program running that contains the one and only Cnc instance, then when the remote machine wants to tell the CNC to move it can run a different script with argz for the new position python action.py x y z. This script could then communicate to the master program to call the move method to the appropriate location without ever having to re-construct a new Cnc object. Then ideally the master program would indicate when the motion is completed and send back a message to the "action" script, that script would output something to tell the remote system that the action is completed, then it would exit, ready to be called again with new argz.

In the end the remote system is highly abstracted from any of the working and just needs to start running the master, then run the move script with argz any time it wants to perform a motion.

Note: My other idea was to just save a text file with the current position then always re initialize the instance with the info in the file.

EDIT: SOLVED... sort of

handler.py

The handler will continuously read from a text file named input.txt looking for a new integer. If received it will update a text file named output.txt to read '0', then do some action with the input (i.e move a cnc) then write the value '1' to output.txt.

from time import sleep
cur_pos=0

while True:
    with open("input.txt","r") as f:
        pos=f.readline()
    try:
        if pos=='':
            pass
        else:
            pos=int(pos)
    except:
        print pos
        print("exititng...")
        exit()

    if cur_pos==pos or pos=='':
        #suggestion from @Todd W to sleep before next read
        sleep(0.3)
        pass
    else:
        print("Current pos: {0:d}, New pos: {1:d}".format(cur_pos,pos))
        print("Updating...")
        with open("output.txt","w") as f:
            f.write("0")
        #do some computation with the data
        sleep(2)
        cur_pos=pos
        print("Current pos: {0:d}".format(cur_pos))
        with open("output.txt","w") as f:
            f.write("1")

pass_action.py

The action passer will accept a command line argument, write it to input.txt, then wait for output.txt to read '1', after which it will print done and exit.

import sys
from time import sleep
newpos=sys.argv[1]
with open("input.txt","w") as f:
    f.write(newpos)

while True:
    sleep(0.1)
    with open("output.txt","r") as f:
        if f.readline()=='1':
            break

sys.stdout.write("done")
user2757771
  • 158
  • 7
  • Mmm.... what happens if 2 parallel processes say *"go here"* then *"cut"* and they get executed at the same time? You might move to A and do the cut you meant to do at B... – Mark Setchell Apr 03 '18 at 19:50
  • I'm more so just wondering if it's possible then will worry about inevitable concurrency issues after. – user2757771 Apr 03 '18 at 20:15
  • @user2757771 Better to perform reset of device to the normal state let's says 0,0,0 point before every new call. Because in case of terminated program or even blackout on remote site you will lose it state and it can't dump current state into the file. To avoid double execution you can check running scripts smth like "ps aux | grep my_control_script.py" and make decision based on that. – Denis Apr 03 '18 at 20:49
  • 1
    Your handler.py should probably sleep at the end of its loop (even if just a second or two) or its going to hammer the CPU and filesystem constantly. – Todd W Apr 03 '18 at 23:40

3 Answers3

2

One possible approach might just be to make your main python script a webapp using something like Flask or Bottle. Your app initializes the cnc, then waits for HTTP input, maybe on an endpoint like 'move'. Your C# app then just sends a REST request (HTTP) to move like {'coordinates': [10,15]} and your app acts on it.

Todd W
  • 398
  • 1
  • 6
  • I'm actaully just running everything on a very secure local network with no internet connection. So this idea might be very difficult to accomplish, but i'll look into it. – user2757771 Apr 03 '18 at 20:17
  • 1
    It doesn't need to be on the internet. You can still run a web app on a local network. – Todd W Apr 03 '18 at 20:24
2

If you really want to be dead simple, have your "main" CNC script read a designated directory on the file system looking for a text file that has one or more commands. If multiple files are there, take the earliest file and execute the command(s). Then delete the file (or move it to another directory) and get the next file. If there's no file, sleep for a few seconds and check again. Repeat ad nauseam. Then your C# app just has to write a command file to the correct directory.

Todd W
  • 398
  • 1
  • 6
  • the best way though would be if there was some way to interact with a running python script over ssh, then i could just use the python `raw_input` method – user2757771 Apr 03 '18 at 20:51
  • I don't think that would work in the way you think it would. What you've asked for in the original question is basically making your python script a server that receives commands from a client. If so, you should consider the answer below for making your python script a web app. – Todd W Apr 03 '18 at 20:58
  • yes a very simple server in some sense that only needs to talk with one client at a time running on the same system. I.e the client is just the script that excepts the positions argz – user2757771 Apr 03 '18 at 21:25
1

Your better bet is to combine gevent with GIPC https://gehrcke.de/gipc/

This allows for asynchronous calls to a stack, and communication between separate processes.

eatmeimadanish
  • 3,809
  • 1
  • 14
  • 20