terjeio / grblHAL

This repo has moved to a new home https://github.com/grblHAL
232 stars 90 forks source link

Adding custom features for the CNC machine #240

Closed krupis closed 3 years ago

krupis commented 3 years ago

Hello. I would like to learn more about adding new/custom features for my CNC setup. I am considering whether I should modify the G-code sender program ( running on my Raspberry PI or modify grbl software ).

For example I would like to implement some additional features/sensors that I must monitor before I start the g code.

Lets say I upload a g code and when user press start to start milling, I must do some additional checks, monitor some sensor values and if everything is alright start milling, if some sensors returned a bad value, I do not want to start milling. Can someone give me some tips on how do I modify and add such behaviour?

terjeio commented 3 years ago

Check out the tool change code, this takes over cycle start handling dynamically:

https://github.com/terjeio/grblHAL/blob/bacab4acffd006f9f4b6484fdfbe106c74ebc0fd/grbl/tool_change.c#L313-L318

It is possible to do it statically on startup/reset in a plugin as well. On cycle start do your checks, if ok pass on to the original function, if not raise an alarm?

krupis commented 3 years ago

Thanks for the response. I have been learning a little bit more and trying to understand what you said.

Since I am using ESP32 , In the ESP32 folder -> grbl I have found my_plugin.c and I assume thats where I put my program?

image

However, thats still not clear for me how do I handle at which point do I execute my code? Since I always want to monitor the sensors right before the start of milling.

I would assume I need to know which part of the code gets executed when a user initiates the milling through g code sender program and then modify that part of code instead of immediately start milling do a sensor check and only then start milling.

For example skeleton code:

- START milling command received from bCNC program
- if(temperature <30){
-   Cycle_start()
- }
- else{
- Raise_alarm() (Ideally I should be able to display some error message "temperature too high" but not essential )
- }

And now it is something like?

-START milling command received from bCNC program
-Cycle_start()

I assume it is not that straight forward as above but is just an example

terjeio commented 3 years ago

Since I am using ESP32 , In the ESP32 folder -> grbl I have found my_plugin.c and I assume thats where I put my program?

No leave that one alone - add yours in the same folder as driver.c, it will automatically override my_plugin_init() in _grbl/myplugin.c as is defined as weak. And this way yours will not be overwritten on a source update.

However, thats still not clear for me how do I handle at which point do I execute my code?

I was a bit quick in my first reply. To detect a regular start of a program you have trap that separately. This can be done in a number of ways, the easiest would be to add a custom M-code to _myplugin.c?

Another way would be to redirect the serial input stream (hal.stream.read) to your code before passing it on: You may then use % (percent character) to indicate start of code (if the sender allows it), or even parse the gcode yourself for whatever start marker you want to use.

It is also possible to subscribe to core events but I believe currently none is suitable for your purpose. Another one could/should be added?

https://github.com/terjeio/grblHAL/blob/e41177bdec206b08d582fa1c657eacf7e963925d/grbl/hal.h#L348-L369

krupis commented 3 years ago

Ok, so my driver.c is located in drivers -> ESP32 folder. Since there are no my_plugin.c file in here, do I just copy and paste the my_plugin.c in there from grblHAL/templates/my_plugin.c and remove the weak attribute to start with?

/*
  my_plugin.c - An embedded CNC Controller with rs274/ngc (g-code) support
  "Dummy" user plugin init, called if no user plugin is provided.
  Part of grblHAL
  Copyright (c) 2020 Terje Io
  Grbl is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  Grbl is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
*/

__attribute__((weak)) void my_plugin_init (void)
{
    // NOOP
}

I was under the impression that this should be way more simple to do. I have imagined that somewhere in grblHAL there is a piece of code that starts the g code so I would just write an if statement above that piece of code and do one extra check, I guess I was wrong!

terjeio commented 3 years ago

I have imagined that somewhere in grblHAL there is a piece of code that starts the g code so I would just write an if statement above that piece of code and do one extra check, I guess I was wrong!

Well, at least you can hook code into grblHAL without touching the original source - that is not possible with vanilla grbl or the ports that I know of.

Motion is started by calling mc_line() in _motioncontrol.c - I have not made it possible to redirect that to user code and I am not sure I want to do that either. You can of course modify mc_line() to see if that is easier to handle. However, you will not be able to recheck there on a cycle start after a hold if that is needed.

https://github.com/terjeio/grblHAL/blob/e41177bdec206b08d582fa1c657eacf7e963925d/grbl/motion_control.c#L96

If you fail a startup at this stage I guess you have to ensure a soft reset so that internal data is kept consistent, or at least sync the current position back to the parser copy. IMO it is "cleaner" to stop execution before any gcode has been processed by the parser and sent to the motion controller.

krupis commented 3 years ago

Hmm. So I definately want to stop execution before any of the gcode has been executed. If you said that the motion ( g -code execution ) is started by calling mc_line(), would something like that be correct?

if(temperature <30){ mc_line() } else{ execute feed_hold or restart? }

I can see that this going to be very difficult since I have not written any of the code therefore It is very hard for me to follow and understand especially with lack of this type of programming experience?

I had a look at motion_control.c and I see a function mc_line declaration, but where exactly it is being called for the first during the program? Maybe if I know that I can write my code there?

From what I understand, modifying mc_line function and putting my code in there is not going to be good idea ? I must do my checks before this function is executed?

krupis commented 3 years ago

The more I think about it, the more I am considering to modify the G-code sender program instead of GRBL. Since I use raspberry PI and bCNC. Maybe it would make more sense to implement my custom code into bCNC script and before the gcode is sent to the ESP32 from the Raspberry PI, I would do my sensor checks.