3D Printer - Coding Arduino and Python -BEGINNER - microswitch

Hello, I’m currently an engineering student and my project is to create a program for a 3D printer. I have no coding experience what so ever and have been learning from tutorials and YouTube. I have been creating a program with python which allows me to control the printer when buttons are pressed. I have become stuck on trying to get the axes to home. I have a microswitch positioned at the minimum point on each axes. I have spent numerous hours trying to get this to work. I have done the tutorial for the StateChangeDetection and Debounce but still can’t get it to work. Could anyone lead me in the right direction please and if you notice any changes that you would advise for my code, feel free to inform me, thanks.

#define X_STEP_PIN         54 //Printer Head/carriage
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38
#define X_MIN_PIN           3
#define X_MAX_PIN           2

#define Y_STEP_PIN         60 //Printer Bed 
#define Y_DIR_PIN          61
#define Y_ENABLE_PIN       56
#define Y_MIN_PIN          14
#define Y_MAX_PIN          15

#define Z_STEP_PIN         46 
#define Z_DIR_PIN          48
#define Z_ENABLE_PIN       62
#define Z_MIN_PIN          18
#define Z_MAX_PIN          19

#define E_STEP_PIN         26
#define E_DIR_PIN          28
#define E_ENABLE_PIN       24

#define Q_STEP_PIN         36
#define Q_DIR_PIN          34
#define Q_ENABLE_PIN       30

#define SDPOWER            -1
#define SDSS               53
#define LED_PIN            13

#define FAN_PIN            9

#define PS_ON_PIN          12
#define KILL_PIN           -1

#define HEATER_0_PIN       10
#define HEATER_1_PIN       8
#define TEMP_0_PIN          13   // ANALOG NUMBERING
#define TEMP_1_PIN          14   // ANALOG NUMBERING

int X_STOP = 0;
int Y_STOP = 0;
int Z_STOP = 0;

void setup() {

  Serial.begin(9600); //sets the baud rate of 9600 bps
  pinMode(FAN_PIN , OUTPUT);
  pinMode(HEATER_0_PIN , OUTPUT);
  pinMode(HEATER_1_PIN , OUTPUT);
  pinMode(LED_PIN  , OUTPUT);
  
  pinMode(X_STEP_PIN  , OUTPUT);
  pinMode(X_DIR_PIN    , OUTPUT);
  pinMode(X_ENABLE_PIN    , OUTPUT);
  pinMode(X_MIN_PIN, INPUT);
  
  pinMode(Y_STEP_PIN  , OUTPUT);
  pinMode(Y_DIR_PIN    , OUTPUT);
  pinMode(Y_ENABLE_PIN    , OUTPUT);
  pinMode(Y_MIN_PIN, INPUT);
  
  pinMode(Z_STEP_PIN  , OUTPUT);
  pinMode(Z_DIR_PIN    , OUTPUT);
  pinMode(Z_ENABLE_PIN    , OUTPUT);
  pinMode(Y_MIN_PIN, INPUT);
  
  pinMode(E_STEP_PIN  , OUTPUT);
  pinMode(E_DIR_PIN    , OUTPUT);
  pinMode(E_ENABLE_PIN    , OUTPUT);
  
  pinMode(Q_STEP_PIN  , OUTPUT);
  pinMode(Q_DIR_PIN    , OUTPUT);
  pinMode(Q_ENABLE_PIN    , OUTPUT);
  
   digitalWrite(X_ENABLE_PIN    , LOW);
    digitalWrite(Y_ENABLE_PIN    , LOW);
    digitalWrite(Z_ENABLE_PIN    , LOW);
    digitalWrite(E_ENABLE_PIN    , LOW);
    digitalWrite(Q_ENABLE_PIN    , LOW);
}

