BTW this is correct in terms of TOOL movement, +X movement moves the tool, the blade in this case, to the right (-: view the saw stop like a moving mill table .... tool right (X+) is table left.
Then I would use a spacer of about 6". The actual size does not matter so long as you can measure it accurately. Lets a say it measures at 6.127 inches Home put spacer against blade jog sawstop up to spacer. now we need to tell the controller that X0 is 6.127" away from where we are now. refer to G Codes G20 G10 L20 P0 X6.127 G20 ; use inches for measurements G10 L20 ; set coordinates P0 ; set for current work coordinate system X6.127 ; set X to believe that current position is 6.127" Note: if you ever hit 'goto0' the stop is going to hit the idler pulley. you probably want to put a limit switch there so it stops safely. You can make a Gcode macro for this so you don't have to remember all the numbers.
I think I understand. I didn’t have but about ten minutes at the saw yesterday, but I did try the suggestion to It worked as expected until I homed the sawstop and then it was all out of wack. I am thinking because the P0 wasn’t added to the command line it didn’t set it as work coordinates? So, when I rehomed, it reverted back to whatever my previous work coordinates were. Does this sound right? thanks for the explanation makes sense! Thanks!
It should still take without P0. Are you sure you Homed initially (before storing the offset - otherwise storing an offset on an unhomed axis, is to be expected to be invalid after homing) So: 1) Home (so the machine knows where that switch is) 2) Set origin (stored as offset from Home) 3) Rehome (restores stored origin)
I thought that I did, but I will give it a shot again… I was in a hurry… I know this is a basic simple question, but I can’t figure it out. I am playing around with the script you wrote for the macro trying to understand it. I can’t figure out how to change the button heights. I can change the widths to where they are even larger than the whole displayed screen of the macro but I can’t seem to figure out how to change button height. Also, can the macro screen be made larger? thanks!
power on, then home. always always always home after power on or reset, before doing anything else. without a proper sense of home, other settings cannot make sense.
Predefined CSS in metro: Metro4 Buttons Documentation I'm using the "large" className there You can perhaps inject with the CSS !important Property to override the built in CSS (not tested): Code: .keypadBtn {width: 80px; height: 80px !important} When you create the Metro Dialog Code: Metro.dialog.create({ title: "Saw Stop Macro", width: '90%'... You can pass it Width (and some other parameters, see Metro4 Dialogs Documentation
I was able to get it to work seemingly correct in my brief time at the saw, but I had to use this entire line: G20 G10 L20 P0 X10 The homing is not putting exactly on my external scale where it should. If the read out says it is on 88.52, it is actually on my external scale at 88.45. This could possibly still be in what @Peter Van Der Walt described as the mechanical issue discussed earlier. Or, Could it be in part of my settings for the feed rate when homing, or moving away from switch, or distance to clear the switch? I played around with the code and the line suggested to change in order to change the size of the height of the button. However, I can't get it to change heights. It appears most all of the buttons on the main UI of CONTROL have the same button heights as the ones in the macro, but the jog buttons appear to be larger than all others. So , I assume this means it can be done. I looked through the main CONTROL code here: OpenBuilds-CONTROL/app at master · OpenBuilds/OpenBuilds-CONTROL to see if I could figure out how they did it, but I can't find where the buttons are created in these files. Thanks!
The jogbuttons in CONTROL scale according to the content on the button: See OpenBuilds-CONTROL/index.html at 79c0a05f258c381260f2fc82d3fc8634338d0e6f · OpenBuilds/OpenBuilds-CONTROL for example for the X- button, using Font Awesome Layers to stack the icon and text Or the tape is wrong? Tape measure - Wikipedia (Did you buy a Class I or a Class III? ) But looking at the earlier video of the mechanism itself. ot could be belt-droop pulling it off position, or just inaccuracies in the mechanism itself too. It's not a leadscrew driven C-Beam after all
You are using a belt. Belt length varies with tension. Tension varies with temperature. And it is all mounted to wood, which also changes size with temperature and humidity. But, many messages back Peter advised that you calibrate the mechanism, so before going any further you need to do that. There is a wizard for it in OBControl under Wizards and Tools. Calibrate over the longest distance you can accurately measure. The steps per millimeter calibration is in millimeters no matter what mode you display, so grab a pocket calculator and multiply your inches by 25.4 for perfect conversion. and don't round off, use as many decimal digits as will fit.
I will calibrate again, but I did calibrate using control earlier. However, I don’t think it is the calibration. The movements are dead on accurate in one direction. The inaccuracy I described above is only when homing. After homing (which may not be dead on the number displayed in Control) each move in one direction is perfect. Ex. After homing, if the external scale reads 88.45 and the control display reads 88.52(I don’t really have an exact way of knowing where this decimal is there could be slight error in reading this), and I turn power to steppers off and to move the stop to the position that is displayed in control (88.52); turn the steppers back on and make a move; the move is perfect in one direction. And I can move back and forth and every move in one direction is perfect. In the other direction it is slightly off. I think Peter is right, it is something mechanical. My belt is pretty tight (although I don’t know how to gauge or know how tight it should be) I think it could be the gear spinning on the stepper shaft under a load as he said earlier. Not sure why it’s only in one direction, but those small set screws are a pain to tighten on the gear. I have them as tight as i could get them, but I still think it could be an issue. Is there a better way to fasten them down? I really need more time at it to try and get it perfected, but I am very happy with where it is at to this point, and I am appreciative of all the help! I am playing around with the js code @Peter Van Der Walt provided, and I have made a couple of changes (personal preference changes) I think I will like. I will post later so if anyone is interested it will be available. Thanks!!
The number displayed is only an offset from where setzero was last used. Depending on how good your limit switch is, it may vary by many thousandths of an inch every time you home. A 'good' switch will trigger within 0.001" every time. if you turn power off the controller has no idea where anything is anymore, and then homing and setting an accurate 0 offset is pointless. Also, this brings on danger in that a move which should stop at 20" will now only stop at 6" from the blade, thus pushing your hand/arm whatever INTO the blade. Don't do it. perfect in one direction means 'backlash'. Do the teeth on the belt mesh perfectly with the teeth on the motor pulley? Is the belt tight enough? At least one screw on the pulley must go onto the flat on the motor shaft. If there is no flat on the shaft, then make one (be careful to keep the grinding grit out of the bearings and off the magnets) A fishing spring balance will let you pull on the belt to a known tension. I set my GT2 belts to 12kg. Is that enough for yours? I don't know, but at least it is repeatable (-: https://www.amazon.com/Luggage-Fishing-Balance-Weighing-Measuring/dp/B077ZVXF98 [/QUOTE]
See earlier in thread: Direct link to the post: NickEng's Sawstop Grbl interface / coding (well, not pictures, but Moving Pictures are better right)
I will post a better video when I get it closer to finished. But, I am going to admit, none of my work nor this setup are aesthetically pleasing, but I hope for it to be functional. Maybe someone with more knowledge and experience can use some of the provided info to create a better design. I am still struggling my way through the design and the script to create what I want. I have been able to increase the size of the buttons and maneuver them around. I am still struggling to figure out how to increase the size of the dialogue of the macro created by @Peter Van Der Walt. I did make a change to it so that when a value is input and sent to gcode the sawstopvalue is set to 0. This allows you to make the next move without clearing the previous value. I ordered the pnuematic cylinder and a valve, but I’m not sure the best way to implement it. The problem I am seeing is with one valve and the cylinder, even with a spring, the retraction of the cylinder will require air being released between the cylinder and the valve. The only way I can think to do this is to add a tee and second valve on the cylinder side of the valve I have. It would need to open, and let the “trapped” air (between the cylinder and output side of valve)out so that the piston could retract and allow the saw stop to move. It would serve basically as a relief valve. Is there a better way to do this? What am I missing? I haven’t gotten a chance to check these, but I will. It is ugly, but here is what I have to this point with editing the macro script: // Add some CSS classes $("<style type='text/css'> .keypadBtn {width: 45px; height: 300px;} .sawStopKeypadBtn {width:140px;} .sawStopActionBtn {width: 300px; } </style>").appendTo("head"); // variables placeholder window.sawStopValue = 0.0; window.sawStopFractionValue = 0; // Update the UI <span> fields to display value window.updateSawStopValueUI = setInterval(function() { $("#sawStopValue").html(sawStopValue.toFixed(0)); if (sawStopFractionValue.length > 1) { $("#sawStopFraction").html(" and " + sawStopFractionValue); } else { $("#sawStopFraction").html(""); } }, 50); // keypad button window.sawStopBtn = function(val) { var currentValue = sawStopValue.toString(); currentValue += val; sawStopValue = parseInt(currentValue); } // fraction button window.sawStopFraction = function(val) { sawStopFractionValue = val; } // backspace button window.sawStopBackSpace = function() { var sawStopcurrentValue = sawStopValue.toString(); var sawStopNewValue = sawStopcurrentValue.slice(0, -1); if (sawStopNewValue.length == 0) { sawStopNewValue = "0"; } sawStopValue = parseInt(sawStopNewValue); } window.sawStopMoveTo = function() { // Calculate Decimals from fractions if (sawStopFractionValue.length > 1) { var sawStopFractionSplit = sawStopFractionValue.split("/"); var sawStopDecimals = parseInt(sawStopFractionSplit[0], 10) / parseInt(sawStopFractionSplit[1], 10); var decimalSawStopFractionValue = eval(sawStopFractionValue); } else { var decimalSawStopFractionValue = 0; } // add decimals to integers var sawStopFinalPosition = sawStopValue + decimalSawStopFractionValue; // Send move command to Grbl sendGcode("$J=G90 G20 X" + sawStopFinalPosition + " F10000"); sawStopValue = 0; sawStopFractionValue = 0; } // Create the User Interface Metro.dialog.create({ title: "Saw Stop Macro", width: '960', content: ` <span class="display3" id="sawStopValue">0</span> <span class="display3" id="sawStopFraction"></span> <span class="display2"> inch</span> <div id="sawStopNumbersUI"> <table class="table striped compact"> <tr> <td> <table> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(1);">1</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(2);">2</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(3);">3</button></td> <span class="fa-layers fa-fw"> </tr> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(4);">4</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(5);">5</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(6);">6</button></td> <span class="fa-layers fa-fw"> </tr> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(7);">7</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(8);">8</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(9);">9</button></td> <span class="fa-layers fa-fw"> </tr> <tr> <td></td> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBtn(0);">0</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopBackSpace();"><i class="fas fa-arrow-left"></i></button></td> <span class="fa-layers fa-fw"> </tr> </table> </td> <td> <table> <tr> <td colspan="2"> <hr> </td> </tr> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('1/16');">1/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('1/8');">1/8</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('3/16');">3/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('1/4');">1/4</button></td> <span class="fa-layers fa-fw"> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('5/16');">5/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('3/8');">3/8</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('7/16');">7/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('1/2');">1/2</button></td> <span class="fa-layers fa-fw"> </tr> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('9/16');">9/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('5/8');">5/8</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('11/16');">11/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('3/4');">3/4</button></td> <span class="fa-layers fa-fw"> </tr> <tr> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('13/16');">13/16</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('7/8');">7/8</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopKeypadBtn" onclick="sawStopFraction('15/16');">15/16</button></td> <span class="fa-layers fa-fw"> </div> </table> </tr> <tr> <hr> <td><button class="button outline xlarge m-0 sawStopActionBtn alert" onclick="sawStopValue=0; sawStopFractionValue=0;">CLEAR</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopActionBtn success" onclick="sawStopMoveTo();">MOVE TO</button></td> <span class="fa-layers fa-fw"> </tr> <hr> <tr> <td><button class="button outline xlarge m-0 sawStopActionBtn secondary" onclick="sendGcode('$H');">HOME</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopActionBtn secondary" onclick="sendGcode('G10 P0 L20 X0');">SETZERO</button></td> <span class="fa-layers fa-fw"> </tr> <hr> <tr> <td><button class="button outline xlarge m-0 sawStopActionBtn warning" onclick="sendGcode('M8');">APPLY BRAKE</button></td> <span class="fa-layers fa-fw"> <td><button class="button outline xlarge m-0 sawStopActionBtn primary" onclick="sendGcode('M9');">RELEASE BRAKE</button></td> <span class="fa-layers fa-fw"> </tr> `, actions: [{ caption: "Exit Macro", cls: "js-dialog-close alert", onclick: function() { printLog("Saw Stop Macro Exited") } }] }); Thanks!
Pick the right solenoid. For example a 5/2 according to https://upmation.com/directional-control-valve/ (just off a quick google search) Comes with double action and exhaust ports. A visit to a industrial supply will maybe be better than shopping online. Lots of industrial doodads has clamp and then release needs, its a classic use case and basically a "solved problem"
Ok, I ordered a 5/2. We don't have an industrial supply near where I am located. I have still been fooling with the macro code. I have added a button for jogging like is on the main control screen, but I'm not sure what function needs to be called when the button is clicked. Also, what is needed to continuously move as long as the jog button is pressed? I found some of the code for jogging in the main CONTROL code, but it seems fairly complex. I'm hoping it want be that complicated to add. Thanks!
Honestly, I was expecting this to be a hack and automation of the Sawstop table saw... but the project itself is pretty cool non the less. The principals are probably the same, and Jeremy Fielding on youtube did a servo driven fence.. it might help you.
wow, yes, I just watched a video of his. Very impressive. This project is no where near as well built as his. I do like the idea, and hopefully one day can do something similar. I think control and grbl could be used to do what he is doing from the software/coding/electrical side of things. Possibly even utilizing a blackbox? Although, I am still struggling a bit with the code. @Peter Van Der Walt, is there a simple way to add jogging functionality to the macro like what is on the main control interface? I have created the buttons for it, but what function needs to be called when the jog button is pressed? For my application, I think I only want the continuous jog mode. Thanks!
I have on the todolist to add a "drop in" jog pad you can import - but no time to work on that right away For now, borrow the mini jog buttons from the Probe wizard? OpenBuilds-CONTROL/index.html at master · OpenBuilds/OpenBuilds-CONTROL as it does continuous If you want to see the logic behind continous see OpenBuilds-CONTROL/jog.js at master · OpenBuilds/OpenBuilds-CONTROL
I took a look at them, but I am a little lost as to how I call the function needed to make the gcode send when continuously holding down the x+ or x- buttons. If I paste the code below in my current macro code, how do I make a button press run the function? P.S. I can't find code tags $('.xM').on('touchstart mousedown', function(ev) { console.log(ev) if (ev.which > 1) { return } ev.preventDefault(); var hasSoftLimits = false; if (Object.keys(grblParams).length > 0) { if (parseInt(grblParams.$20) == 1) { hasSoftLimits = true; } } if (allowContinuousJog) { // startJog(); if (!waitingForStatus && laststatus.comms.runStatus == "Idle" || laststatus.comms.runStatus == "Door:0") { var direction = "X-"; var distance = 1000; if (hasSoftLimits) { // Soft Limits is enabled so lets calculate maximum move distance var mindistance = parseInt(grblParams.$130) var maxdistance = 0; // Grbl all negative coordinates // Negative move: distance = (mindistance + (parseFloat(laststatus.machine.position.offset.x) + parseFloat(laststatus.machine.position.work.x))) - 1 distance = distance.toFixed(3); if (distance < 1) { toastJogWillHit("X-"); } } if (distance >= 1) { socket.emit('runCommand', "$J=G91 G21 " + direction + distance + " F" + jogRateX + "\n"); continuousJogRunning = true; waitingForStatus = true; $('.xM').click(); } } else { toastJogNotIdle(); } } else { jog('X', '-' + jogdist, jogRateX); } $('#runNewProbeBtn').addClass("disabled") $('#confirmNewProbeBtn').removeClass("disabled") }); $('.xM').on('touchend mouseup', function(ev) { ev.preventDefault(); if (allowContinuousJog) { cancelJog() } }); $('.xP').on('touchstart mousedown', function(ev) { // console.log("xp down") if (ev.which > 1) { return } ev.preventDefault(); var hasSoftLimits = false; if (Object.keys(grblParams).length > 0) { if (parseInt(grblParams.$20) == 1) { hasSoftLimits = true; } } if (allowContinuousJog) { // startJog(); if (!waitingForStatus && laststatus.comms.runStatus == "Idle" || laststatus.comms.runStatus == "Door:0") { var direction = "X"; var distance = 1000; if (hasSoftLimits) { // Soft Limits is enabled so lets calculate maximum move distance var mindistance = parseInt(grblParams.$130) var maxdistance = 0; // Grbl all negative coordinates // Positive move: distance = (maxdistance - (parseFloat(laststatus.machine.position.offset.x) + parseFloat(laststatus.machine.position.work.x))) - 1 distance = distance.toFixed(3); if (distance < 1) { toastJogWillHit("X+"); } } if (distance >= 1) { socket.emit('runCommand', "$J=G91 G21 " + direction + distance + " F" + jogRateX + "\n"); continuousJogRunning = true; waitingForStatus = true; $('.xP').click(); } } else { toastJogNotIdle(); } } else { jog('X', jogdist, jogRateX); } $('#runNewProbeBtn').addClass("disabled") $('#confirmNewProbeBtn').removeClass("disabled") }); $('.xP').on('touchend mouseup', function(ev) { // console.log("xp up") ev.preventDefault(); if (allowContinuousJog) { cancelJog() } }); THANKS!
Ok, I have been hacking my way through the openbuild resource code @Peter Van Der Walt has thankfully provided. It is tough for me. I am new to JS, HTML, CSS. I'm not even sure which I am using/copying/reading most of the time. However, I have made some progress. The more I do, the more I think I want. I am pasting the code and a screen shot of what the macro looks like to this point. I know with the latest addition the continuous jog feature there are a couple of issues. 1. I probably have way too much code than what is needed for the single axis functionality. I took out a lot of the Y and Z, but some I wasn't sure if it was needed or not. I left a few things in that may be beneficial with later additions (DRO of location of sawStop) and (KeyPad entry of desired location) 2. I really want the pneumatic cylinder to lock/unlock automatically with a move. However, I am not sure the best way to handle this with the jog buttons. In order to automatically lock/unlock the sawStop pneumatic cylinder, I am hoping to use the m8/m9 commands. I haven't gotten all of my stuff in to physically try using m8/m9 to do this, but I took a stab at it in code with this bit: This seems like it may work for unlocking, but I'm not sure how to tell when to lock? Or, will it parse the m9 command until the move is complete before executing the m9? Here is a screen shot of the macro to this point: I'd still like to get it to full screen size or have the option to make it full screen, but I've yet to figure that out. Here is the code for it: THANKS!
I could give you the answer but rather, i'll tell you a) try it and see. Hook up a led or multimeter to the coolant output and see for yourself or b) read the Grbl Wiki to learn which commands are realtime, which are not (queued) and also c) learn more about the G4 command too - not only as a delay, but also as a tool to sync the buffer Metro.dialog doesn't have a full screen div, so that's a lot of CSS hacking. Might be easier to just use jquery to add your own 100%/100% div with a high Z index over it all. Replacing metro.dialog
The M8 and M9 commands don't que They are realtime. This isn't good for my application I don't think. I see where I could use a "G4 P1000" for unlocking before a move, but it would be a guessing game for the locking feature. I suppose I could determine how long it takes for my longest move and have a delay of that length set prior to locking, but this seems inefficient. Thanks!
Grbl v1.1 Commands · gnea/grbl Wiki says the realtime Flood coolant command is 0xA0 (Does not say M8 is realtime) "For certain commands, like G4 dwell or M3/4/5 spindle control, Grbl has to empty its buffer to finish all motions in queue to execute the command on-time and as programmed" Pretty sure M8 falls under that... Even it it doesn't a G4P0.1 will be enough to force the queue to catch up
I have been away and unable to work on the project. However, I just tried the above suggestion, but I am apparently not understanding, or it isn't working as expected. If I send any jog command, and I send any of the above commands (while the machine is jogging) I get an error 9 "gCode is locked out durring alarm or jog state [G4P0.1]" I have tried the following commands while it is jogging and each send the same error: G4P0.1 M8 M9 0xA0 The function I used for the macro that I thought was going to work looks like this: // Send move command to Grbl sendGcode("m9"); //unlock pnuematic cylinder sendGcode("G4P0.1"); sendGcode("$J=G90 G20 X" + sawStopFinalPosition + " F10000"); // move to position currentPositionValue = sawStopValue; // save value to display current position currentFractionValue = sawStopFractionValue; // save fraction value to display current position sawStopValue = 0; //reset value to prepare for next entered distance sawStopFractionValue = 0; //reset fraction value to prepare for next entered distance sendGcode("G4P0.1");//delay until move is complete all gcodes are executed sendGcode("m8"); //lock cylinder Any idea what I am doing wrong? Thanks!
If I try that exactly, I get this error: error1 Gcode words consist of a letter and a value. Letter was not found. This doesn't work either: sendGcode("$J=G90 G20 X" + sawStopFinalPosition + " F10000 \n M8"); // move to position Thanks!
Try G0 instead of Jog. Technically that is a positioning move, not a jog. Also try runJob instead of sendGcode, as a bunch of commands are more like a job so let CONTROL handle it through its character counting queue thats part of runJob