Hello Guest it is January 23, 2020, 12:19:09 AM

Author Topic: Axis as a Spindle using Jog? (or Serial??)  (Read 455 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonRafferty

*
  •  17 17
  • Movie SFX Design Engineer
    • View Profile
Axis as a Spindle using Jog? (or Serial??)
« on: November 19, 2019, 05:41:43 PM »
I have an EMCO PCMill100 which uses the spindle to move the tool turret.  Originally, the servo drive had analog and pulse/dir inputs with a line to swap mode.  Unfortunately the motor was fizzed when I bought it.  I replaced the spindle servo with a DMM Dyn4 + 750W motor which was the same frame size.  It works just fine in either step/dir or analog - but you have to send RS232 Serial commands to it to change mode.  I failed to make the Lua Serial library play nicely - so I thought up a different solution.

I'm trying to use Jogging - via the mcJogVelocityStart(inst, 3, mc.MC_JOG_POS) function inside M3,4,5 Macros (attached).
It works fine from the Lua IDE - but will not work from the MDI or GCode.  It clearly starts to run as the mcCntlSetLastError is displayed - but does not jog the axis.

Is there something in Mach4 which prevents Jog Velocity from running once the macro has terminated - i.e. is the jog running in a process, terminated at the end of the macro?

If that is the case (and it will not work no matter what), do any of you have an example of sending Serial data via Lua?

P.S. You might ask why I'm not using an OB Axis, which is intended for just this?  I'm using a CSMIO/IP-M which doesn't support OB.  They have (helpfully) suggested I buy an IP-A which does support it.  I figured a work-around was worth a go first!  At the very least, I've learned a lot about the inners of Mach4!
Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #1 on: November 21, 2019, 10:47:58 AM »
Simon,

I have successfully used Mach 4 LUA to communicate over serial to my AC servo drives (ASCII protocol). These are Ultra 3000 drives so they won't use the same commands as you need, but I have painfully learned how to get serial communications working. It is extremely reliable now and I use it as a backbone to my CNC control.

If you are still interested in getting serial working, I would be happy to share my code and answer any questions you might have.

I don't think there any many users of serial and there is essentially no documentation (I know your pain... ).

Mike
Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #2 on: November 21, 2019, 11:55:40 AM »
I'll do my best to provide you with some background information on the serial communications and follow up with the actual code when I can get to it later today.

Serial communications is handled in the background in Windows. Windows offers multiple serial ports, some are hardware and some are virtual (USB to RS232 converters). When a device is plugged in, it is assigned a COM port number. These are fixed for hardware serial ports, but can change each time you plug it in for the virtual ones (there are ways to assign fixed values). Only one program can "own" a serial port, and if a second program attempts to open a COM port which is in use, that attempt will fail.

Windows buffers incoming serial transmissions for you. I think the default value is 4096 bytes. It is a FIFO buffer which is always read from the oldest byte. Reading a byte from the buffer will permanently remove it, so make sure you are copying the data somewhere if you need it later. If the buffer fills up, the oldest data is pushed out and lost forever.

The LUA implementation of serial is a wrapper around the C++ library for serial communications. It only has a few functions and is entirely undocumented. These functions are:

-Open Serial Port
-Close Serial Port
-Flush Buffer (deletes the entire contents of the buffer without reading the data)
-Read (read a given number of characters, includes an optional timeout)
-Write (writes an input string, includes an optional timeout)

These functions do return exception codes if applicable and should be used to check if your code works as intended.

Since serial communications leave your computer, you need to deal with "real world" problems like late transmissions, corrupted data, and missing replies. The timeout value included in the read and write commands specifies the maximum amount of time the function will wait for data to arrive. If try to read the port, but you didn't provide a value and no data is available to be read, your program will hang. If you use large timeout values and data doesn't arrive, your program will run very slowly. I use 5ms in my system.

Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #3 on: November 21, 2019, 01:13:27 PM »
RS232 is the standard communications protocol for serial and can support a single connection between 1 computer and 1 servo drive. RS485 is a multi-drop network that can support many nodes, but is limited to a Master-Slave type of network since no data flow control is present (unlike Ethernet). In the case of my CNC control system, I have a PC with a built in RS232 port. I use an RS232-RS485 adapter ($10 on eBay) to connect the computer to a multi-drop network using Cat5e cable as the media. I have 6 servo drives on the network, waiting for commands from the PC.

I also have an extra RS232 to RS485 converter to connect a laptop to the network to view the traffic. This has been incredibly helpful for setting up and troubleshooting my code.

I use a free program called PuTTy to access the network like a terminal. This cannot be used at the same time as Mach 4 serial since they would try to share the port. I would first try to make sure you can type your commands into PuTTy while connected to the drive and get everything to work. If you cannot do that, then serial in Mach 4 definitely wont work. When I am using Mach 4 serial, I often have my laptop with PuTTy open on the network viewing traffic.
Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #4 on: November 21, 2019, 09:33:42 PM »
Simon,

Here are some of the key parts of scripting serial communications. I have attached my Mach 4 module (titled mcServo) which I created to communicate with my AB Ultra 3000 servo drives. If you do want to use this module, just be aware that the functions are tailored for my particular communications needs (including checksum calculation and verification, timing requirements, and Master/Slave communication). You will need to learn how the serial library works and use my scripts as an example to build what you need.

First off, you need to add the following header to wherever you are writing your scripts. This gets the current Mach 4 instance, includes the use of the LUA serial library, and defines a variable with the name of whatever COM port you would like to use. The io.stderr[/code] line was included in some example code I found, however I don't know if it is necessary or what its function is.

Code: [Select]
local inst = mc.mcGetInstance()

rs232 = require("luars232")
port_name = "COM1"
local out = io.stderr

Next you need to open the Serial Port and set the communication parameters. In this example I open COM1 at 38400 Baud and 8N1. You will find I do handle exceptions in the real serial module (attached), however they have been removed for clarity here.

Code: [Select]
e, p = rs232.open(port_name)
-- set port settings
assert(p:set_baud_rate(rs232.RS232_BAUD_38400) == rs232.RS232_ERR_NOERROR)
assert(p:set_data_bits(rs232.RS232_DATA_8) == rs232.RS232_ERR_NOERROR)
assert(p:set_parity(rs232.RS232_PARITY_NONE) == rs232.RS232_ERR_NOERROR)
assert(p:set_stop_bits(rs232.RS232_STOP_1) == rs232.RS232_ERR_NOERROR)
assert(p:set_flow_control(rs232.RS232_FLOW_OFF)  == rs232.RS232_ERR_NOERROR)

From now on, your open port will be named "p" and the methods you call will begin with "p:". For example if we wish to close the port, we use the following, where "e" is a returned error code.

Code: [Select]
e = p:close()
If we wish to flush the serial buffer, we can use either of the following lines of code. Obviously using the method :flush is simpler, however reading the entire contents of the buffer (4096 bytes, 5ms timeout) is equally effective.

Code: [Select]
e = p:flush()

e = p:read(4096, 5)

Now comes the good stuff. If we wish to write "Hello World" out of the port, we use the following. Note the use of standard string escape characters, in this case \r is carriage return. If you had a laptop with PuTTy open and connected to the serial network, you should see "Hello World" appear on the screen. len_written is an optional function return which gives you the length of the written string

Code: [Select]
e, len_written = p:write("Hello World\r", 5)
To read data on the port, we use the following. In this example we would be reading 10 characters (bytes) which included non-printed characters like carriage returns and applying a 5ms timeout. Again, "e" is an exception code (hopefully zero), "data_read" is the string of characters read from the port (this is what we want), and "size" is the length of the received string.

Code: [Select]
e, data_read, size = p:read(10, 5)
If you are writing out on the port and expecting a response back, it is a good idea to flush the buffer immediately before writing.

Please ask questions if you have them.

Mike
Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #5 on: November 21, 2019, 10:02:13 PM »
Some additional tips...

When I am developing new code, I often place some buttons on screen which execute a small chunk of code when clicked. To do this, I go into the screen editor and add a new tab to the Operations Tabs. Inside this tab I place a new button, give it text, and paste my chunk of code into the "Clicked Script" area. This would be a great place to develop your code to write "Hello World".

If the serial cable gets disconnected, the open port command will fail and "p" will have a value of nil. If you later try to use a serial function like p:write(), you will get a LUA error which will stop script execution in Mach 4. It is necessary to check if "p" actually exists before trying to use any serial commands.

It isn't always good enough to send a command and assume all the transmissions went correctly. When possible, try to read your changes back from the drive to verify they were applied.




Offline SimonRafferty

*
  •  17 17
  • Movie SFX Design Engineer
    • View Profile
Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #6 on: November 23, 2019, 04:59:03 AM »
Dear Mike,
Thanks very much!  You're a star!

The main problem I encounteres was lack of documentation - and what there was, didn't entirely work with Mach4.  I'll give yours a go.

I was using the same library - but the bit I'd missed was to close then flush the buffer and using two instances for Tx & Rx.  Well done for figuring that out.

Without the flush, mine would send intermittently.  I'm guessing that when you create the instance, the buffer pointer has some random value - then depending on the string you send it, the buffer overruns?

This is only my second outing with Lua (first was an ESP8266) though I've coded in C++ & C# for a long time - so it's just getting my head round the different syntax & environment. 

I'm also intending to use Ultra3000 drives on a Denford Cyclone F using Fanuc Red Cap motors.  I've had one spinning with pulse & direction though the motor needs a bit of tuning.  I'd not yet tried talking to the drives using Serial.

I have been trying to figure out how to control the original Fanuc A068-6059 spindle drive - but much of that still remains a mystery!  If that fails, an Ultra3000 30A ought to be sufficient to drive it.  Then talking to the drive to implement the spindle as an Axis would be useful.  My intention is to add live tooling - for which this is rather important!

Thanks again,

Si
Re: Axis as a Spindle using Jog? (or Serial??)
« Reply #7 on: November 23, 2019, 12:52:55 PM »
Simon,

Happy to help!

Quote
but the bit I'd missed was to close then flush the buffer and using two instances for Tx & Rx

Not entirely sure what you're referring to here. Ideally you keep the serial port open the entire time you are using Mach. I'm pretty sure Windows will automatically close the port when Mach 4 closes, but I opted to close it in the screen unload script anyways.

Quote
Without the flush, mine would send intermittently.  I'm guessing that when you create the instance, the buffer pointer has some random value - then depending on the string you send it, the buffer overruns?

As far as I know, the serial buffer is only used for data received on the open port (the buffer will not fill when the port is closed). Since writing data happens immediately, there is no need to buffer it. Without a buffer, you would need to get incredibly lucky to have your program looking for incoming data at the exact moment it arrived. Instead Windows captures and saves this data asynchronously from your code in the buffer.

Whenever the port is open, you should be able to write out the port, and it should happen immediately.

The buffer flush is not explicitly necessary, but I use it to make sure there isn't any junk in the buffer that I'd need to sort through to find the data packet I wanted. Even then, the serial code will handle a buffer full of junk characters as it looks for specific start and end characters and verifies the data with a checksum check.

Quote
This is only my second outing with Lua (first was an ESP8266) though I've coded in C++ & C# for a long time - so it's just getting my head round the different syntax & environment.

I was in the same boat as you 6 months to a year ago. I had just a bit of C++ experience and no idea what LUA was. The learning curve is a bit painful, but I really feel comfortable with the language now.

Quote
I'm also intending to use Ultra3000 drives on a Denford Cyclone F using Fanuc Red Cap motors.  I've had one spinning with pulse & direction though the motor needs a bit of tuning.  I'd not yet tried talking to the drives using Serial.

Wow! I'd love to hear how you got that working. It was my understanding that the Fanuc motors used pulsecoders with a proprietary serial interface that most drives couldn't understand.

In my setup, the serial data is just "bonus" stuff and my CNC would still work fine without it. I am using serial to configure the drives to my standard settings when Mach 4 loads, get the spindle load in real time, pull absolute position data into Mach 4 for homing, and hopefully soon - rigid tapping.

If you are interested, I would be happy to share my sister module to the serial one posted above that has all the functions to talk with the Ultra 3000.

Quote
If that fails, an Ultra3000 30A ought to be sufficient to drive it.  Then talking to the drive to implement the spindle as an Axis would be useful.  My intention is to add live tooling - for which this is rather important!

Sounds like a sweet setup! Would love to see it. Here to help with anything I can.
« Last Edit: November 23, 2019, 12:54:44 PM by mcardoso »