MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.34k stars 19.26k forks source link

[FR]Lcd Stop button as reset #8994

Closed Witgang closed 6 years ago

Witgang commented 6 years ago

I just finished printing a box for my ramps board and LCD and if i put it all together the reset button on the arduino board will be out of reach, but the one on the LCD is already incorporated in the design https://www.thingiverse.com/thing:1874156

so from now on when thermal runaway is triggered i'm only left with the power button to work as a reset which i don't quite like to trigger since it turns the whole PSU off then on.

is there a way to make the stop button on the lcd act as the rest on the arduino trough software? or do i have make "changes" to the hardware?

cjsoong commented 6 years ago

marlin_main.cpp

 #if HAS_KILL

    // Check if the kill button was pressed and wait just in case it was an accidental
    // key kill key press
    // -------------------------------------------------------------------------------
    static int killCount = 0;   // make the inactivity button a bit less responsive
    const int KILL_DELAY = 750;
    if (!READ(KILL_PIN))
      killCount++;
    else if (killCount > 0)
      killCount--;

    // Exceeded threshold and we can confirm that it was not accidental
    // KILL the machine
    // ----------------------------------------------------------------
    if (killCount >= KILL_DELAY) {
      SERIAL_ERROR_START();
      SERIAL_ERRORLNPGM(MSG_KILL_BUTTON);
      kill(PSTR(MSG_KILLED));
    }
 /* KILL KEY= RESET */
    if (!READ(KILL_PIN)) 
        {
           wdt_enable(WDTO_60MS);
           while(1) {}
         }
/*********************************************/**
  #endif
tcm0116 commented 6 years ago

I think what @Witgang is getting at is the kill pin doesn't actually reset the Arduino. It basically causes Marlin to shut everything down and then go into an infinite loop.

It may be possible to reset the Arduino via reset command, but it'd take some research. An alternate approach is to simply disconnect and reconnect the host software that's being used to control the printer. This should cause the Arduino to reset. Here's some info on the Auruino auto reset, if you're interested:

http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

Witgang commented 6 years ago

yes you are right @tcm0116 , i don't know exactly why the kill pin behaves like that instead of a reset. it's probably an unfinished feature and this works as a placeholder until they have time to revise it and make it work as a reset button. or if some desire it's current function too maybe make it so you have to press it another time after it goes into the loop

Witgang commented 6 years ago

after some research the code @cjsoong provided should work the same way although i do pray that after reset the wdt is not enabled. i'll put that in and see how it goes for a while. thank you for help!

fiveangle commented 6 years ago

If you use Octoprint, you can use the ACTION_ON_KILL feature to send action to OP then have OP perform the operation via plugin @benlye wrote: https://plugins.octoprint.org/plugins/actioncommands/

-=dave

Witgang commented 6 years ago

i had the time to implement and test the code provided by @cjsoong and it seems to work ok, as soon as i press the kill button it will reset which is what i wanted , don't think i will need to mess up with the timings to trigger that since it's a really small button i have on my case and quite hard to trigger accidentally . so thank you @cjsoong for your help on this:)

fiveangle commented 6 years ago

I tried the code and it did not work 🤷‍♂️ - I wonder if it may be due to me being on AT90USB ?

I think this is something a lot of others may also want. Maybe submit a PR once you have it nailed down ?

Witgang commented 6 years ago

@fiveangle it may have something to do with the watchdog using internal clock timer on your chip, i really have no clue quite new into this thing myself:)

cjsoong commented 6 years ago

@fiveangle If your watchdog can not work, try this code to force jump to the beginning of the program.

marlin_main.cpp

#if HAS_KILL

// Check if the kill button was pressed and wait just in case it was an accidental
// key kill key press
// -------------------------------------------------------------------------------
static int killCount = 0;   // make the inactivity button a bit less responsive
const int KILL_DELAY = 750;
if (!READ(KILL_PIN))
  killCount++;
else if (killCount > 0)
  killCount--;

// Exceeded threshold and we can confirm that it was not accidental
// KILL the machine
// ----------------------------------------------------------------
if (killCount >= KILL_DELAY) {
  SERIAL_ERROR_START();
  SERIAL_ERRORLNPGM(MSG_KILL_BUTTON);
  kill(PSTR(MSG_KILLED));
}
/* KILL KEY= RESET */
if (!READ(KILL_PIN))
{
//wdt_enable(WDTO_60MS);
  asm volatile (" jmp 0");        //RESET 
while(1) {}
}
/******************************************/
#endif
luwi66 commented 6 years ago

Hello, I'd like to try this, but I don't know where to put that piece of code into marlin_main.cpp. Sorry, but I'm rather new to C.

cjsoong commented 6 years ago

@luwi66
You need to install arduino ide https://www.arduino.cc/en/Main/Donate

luwi66 commented 6 years ago

@cjsoong That's not my question. I use arduino ide and have flashed Marlin several times. No, what i'd like to know is where to insert your code into the marlin.cpp code. After which line of code?

cjsoong commented 6 years ago

