Hi - First post, so please let me know if i'm posting in the wrong place. I'm building a gantry style machine, but rather than the usual tool end effector, the end effector is a specialized "claw" type device for handling an object in the workspace. I got most of my inspiration from Openbuilds belt and pinion design linear actuators and am at the stage where I need to write the software. I'm looking for the easiest/best way to control the machine. For context, I have a lot of experience writing software, so I'm not worried about programming. I just don't want to go waste a ton of time going down a rabbit hole that leads nowhere. My questions are the following- 1) Should I use GRBL to control the XYZ for the machine? I need a decent programmatic interface, but I can't seem to figure out how to send commands to GRBL using an interface other than something like Universal Gcode Sender. My needs at this level aren't much more than 'Go to X Y Z', no crazy path or anything. I had thought GRBL was a little more flexible, but it seems it's really only made for CNC machines. 2) Is there a decent tutorial on how one can write custom (basic) Gcode, if I were to attempt to send it over the connection myself? I have close to zero experience with Gcode, but I have learned many programming languages over the years so I'm not worried about figuring it out. 3) Should I just write the code myself from scratch? The only reason I want to avoid this is because it sounds like GRBL is already optimized and getting the steppers tuned might be a pain without a good example. 4) Is there some other option I should consider? For context, I already have GRBL running on an arduino, and I can use it to control the linear actuators via the Universal Gcode Sender software.
I would use GRBL for the motion control and use my favourite language (with serial communications) to send it Gcode commands. this is the fastest development route. as you say, GRBL already has the stepper control figured out, best to just use it. note that there are GRBL compile options for RC servo control on Z, instead of a stepper motor, in case that operates your claw better.
Oh wow, I didn't know that about the RC servo control on Z. That becomes very interesting! I'm currently looking through the documentation that @Peter Van Der Walt pointed me to, this looks like a viable approach. As mentioned, I would definitely prefer letting GRBL do the heavy lifting it is designed to do. Will report back here, hopefully with some videos. One more question if someone with more experience than me can provide some insight - How do I get really smooth and quick acceleration like this (at 0:11) My mechatronic experience is a bit more limited than my software experience. I'm trying to understand if this smooth motion is mostly software configuration on normal NEMA 17 steppers, or if it's something else? Please feel free to indulge me like a 5 year old, as I am currently pursuing a degree in this field after two decades of software and chip design professional experience. Thanks ahead of time for the pointers and the info!
Hello again, I disabled microstepping to try to get faster motion. I'm now getting behavior from the stepper that I'm having difficulty getting to the bottom of. Here are two videos... I'm guessing maybe my wheels might be too tight, so the torque required to overcome the friction is high, and the acceleration on the shaft In the first video, you can see two red dots, one on the shaft and the other on the pulley , to help show the motion. The motion appears to step back and forth rather than just one direction. In this video, there is just one red dot on the pulley, and it appears that maybe the belt is slipping though it doesn't seem too tight. Lastly, here is a video with the belt taken off the pulley. Does this look normal? Why is there a wobble at the start and end of a cycle? Is something loose? And here is a video of the motion with 1/32 microstepping set on the DRV8825. Moving slowly, but much more smooth. I could work with this for my purposes, but it would be nice to be able to go a little faster. Thanks ahead of time
Looks typical of only 3 of the 4 motor wires making good contact. Recheck motor wiring, redo any joints.
@Peter Van Der Walt Got it, thanks for the feedback. I had chopped the wires that came with the steppers and spliced in longer sections since my gantry is long and I just had the shorter wires. I soldered and heatshrank everything as cleanly as I could, but it's possible I did a bad job. I've ordered some new 1meter wires off Amazon. I also had one extra wire laying around and swapped out the old one with the extra one, so it seems to have made a world of difference. Here's a video:
you don't need more than 8x microstepping with belts. microstepping was invented to solve the problem of vibration in stepper motors, we misapply it to get more resolution, but more microsteps = less accuracy and less power, so only use what you really need.
Hello again and Happy Holidays to all. I went through @Peter Van Der Walt's link for the GRBL streaming interface and have written a short program. Briefly, I give it a pyramid - meaning, X100, X200... X600, X500 ... X100 , here is my output (below). There is something basic I must be misunderstanding. 1) The behavior I get, unless I introduce artificial delays in my python script, is that it goes from X0 to X600 to X100 without stopping. I suppose this makes sense, the command are sent to GRBL, GRBL response with 'ok' and then they are executed as fast as possible, so GRBL never decelerates or slows down. Please correct me here or let me know if I've got that right, thanks. 2) I issue some '?' along the way to get position information, but I don't quite understand what I'm getting back. These positions are clearly not at the locations I commanded the machine to. If I add 1 second delay/sleep between each commands, I get the expected positions based on the commands. I'm assuming these positions are just the position when GRBL actually receives the command. I saw something in the wiki about GRBL picking these commands off and running them as soon as it sees them. Again, please correct me if I'm misunderstanding anything. Also, I've added a video at the bottom just in case that's helpful to see. Sending: $H ok Sending: G10 P0 L20 X0 Y0 Z0 ok pattern2 Sending: G0 X100 ok Sending: ? <Run|MPos:0.000,0.000,0.000|Bf:14,127|FS:7200,0|WCO:0.000,0.000,0.000> ok Sending: ok Sending: G0 X200 ok Sending: ? <Run|MPos:0.400,0.000,0.000|Bf:13,127|FS:7200,0|Ov:100,100,100> ok Sending: ok Sending: G0 X300 ok Sending: ? <Run|MPos:1.200,0.000,0.000|Bf:12,127|FS:9600,0> ok Sending: ok Sending: G0 X400 ok Sending: ? <Run|MPos:2.600,0.000,0.000|Bf:11,127|FS:12000,0> ok Sending: ok Sending: G0 X500 ok Sending: ? <Run|MPos:4.600,0.000,0.000|Bf:10,127|FS:13200,0> ok Sending: ok Sending: G0 X600 ok Sending: ? <Run|MPos:7.000,0.000,0.000|Bf:9,127|FS:15600,0> ok Sending: ok Sending: G0 X500 ok Sending: ? <Run|MPos:10.000,0.000,0.000|Bf:8,128|FS:18000,0> ok Sending: ok Sending: G0 X400 ok Sending: ? <Run|MPos:13.600,0.000,0.000|Bf:7,127|FS:19200,0> ok Sending: ok Sending: G0 X300 ok Sending: ? <Run|MPos:17.600,0.000,0.000|Bf:6,127|FS:21600,0> ok Sending: ok Sending: G0 X200 ok Sending: ? <Run|MPos:22.400,0.000,0.000|Bf:5,127|FS:22800,0> ok Sending: ok Sending: G0 X100 ok Sending: ? <Run|MPos:27.400,0.000,0.000|Bf:4,127|FS:25200,0> ok
Post your script please ? Returns current position So you might want to: - send move - wait for the OK response (move is now ij planner) - wait until machine is IDLE (no longer moving) - read the position - send next move
Thanks @Peter Van Der Walt, how would I check that the machine is IDLE? Is it just by polling the '?' command and parsing the result? If this is the case, I can probably just add artificial delays since my application isn't too time sensitive Here's the script (with syntax highlighting and indentation), import serialimport timedef sendCommands(cmds, delay=0): for cmd in cm - Pastebin.com, and also pasted below (sorry, I wasn't sure how to format it). Basically 'sendCommands' parses the string of commands and blocks until it sees an 'ok'. Any help on how to do this properly would be greatly appreciated. Thanks again, import serial import time def sendCommands(cmds, delay=0): for cmd in cmds.strip().splitlines(): cmd = cmd.strip() print('Sending: ' + cmd) cmd = cmd + '\n' s.write(cmd.encode()) # Send g-code block to grbl if (delay != 0): time.sleep(delay) while True: grbl_out_raw = s.readline() grbl_out = grbl_out_raw.decode('utf-8').strip() print(grbl_out) if grbl_out == 'ok': break def homeDevice(): cmd = """ $$ $H G10 P0 L20 X0 Y0 Z0 """ sendCommands(cmd) def pyramidPattern(): cmd='' # Count up to 600 for i in range(100,700,100): cmd += """ G0 X{0} ? """.format(i) # Count down to 100 for i in range(500,0,-100): cmd += """ G0 X{0} ? """.format(i) sendCommands(cmd, delay=0) # Open grbl serial port s = serial.Serial('/dev/cu.usbmodem146401',115200) # Wake up grbl serialCmd = "\r\n\r\n" s.write(serialCmd.encode()) time.sleep(2) # Wait for grbl to initialize s.flushInput() # Flush startup text in serial input homeDevice() pyramidPattern()
Correct, first field From the Grbl Wiki: On mobile at the moment, will check script soon as I am in front of a PC