void loop() {

  X_STOP = digitalRead(X_MIN_PIN);

  if(Serial.available())
  {
    switch(Serial.read())
    {
      case 'A': digitalWrite(X_DIR_PIN,LOW);
                for(int x=0; x < 1; x++){
                digitalWrite(X_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(X_STEP_PIN,LOW);
                delayMicroseconds(500);
                }
      break;
      case 'B': digitalWrite(X_DIR_PIN,HIGH);
                for(int x=0; x < 1; x++){
                digitalWrite(X_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(X_STEP_PIN,LOW);
                }
      break;
      case 'C': digitalWrite(Y_DIR_PIN,LOW);
                for(int x = 0; x < 1; x++){
                digitalWrite(Y_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Y_STEP_PIN,LOW);
                }
      break;
      case 'D': digitalWrite(Y_DIR_PIN,HIGH);
                for(int x=0; x < 1; x++){
                digitalWrite(Y_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Y_STEP_PIN,LOW);
                }
      break;
      case 'E': digitalWrite(Z_DIR_PIN,LOW);
                for(int x=0; x < 1; x++){
                digitalWrite(Z_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Z_STEP_PIN,LOW);
                }
      break;
      case 'F': digitalWrite(Z_DIR_PIN,HIGH);
                for(int x=0; x < 1; x++){
                digitalWrite(Z_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Z_STEP_PIN,LOW);
                }
      break;
      case 'G': digitalWrite(X_DIR_PIN,LOW);
                for(int x=0; x < 1200; x++){
                digitalWrite(X_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(X_STEP_PIN,LOW);
                delayMicroseconds(500);
                }
      break;
      case 'H': digitalWrite(X_DIR_PIN,HIGH);
                for(int x=0; x < 1200; x++){
                digitalWrite(X_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(X_STEP_PIN,LOW);
                }
      break;
      case 'I': digitalWrite(Y_DIR_PIN,LOW);
                for(int x = 0; x < 1200; x++){
                digitalWrite(Y_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Y_STEP_PIN,LOW);
                }
      break;
      case 'J': digitalWrite(Y_DIR_PIN,HIGH);
                for(int x=0; x < 1200; x++){
                digitalWrite(Y_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Y_STEP_PIN,LOW);
                }
      break;
      case 'K': digitalWrite(Z_DIR_PIN,LOW);
                for(int x=0; x < 3200; x++){
                digitalWrite(Z_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Z_STEP_PIN,LOW);
                }
      break;
      case 'L': digitalWrite(Z_DIR_PIN,HIGH);
                for(int x=0; x < 3200; x++){
                digitalWrite(Z_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(Z_STEP_PIN,LOW);
                }
      break;
      case 'M': do {
                digitalWrite(X_DIR_PIN,LOW);
                for(int x=0; x < 1; x++){
                digitalWrite(X_STEP_PIN,HIGH);
                delayMicroseconds(500);
                digitalWrite(X_STEP_PIN,LOW);
                delayMicroseconds(500);}
      } while (digitalRead(X_STOP == LOW));
                 
      break;
      default: break;
    }
  }
  }

Could anyone lead me in the right direction please

Certainly. Which way do you want to go?

The code you posted (correctly, thank you) does something. You want it to do something. Clearly, if the two somethings were the same thing you would not have felt the urge to post the code. However, all that we can read into that is that the code is not doing what you want. That is no help in knowing what the code actually does, or how that differs from what you want.

Frankly, there is WAY too much code, doing WAY too many things, for resolving the issue. There is NO reason to read from the serial port until the hardware works properly. There is NEVER a reason to use a for loop that iterates exactly once.

Knowing how the switches are wired, and why you are not using the internal pullup resistors, and the dirt simple wiring that they enable, will be essential to helping solve your problem.

PaulS:
Frankly, there is WAY too much code, doing WAY too many things, for resolving the issue. There is NO reason to read from the serial port until the hardware works properly. There is NEVER a reason to use a for loop that iterates exactly once.

The other parts of the code is for different movements required within my program I am developing within Python. When I click the button for the X-axis to home, it returns to home but does not stop when it hits the microswitch. Once I have achieved the homing for the X-axis I will be able to do the same for the other axes.

Note: I am using an Arduino Mega 2560 board and a RAMPs 1.4 board for the 3D Printer.

Once I have achieved the homing for the X-axis I will be able to do the same for the other axes.

Exactly. So, the sketch that you develop to do that does NOT need to deal with the serial port, for loops, or the other axes.

but does not stop when it hits the microswitch.

We are back to needing to understand how, and why, you have wired the switches.

Sorry PaulS, you are making no sense whatsoever to me. The sketch does need to deal with the serial port as it must read if the microswitch has been closed, to therefore tell the sketch the print head is home in that axes, i.e. stop the stepper motor from rotating.

The sketch does need to deal with the serial port as it must read if the microswitch has been closed

Really? Can you post a link to the serial switch? I've never seen a switch with a serial interface.

to therefore tell the sketch the print head is home in that axes, i.e. stop the stepper motor from rotating.

The sketch does not need to tell the sketch that the print head is home. It KNOWS that already. The sketch does not use the serial interface to tell the stepper to stop.

Have you not looked at the example sketches provided with Arduino? StateChangeDetection and Debounce? They use the serial port to read whether the button is pressed, in this case the switch is closed, and counts the number of times it has been closed. The microswitch I am using is similar to this Buy Small mini micro switch micro switch in China on Alibaba.com

The print head doesn’t know its home as the stepper motor continues to rotate with my code, even though the microswitch is closed. The microswitch is there to allow the program to determine when the print head has reached the minimum limit on the axes. Therefore I need to microswitch to tell the stepper motor to stop rotating when it is closed.

Have you not looked at the example sketches provided with Arduino? StateChangeDetection and Debounce? They use the serial port to read whether the button is pressed

They most certainly do NOT. They use the serial port to WRITE out, for your benefit, some information about the state of the switches. NOWHERE in the the State Change Detection example will you fine ANY code that reads from the serial port.

The print head doesn’t know its home as the stepper motor continues to rotate with my code, even though the microswitch is closed.

That is a problem with how your switch is wired, almost certainly.

Therefore I need to microswitch to tell the stepper motor to stop rotating when it is closed.

That is not going to happen. The Arduino needs to query the state of the switch, and make the stepper move, or not. The switch can’t make the stepper do anything. The switch can’t tell the Arduino anything, either. What is does is set a pin HIGH or LOW or some undefined state, based on how it is wired which you STILL haven’t told us.

Okay sorry that is my mistake, but like I said I am a beginner and I'm still trying to learn what I'm doing.

The microswitch has wires from the COM and NC which is attached to the RAMPs 1.4 board into the X min pins. If I'm correct in saying that would mean when the switch is closed it would set the pin as HIGH?

I have had success in getting the pin to give HIGH and LOW inputs to the digital read as I got the tutorials to work that Arduino supply.

I have had success in getting the pin to give HIGH and LOW inputs to the digital read as I got the tutorials to work that Arduino supply.

What I think you need to do is create a sketch that reads a limit switch pin and shows when the pin changes state, as you press the switch.

Determine, for sure, that you get output only when you press or release the switch, and that the message that you print correctly matches the action that you performed (that is, you do not want to see "RELEASED" when you press the switch, and "PRESSED" when you release it).

When you know that the switch works correctly, then add code to move the stepper motor toward the switch.

Read the switch. If not pressed, take a step. Repeat until the switch is pressed.

Once that works, then you can incorporate the rest of the code.

ronan635:
but like I said I am a beginner supply.

A 3D printer is an extraordinarily complex project especially if you are a beginner.

You need to develop your expertise one piece at a time. For example,

  • Receive data from your PC
  • Make a motor move N steps.
  • Make 2 motors move N and M steps respectively.
  • Likewise for 3 motors.
  • How to detect a limit switch being triggered.
  • How to get the motors to go to their home positions
  • … and that is just for starters

Have a look at Planning and Implementing a Program

And it will be very much easier to get help from this Forum if you are enquiring about a small part of the project at any one time.

…R

PaulS:
When you know that the switch works correctly, then add code to move the stepper motor toward the switch.

Read the switch. If not pressed, take a step. Repeat until the switch is pressed.

Once that works, then you can incorporate the rest of the code.

I did the first part you explained to gain a serial print which stated if the the microswitch was closed or released and got it to work. Its just when I ask the stepper motor to move I can’t seem to get it to move after it has checked if the pin is LOW. How do you do this?

#define X_STEP_PIN         54 //Printer Head/carriage
#define X_DIR_PIN          55
#define X_MIN_PIN           3
int X_STOP = LOW;

void setup() {
  
  pinMode(X_STEP_PIN  , OUTPUT);
  pinMode(X_DIR_PIN    , OUTPUT);
  pinMode(X_MIN_PIN, INPUT);
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  X_STOP = digitalRead(X_MIN_PIN);
  
 digitalWrite(X_DIR_PIN, LOW);
    for (int x = 0; x < 1; x++) {
      digitalWrite(X_STEP_PIN, HIGH);
      delayMicroseconds(500);
      digitalWrite(X_STEP_PIN, LOW);
      delayMicroseconds(500);}

  if (X_STOP == LOW) {
   digitalWrite(X_DIR_PIN, LOW);
    for (int x = 0; x < 1; x++) {
      digitalWrite(X_STEP_PIN, HIGH);
      delayMicroseconds(500);
      digitalWrite(X_STEP_PIN, LOW);
      delayMicroseconds(500);
    }}}
    for (int x = 0; x < 1; x++) {
      digitalWrite(X_STEP_PIN, HIGH);
      delayMicroseconds(500);
      digitalWrite(X_STEP_PIN, LOW);
      delayMicroseconds(500);}

Why is this code in a for loop that iterates no more, and no less, than one time?

Why not just use:

      digitalWrite(X_STEP_PIN, HIGH);
      delayMicroseconds(500);
      digitalWrite(X_STEP_PIN, LOW);
      delayMicroseconds(500);

Why not put this code in a function, step(), that takes a pin number?

Assuming that LOW means the limit switch is pressed, I would have something like:

   while(digitalRead(X_MIN_PIN) == LOW)
   {
      step(X_STEP_PIN);
   }

See how much simpler that looks? See how the curly braces line up nicely?

Put that in a function called goHome(), and you can home the head in one easy step.

ronan635:
Hello, I'm currently an engineering student and my project is to create a program for a 3D printer. I have no coding experience what so ever and have been learning from tutorials and YouTube.

  • Is it a group project? If so, how did the student with no coding experience get the programming assignment?

  • Don't engineering students have to take programming classes anymore? I had to take several and that was in the early 80's.

I had to take several and that was in the early 80's.

In the late 70s, I didn't have to. But, I took every one I could. I found programming fun.

gfvalvo:

  • Is it a group project? If so, how did the student with no coding experience get the programming assignment?

  • Don't engineering students have to take programming classes anymore? I had to take several and that was in the early 80's.

This is my final year project, and yes I have the same feeling of how I got this project with no experience? It was advertised to us as "Design of a 3D Printer Extruder". The bachelors student is doing the design work on the extruder which I thought I was suppose to be doing but I (Masters student) have to create the program to control the 3D Printer and the extruder if I ever get that far! My degree is in Mechanical Engineering.

My degree is in Mechanical Engineering.

So is mine. I've never designed anything but computer programs. Lots and lots of them.

But, if you did have the job of designing the extruder, you would have several parts to design, right? You would not expect to complete the drawings and send the parts out for manufacture, and get everything back, and have it all work, would you? No. You'd expect to have to iterate, changing tolerances, etc. until the whole part worked properly. Coding is really no different. You iterate. You scrap poor designs. You build test parts (programs/functions).

PaulS:

    for (int x = 0; x < 1; x++) {

digitalWrite(X_STEP_PIN, HIGH);
     delayMicroseconds(500);
     digitalWrite(X_STEP_PIN, LOW);
     delayMicroseconds(500);}



Why is this code in a for loop that iterates no more, and no less, than one time?

When I remove this for loop, the stepper motor doesn’t move.

PaulS:
Why not just use:

      digitalWrite(X_STEP_PIN, HIGH);

delayMicroseconds(500);
     digitalWrite(X_STEP_PIN, LOW);
     delayMicroseconds(500);




Why not put this code in a function, step(), that takes a pin number?

Assuming that LOW means the limit switch is pressed, I would have something like:


while(digitalRead(X_MIN_PIN) == LOW)
  {
     step(X_STEP_PIN);
  }



See how much simpler that looks? See how the curly braces line up nicely?

Put that in a function called goHome(), and you can home the head in one easy step.

I don’t quite understand what u mean by putting the code in a function of step()? Do you mean place the code inside the brackets? You have me completely confused right now. The same with the goHome().

When I remove this for loop, the stepper motor doesn't move.

You need the code in the body of the for loop. You do not need the useless for statement.

I don't quite understand what u mean by putting the code in a function of step()

I mean that you should create a function that does nothing more, and nothing less, than make a stepper step once:

void step(int pinNumber)
{
  digitalWrite(pinNumber, HIGH);
  delayMicroseconds(500);
  digitalWrite(pinNumber, LOW);
  delayMicroseconds(500);
}

Then, call that function to make a stepper whose step pin is connected to any pin, step once.

I don't understand why you are not using the Stepper (or AccelStepper or MultiStepper) library to handle the stepping.

First, your bracing style is shit.

}}}

NEVER DO THIS. I don't care what you do with the opening curly braces, but closing braces always go on their own line with nothing else on it. The only exceptions that are acceptable are the else clause of an if-else structure or the while clause of a do-while loop.

Also, fix your indenting so that it follows the common convention.

Style guidelines exist for a reason. While these changes won't make any functional difference to the compiler, they make it 10x easier for a human to read. That includes yourself.

PaulS:
Why not just use:

      digitalWrite(X_STEP_PIN, HIGH);

delayMicroseconds(500);
      digitalWrite(X_STEP_PIN, LOW);
      delayMicroseconds(500);

There's a perfectly good reason why that code (and the original code too) should not be used.

Because delay is evil. It is the worst function possible for this sort of thing. ronan has no hope of ever getting his Arduino to conduct the orchestra of devices to play the necessary symphony of motions by using delays. Invest in learning non-blocking techniques now, and save yourself a HUGE headache when you progress to trying to move 2 or 3 steppers in concert.