@luwi66 code file is "marlin_main.cpp". You can search for "#if HAS_KILL" related words. Add this code (#line 14085)

/ * KILL KEY = RESET /
if (! READ (KILL_PIN))
{
// wdt_enable (WDTO_60MS);
asm volatile ("jmp 0"); // RESET
while (1) {}
}
/ ****************************************** /
luwi66 commented 6 years ago

OK, got it. Sorry for not understanding at once. I uploaded it to my arduino; the effect is, that now the Kill Button does not cause a Kill anymore. But it also does not reset the arduino. When pressing the button, nothing happens.

cjsoong commented 6 years ago

@luwi66 I'm sorry .. my mistake There is one less "" / KILL KEY = RESET / -----> / KILL KEY = RESET /

luwi66 commented 6 years ago

I already did this decommenting; but tried again. Same result: The Kill/Reset button now has no effect at all.

thinkyhead commented 6 years ago

A similar method to make the KILL_PIN cause a reset. First restore your KILL_PIN value and make these changes to Marlin_main.cpp.

Add this line just before the manage_inactivity function. This is just a different way to do what is described above.

void(* resetFunc) (void) = 0; // Declare reset function as address 0

Then in manage_inactivity find these lines and make the indicated change:

    if (killCount >= KILL_DELAY) {
-     SERIAL_ERROR_START();
-     SERIAL_ERRORLNPGM(MSG_KILL_BUTTON);
-     kill(PSTR(MSG_KILLED));
+     resetFunc();
    }

This should turn your KILL_PIN into a reset button.

luwi66 commented 6 years ago

Sorry, doesn't work. Kill button now again causes Kill - not a reset.

thinkyhead commented 6 years ago

Hmm, well I've got nothing then. Anyone else in the gallery have some ideas?

luwi66 commented 6 years ago

Well, the solution is somewhere in the code. I have a Tevo Tarantula printer and got Marlin (bugfix version 1.1.8) from the Marlin EasyConfig-1.1x branch. The Tevo has a MKS Base 1.5 motherboard and a 2004 LCD Display. This display has a reset button - and it works as reset.

AnHardt commented 6 years ago

How about not connecting the button to an io-pin, but to the reset line?

luwi66 commented 6 years ago

Well, I simply wanted a solderless solution, as this works with Marlin at the Tevo display. An easy solution would be to solder another button in parallel to the reset button on the Ramps board. And place this button near the display so that I have a kill button and a reset button there.

thinkyhead commented 6 years ago

If you don't mind waiting 4 seconds this should do it with USE_WATCHDOG turned on:

    if (killCount >= KILL_DELAY) {
-     SERIAL_ERROR_START();
-     SERIAL_ERRORLNPGM(MSG_KILL_BUTTON);
-     kill(PSTR(MSG_KILLED));
+     delay(8000);
    }
tcm0116 commented 6 years ago

@thinkyhead is is possible to change the period of the watchdog timer prior to the delay? If so, you could lower it to a very small value, which would make the reset more instantaneous.

thinkyhead commented 6 years ago

Aha! Something like this?

    if (killCount >= KILL_DELAY) {
      SERIAL_ERROR_START();
      SERIAL_ERRORLNPGM("RESET");
-     kill(PSTR(MSG_KILLED));
+     wdt_enable(WDTO_15MS);
+     while(1);
    }
tcm0116 commented 6 years ago

Seems like it should work. However, keep in mind that this won't work for 32-bit boards that use Smoothieware bootloader, since it will hang in the bootloader if it detects that a watchdog reset occurred.

thinkyhead commented 6 years ago

Well, this isn't going into Marlin proper. It's just for this motley crew.

luwi66 commented 6 years ago

Beide Vorschläge von thinkyhead bringen keinen Erfolg. Nach wie vor kommt nur der Kill.

luwi66 commented 6 years ago

Sorry, fell into German. Both code snippets didn't succeed. Again only the Kill effect.

thinkyhead commented 6 years ago

Good luck. This issue is being closed, and we will soon be locking down the repository to deal with troll behavior.

AnHardt commented 6 years ago

The minimal change to 'reset' instead of 'kill' when pressing the button at the display is

@@ -13424,10 +13424,11 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
     // KILL the machine
     // ----------------------------------------------------------------
     if (killCount >= KILL_DELAY) {
       SERIAL_ERROR_START();
       SERIAL_ERRORLNPGM(MSG_KILL_BUTTON);
+      asm volatile ("jmp 0"); // RESET
       kill(PSTR(MSG_KILLED));
     }
   #endif

   #if HAS_HOME

Tested and working at todays bugfix-1.1.x branch.

If you want always a 'reset' instead of a 'kill' try:

@@ -13581,10 +13581,11 @@ void idle(
 /**
  * Kill all activity and lock the machine.
  * After this the machine will need to be reset.
  */
 void kill(const char* lcd_msg) {
+  asm volatile ("jmp 0"); // RESET
   SERIAL_ERROR_START();
   SERIAL_ERRORLNPGM(MSG_ERR_KILLED);

   thermalManager.disable_all_heaters();
   disable_all_steppers();

Be aware we do a kill by purpose! After a reset, not realized by the host, it will continue to send data. That can be disastrous. It's only a 'software' reset. Pins not properly initialised by Marlin will have the state before the reset. They will not have the default hardware state. If things go really wrong, a heater may be on.

A physical reset button is safer than this software reset. The button is not tested if the program hangs in an interrupt. The kill function is likely safer than the hardware reset.

AnHardt commented 6 years ago

The watchdog reset is a real hardware reset and has the advantage of hanging on some boars in the bootloader. (As far as i know this is not a good idea for a RAMPS-FD V1.x. The heaters will be on. This is why RAMPS-FD V1.x is called "unsave".)

luwi66 commented 6 years ago

@AnHardt Thanks. Your first solution works. Didn't try the second. Bye Ludwig

mbernalcu commented 6 years ago

Thanks @cjsoong ! I'm converting my CNC in a 3D printer, and need no endstops, so I was looking to hard reset my board after making some negative movements. The only way to reset machine position in Marlin 1.1.8 is reseting the board; G92 has no efect in machine position anymore. Your modifications to Marlin_main.cpp worked great for me!

github-actions[bot] commented 4 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.