Safety switch for Laser

is it possible to use one I/O pin and of coarse to check in a loop to block operation when firmware is set to Laser mode?
I think everybody should use a cover around laserbeam for his own safety and let machine only operate when
cover is closed.
touching a rotating mill flute can cut fingers and can be  mostly repaired by doctor but looking even to a reflection of a laserbeam <20mW on a metal surface can damage your eyes irreversible.

So a use of a safety lock is a must , we should not build dangerous machines !

best regards,


  • Sounds like a good idea. Mine is open so I always put on my laser safety glasses.
    I even think a bit further to stop also a print if you have such a pin to check. We could go to blocking input mode so hosts stops sending and moves stop. To be able to continue printing we need to run out the print buffer, so that is not very immediate. Problem is that laser is also controlled by these lines, so we need to tweak a bit there to at least disable laser even if moves continue. Might then ruin the laser cut a bit, but better that then eyes:-)
  • edited April 2016

     What do you think about this :

    just doesn´t execute G-Code when Feature is selected , works fine for me :

    in Repetier.h (i put it to line 249)

    #error You need to define SAFETY_PIN to use Safety Door!

    in Configuration.h (i put it after Case Light)

    #define FEATURE_SAFETY_DOOR true
    #define SAFETY_PIN 69
    #define SAFETY_PIN_PULLUP 1

    in Printer.cpp (i put it after Z-Probe)


    in Commands.cpp

    add to processGcode before switch(com->G)

    if (Printer::mode == PRINTER_MODE_LASER)

    Com::printWarningFLN(PSTR("SAFETY DOOR OPEN"));
    Com::printWarningFLN(PSTR("USE SAFETY GOOGLES"));

    of coarse it doesn´t stop host sending , but it doesnt execute g-codes also from SD without affecting anything else in Firmware .

    only thing i don´t understand , if i set  FEATURE_SAFETY_DOOR false and SAFETY_PIN to -1   i get compiler error because of the READ(SAFETY_PIN),couldn´t find out why ...

    best regards,

  • You can not read pin -1. You need a 
    #if SAFETY_PIN >=0
    around that part.

    But no to the gcode handling alone. We should go to blocking mode to prevent host sending more data in the upper loop.

    Then the question is what we shoudl also do. lcd moves bypass gcode and call move routines directly. But if your hand is on lcd control it is not in machine, so maybe not a problem. laser bust be hardly blocked. Maybe best directly at the driver which checks saftey pin state. I think Id like to add a new flag for safetyMode in Printer class that we can query at different positions and the door open check in the perodicalActions function.

    In safety mode main loop should also prevent executing commands like you suggested. 
  • edited April 2016
    what do you think of checking the pin in command loop and set blocking mode there?

    #ifdef DEBUG_PRINT
            debugWaitLoop = 1;

    // if feature active check pin and set blocking mode here maybe also disable laser driver here

            if(!Printer::isBlockingReceive()) {......

    i also thought about doing it in checkForPeriodicalActions   via eventtimer100ms

    hard blocking laser for my point of view is only possible by hardware via real and-gate
    (sorry for that but I´m Hardware Guy educated in middle 80´s)

    One question to your Laser setup  what kind of Laser do you use and what´s your experience with that stuff?
    I´ played with the Osram 1,6W blue Laser Diode and unfortunatley killed it by disadjusting Optics...
    Beam killed Laser itself...
    Ordered a 3W complete module in US´s on the way

  • edited April 2016
    got stuck now , tried something in command loop, looks not too bad,
    but is there a possibility to stop actions in buffer?
    when i use this , it seems program doesn´t reach the code from my 1st proposal.
    can you please tell me about the order commands are processed?

    #include "Repetier.h"

    const int8_t sensitive_pins[] PROGMEM = SENSITIVE_PINS; // Sensitive pin list for M42
    int Commands::lowestRAMValue = MAX_RAM;
    int Commands::lowestRAMValueSend = MAX_RAM;
    bool BLOCK = false;
    uint8_t laser_intens = LaserDriver::intensity;

    void Commands::commandLoop() {

    while(true) {
    #ifdef DEBUG_PRINT
    debugWaitLoop = 1;


    if ((Printer::mode == PRINTER_MODE_LASER)&&(READ(SAFETY_PIN)))
    LaserDriver::changeIntensity(0);// works immediate!! tested on a single move g1
    //LaserDriver::laserOn = false;// waits until end of move
    Com::printWarningFLN(PSTR("Host blocked"));
    UI_STATUS("Host blocked");
    BLOCK=true;// be shure communication is blocked from here
    if(BLOCK && (!READ(SAFETY_PIN)) )//set blocking back when door closed
    LaserDriver::changeIntensity(laser_intens);//restore laser intensity
    //LaserDriver::laserOn = true;
    if(!Printer::isBlockingReceive()) {
    ... and so on....

    when i just have 1 slow g1 move in buffer it switches off laser immediate.
    when buffer is 32  it flashes until buffer is empty

    that´s what i figured out , dont care i use just simple led for tests

  • I have a 2W blue laser, but not done much with it. Just cut some papers and wood for testing.

    I think you should not really use laserOn here. You should modify in drivers.cpp the set function. With multiple moves each move sets the value again, which is why it reenables. Doing this in laser driver and adding AND door closed or disable laser condition would catch that as well. Plus a fast laser off when door open is detected. 
  • ok, thanks got it running now.just have to clean up now.

    I´m not really shure how the laser driver works, so may be youll find the time to explain the flow.

    when i finished i´ll send a pull request, i also implemented Z-Probe to quick menu just take a look at that stuff.

    best regards
  • Please make pull request against development branch where all new development takes place.

    Flow is quite simple. You set laser on/intensity. All added moves after that store current setting (which is why it reenabled before with moves in buffer). That way you can make changes and they only affect upcoming gcodes and not buffered moves. And since I needed a storage for this I added the same control for fan, so since then fan turns on at the move you placed it.
  • edited April 2016
    OK, hope i´ll get it done correct ,I´m newbie to GITHUB.

    As I´m actually working on a "Finger Safe"   M6 implementation and dont want to use one
    more pin for acknowledge that tool change is done, what means that fingers are away from spindle..
    M6 GCode description says it´s waiting for Cycle Start to be pressed, but there´s nothing said about
    extra button called "Cycle Start".
    my spindle is 1200 W,flutes up to 20mm dia  so it´s an important feature .
    may be i can go via uiwizard , or how can i check for any key pressed without using ui?
    I´m thinking about a flag but i don´t know how to generate/set/reset it.
    maybe you can point me a way

  • another way would be double use of z-probe input.
    we have the possibility to start z-probe cycle by triggering probe, why not use that pin to trigger cycle start also?
    so after toolchange we should also measure tool length, so it might be nice to trigger the same way.
    whats your meaning about that?
  • I never thought about using it so professionally that you switch tools. Also nothing is against it. I agree there should be some button to be hit to continue, so it does not turn on.

    My suggestion is modifying the cnc driver by adding a tool change flag and corresponding commands. essentially calling toolChange() would set flag, disable spindle and enable spindle gets modified to only enable if tool change flag is not set. So involuntary call of it can not start it.

    So now we need a continue button. You can hook up any pin to a button with that command without the ui, but I think better solution for lcd users would be a very simply wizard that only waits for a hit on the "ok" button. Wizards wait indefinitely. The wizard could also be a bit more complex allowing adjusting z with new tool height. Maybe even with a switch so user can select if he wants to z probe or not. I think about a spezial position and measuring z. That normally means a additional z probe with different height and position. So maybe we should modify G30 to measure using that second z probe. 
  • edited April 2016
    If you want to make PCB´s you need different drill bits for example. Usually they have ring on the shaft so you can adjust height by this ring.
    What i just want to do is meet standards when implementing GCodes.For shure there are some variations.
    Description Source for example
    History for my intention:
    Up to now i made Prototype PCB on a homemade machine based on a crosstable with dovetail guides which were
    extremly slow but also precise.
    Machine is conrolled by GRBL on Arduino Nano Plagiate and i developed a Printer unit based on Nano with teacup Firmware
    switching over just by multiplexing Controllers to the xyz drive on the intents of use.
    Toolhead just changeable within 5 minutes.
    worked fine , but as the dovetail guides were made from aluminum they are ready for recycling now... a few hundred operating hours later. Anyway, i learned a lot about mechanics :-)

    My machine now is bigger, faster and "rocksolid" , has nothing to do with the "modified Printers" where milling is in the best
    case a kind of engraving.

    As it´s built for universal purpose I also want the Firmware match the requirements so that´s why i try to bring the ideas in.
    (Maybe including some stupid questions ;-) )
    I "learnt" some programming in Turbo Pascal 4/5(long long time ago) , did not continue for many years  so knowledge got lost.
    So on this way I´m happy to have the chance of learning by doing useful things.

    but back to beginning,
    if working with z-probe to measure tool lenght or z-height etc. it´s important to have a moveable probe.
    I just use a piece of printed board with known height  (offset). Tool is connected to ground , Z-Input via Optocoupler
    to Z-Probe input. cheap solution, works precise and by using opto also safe (for controller) and without crosstalk.
    that´s also my z-probe for printing, just connect hotend to gnd.

    I agree with a modified G30 , i´m also happy with a modified G29 which i already have because of heating stuff.
    i use it after nozzle change for example.

    I think also of implementing M7 to 9 for additional hardware like vacuum cleaner for example.

    Lots of possibilities and of coarse lots of buttons... thats why i was so fixed on the I2C routines.
    but step by step.
    Think i´ll  get the M6 done this weekend and send a pull request against Development branch including
    the Safety Switch and Z-Probe start via Quickmenu.
    I´ll include the modified G29 also in a seperate file maybe you can take a look on it , i have no delta printer for testing.

  • What should G29 do in CNC case? It is computing average z height from 3 points. 

    With the movable z probe you are right in that you need the surface origin. I guess thats why my z probe switch is also only a switch with long cord and a flat surface to hit:-) But the problem of the right position and then even right z position remains.

    I guess the flow is like this
    1. g-code adds M6 where toolchange is needed
    2. Stop CNC go up to change tool and hope position does not change in xy
    3. Go to a position where you can measure z=0
    4. Go back to M6 start position
    5. enable mill
    6. Continue

    That all must be handled in M6, which is the main problem I think. For some of this the manual control would also be a nice way to go to positions.
  • the G29 i modified just takes actual point without x/y move. i did that to keep the heating stuff for printer.
    was just an example..(i just use it from a button)

    the M6 code is just " a break "  in gcode, that shows what tool has to be used next needs an acknowledge by button when finished.
    so it´s not too hard to implement,just : stop executing code-->> show message-->> wait for ack-->> continue

    so description from linux cnc :

    LinuxCNC includes a userspace HAL component called hal_manualtoolchange,
    which shows a window prompt telling you what tool is expected when a
    M6 command is issued. After the OK button is pressed, execution of
    the program will continue.

    The hal_manualtoolchange component includes a hal pin for a button that
    can be connected to a physical button to complete the tool change and
    remove the window prompt (hal_manualtoolchange.change_button).

    measuring tool lenght for example in GRBL used is G38.2

    so the flow in GCode for a tool change is not a single M6 , it looks as follows:
    (snippet of Drill file i used on GRBL generated via
    (Copyright 2005 - 2012 by John Johnson)

    ...executed code

    G01 Z-2.1000 F200.00
    G00 Z2.0000
    M05                                  //spindle stopped here
    G00 Z50.0000                    //move Z up  
    G00 X0.0000 Y0.0000        // go to defined xy position
    M06 T02  ; 0.8128               // M6 just says "change the tool " and waits for ack
    M03                                  // continue
    G04 P0.500000
    G00 X-20.3200 Y29.2100
    G01 Z-2.1000 F200.00

    So that works without tool length measurement because of my drill bits all have same Z-length adjusted by ring.

    Spindle control is done outside of M6 BUT:
    some people generate their gcode by hand(me also sometimes)  ,a forgotten "M5" will keep spindle running and i think its not bad to switch off (even when its already off) and block the spindle before acknowledge by button for safety reasons.
    there will be no change for operation.

    Example for G-code tool length measurement
    G00 z50.2

    G00 X0.0000 Y0.0000

    M00                               //break

    G00 Z50

    G38.2 z-50 f100              // move z down until triggered

    G92 Z1.75                      // set Z-Offset (probe thickness in this case)

    G0 z10                          //move z up

    M00                              // end of break

    G0 z5


    there are a lot of combinations possible to get same result , but hopefully i have the chance to ask an experienced

    CNC Programmer next week, i want to get as much information as possible for a safe operation.

    Also there are quite huge differences in availability of G or M- codes depemding on the software you use.

    (for example Mach3 , Linux CNC , CamBam etc.)

    From my point of view everyone using software to generate the code should be able to read and understand the code in file.

    simulators are also useful.

    manual movement is also a "nice to have" especially for finding workpiece offsets.

    i did that via analog joystick on analog inputs , refer my post manual positioning / Jogwheel  dated March 6

    ( works good but it´s improvable for shure , will see during working with that).

  • I never stop learning G38.2 with a point is new to me. In fact we can not do fractional G codes:-)

    So as I see it is up the user to generate code to reprobe tool height if required (which is for most I think). That function should also include a message so you know when to place the z probe. But it is the same as M6 with different message.
  • so that´s how it´s implemented in GRBL also found reference in LINUX CNC. and REPRAP WIKI.

    Let me see what CNC Programmer says next week , for the next days i´ll switch over to hardware design , Toys from China arrived today :-)

  • Why can we not handle The G-code as float value?
    so we can read the coordinates also as a float value.

    There are many G-Codes specified as fractional numbers.

    just for example:

     G29  G29.1 G29.2 G38 G38.1 G38.2  G41 G41.1 G43 G43.1 G43.2G92 G92.1 G92.2

    I don´t actually know if there is a need for that stuff but may be it should be possible to implement that in future.

    one other question regarding Z-Probe :

    when i run G29 S2 Z-Probe   it does everything ok , also new value is stored in Eeprom.
    when i run G28 after that , Z height still shows old value in Display , changes to new one after Hardware reset only.

  • The binary format defines M and G as 8 or 16 bit integer. No 3d printer firmware uses fractional gcodes. I think these fractional codes are a vendor way to add new non standard behaviour on default gcodes.

    With z are you speaking about host display or printer lcd? That might be a difference as host has it's own z max stored and only copies homing end coordinates if no job is running. If you see into the code

                    if(ok) {

                        sum *= 0.33333333333333;

                        Com::printFLN(Com::tZProbeAverage, sum);

                        if(com->hasS() && com->S) {




                            Printer::zLength += sum - Printer::currentPosition[Z_AXIS];




                            Printer::currentPositionSteps[Z_AXIS] = sum * Printer::axisStepsPerMM[Z_AXIS];

                            float zup = Printer::runZMaxProbe();

                            if(zup == ILLEGAL_Z_PROBE) {

    ok = false;

                            } else

                            Printer::zLength = zup + sum - ENDSTOP_Z_BACK_ON_HOME;

    #endif // DELTA




                            Printer::currentPositionSteps[Z_AXIS] = sum * Printer::axisStepsPerMM[Z_AXIS];

                            Com::printFLN(PSTR("Adjusted z origin"));

    #endif // max z endstop


                        Printer::feedrate = oldFeedrate;


                        if(ok && com->hasS() && com->S == 2)



    you see save to eeprom stores current zength, so it must somehow already be set correct. But where do you see new z height or do you mean z position after homing which should be identical?

  • edited April 2016
    You write "No 3d printer firmware uses fractional gcodes", so there seem to be some different styles of G-Code regarding CNC / REPRAP . My target is to have universal machine that can also operate CNC Standard code that´s why i asked
    for the fractional codes.
    So for example the reprap G29 S2  is G29.2 in CNC.
    As there are not too many Codes with fraction i think it can be solved by postprocessor in cam Software.
    Even Cam softwares seem to have a kind of "dialect" for me i can figure that out.
    May be i can take a look at DIN66025 in my office , i hope i get get access authorization.
    Even the DIN is just our german standard it might give me some more information.think i opened a big barrel
    for my "universal " solution so it´s time to make compromise ;-)

    regarding the z-probe:
    Homing dir ZMAX
    for example i set Zmax to 200.0 ican see 200.000 in Eeprom(via Repetier Host)  then i run  G92 S2
    if i go to EEprom again i can see 200.120 so Z-probe is updated and set to the new value.
    If i now run g28  z on host shows 200.12  and LCD shows 200.00

    after hardware reset and G28 both show 200.12

    can that happen if i have set  max_software_endstop_z true?

    cannot check it at the moment, long print running , I´ll check it tomorrow

  • The CAM software I use has an editor where I have to set how my gcode is interpreted and what commands to use for this and that. Then it generates the right format. As far as I know does each vendor has it's special codes that vary from standard.

    There is no G92 S2 and G92 never changes eeprom, only current offsets.
  • edited April 2016
    Sorry Typo , G29 of coarse

    which cam software do you use?
Sign In or Register to comment.