3-way switch for stepper motor

Hello, I'm a little out of my depth here with the coding, my apologies for that. I am setting up a vertical positioning stage for a project that uses a stepper motor. What I want is for a 3-position switch to control the direction of motion, with up being up, down being down, and center being stop. I am having a lot of trouble trying to find a way to use a single pole on the stepper motor to hold the position in "stop mode".

Here is my schematic (sorry it's fritzing, but it's simple enough that it seems to make sense. If that's problematic feel free to let me know and I'll find another way)

Currently, this is the sketch I am using (yes, I know it's all wrong for this setup and the desired outcome)

// Define Pins

int reverseSwitch = 2; // push button for reverse
int driverPUL = 7; // PUL pin
int driverDIR = 6; // DIR pin
int spd = A0; // 10k pot

//vars

int pd = 500;  // Pulse delay time
boolean setdir = LOW; // Set direction

// Interrupts

void revmotor() {
  
  setdir = !setdir;
  
}

void setup() {
  
  pinMode (driverPUL, OUTPUT);
  pinMode (driverDIR, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING);
  
}

void loop() {
  
  pd = map((analogRead(spd)),0,1023,10000,500);
  digitalWrite(driverDIR,setdir);
  digitalWrite(driverPUL,HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL,LOW);
  delayMicroseconds(pd);

}

My question is: how do I change this code from a reverse-direction switch to one that will read the value of A1 and respond to the different R values and no value at all? Should I be using a digital interrupt for this? If so, how do I set up a standstill state for the motor?

You can't have multiple loop and setup functions.

It shouldn't be necessary to do anything special for hold in place, even when you're not stepping, the driver will keep the coils enabled to keep the stepper still.

Since there are only two positions use a single pole switch, it is either closed or open (forward or reverse). Your frizzy thing just complicates things, there are to many open wires and stuff missing. Post a schematic showing all connections, power and ground.

The switch will not work wired like that. The analog input is only going to see 5V, floating pin, 5V. You need another resistor to ground to form a voltage divider as below. The added 10K resistor acts as a pulldown resistor when the switch is in the off (open) condition, and as a part of a voltage divider when the switch is in one of the closed condition. The analog input will read 2.5V in the down and 3.3V in the up switch position and around 0V when off.

3 WAY SWITCH.jpg

3 WAY SWITCH.jpg

gilshultz:
Since there are only two positions use a single pole switch, it is either closed or open (forward or reverse). Your frizzy thing just complicates things, there are to many open wires and stuff missing. Post a schematic showing all connections, power and ground.

It is a 3-position switch with a central off position, not a 2-position switch, so I want to utilize the center position to be a "hold" position.
The only wires present in the schematic are the ones actually wired to the board. I don't know what I'm missing, or where the open wires are in the schematic. I am missing the 5v input from the USB, that is the only ground in the circuit.

wildbill:
You can't have multiple loop and setup functions.

It shouldn't be necessary to do anything special for hold in place, even when you're not stepping, the driver will keep the coils enabled to keep the stepper still.

Yes, the code is what I need help with. I'm hoping you are correct, and that all I need to do is tell it to stop moving. However, I don't know the language to tell it to stop, and I cannot find an example anywhere. Perhaps I do not know how to look, this is pretty new to me.

groundFungus:
The switch will not work wired like that. The analog input is only going to see 5V, floating pin, 5V. You need another resistor to ground to form a voltage divider as below. The added 10K resistor acts as a pulldown resistor when the switch is in the off (open) condition, and as a part of a voltage divider when the switch is in one of the closed condition. The analog input will read 2.5V in the down and 3.3V in the up switch position and around 0V when off.

Thank you! That was definitely an oversight on my part and you probably saved me a troubleshooting hassle!
So, once I have three different levels of input, how do I code the responses that I want? If this isn't your fortè or you don't wanna fix some noob's bad code no worries, I appreciate your input!

Here's your code reduced to the parts I think you need. Up & down might be the wrong way round.

int driverPUL = 7; // PUL pin
int driverDIR = 6; // DIR pin
int spd = A0; // 10k pot

const int pd = 500;  // Pulse delay time

void setup()
{
Serial.begin(115200);
pinMode (driverPUL, OUTPUT);
pinMode (driverDIR, OUTPUT);
}

void loop()
{
int SwitchSetting=analogRead(spd);
if(SwitchSetting<480)
  {
  // Do nothing    
  }
else  if(SwitchSetting<650)
  {  // Up
  digitalWrite(driverDIR, HIGH);
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(pd);
  }
else
  {  // Down  
  digitalWrite(driverDIR, LOW);
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(pd);
  }
}

Compiled, not tested.

wildbill:
Here's your code reduced to the parts I think you need. Up & down might be the wrong way round.

int driverPUL = 7; // PUL pin

int driverDIR = 6; // DIR pin
int spd = A0; // 10k pot

const int pd = 500;  // Pulse delay time

void setup()
{
Serial.begin(115200);
pinMode (driverPUL, OUTPUT);
pinMode (driverDIR, OUTPUT);
}

void loop()
{
int SwitchSetting=analogRead(spd);
if(SwitchSetting<480)
  {
  // Do nothing   
  }
else  if(SwitchSetting<650)
  {  // Up
  digitalWrite(driverDIR, HIGH);
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(pd);
  }
else
  {  // Down 
  digitalWrite(driverDIR, LOW);
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(pd);
  }
}



Compiled, not tested.

After adding the resistor to ground per groundFungus and slighly modifying the code you wrote to address the switch on a different input than the pot and still have the pot function as intended, this works perfectly. Thank you for the routine to monitor the analog input, I was unsure how to use the if-else if-else structure. The direction was switched, no big deal. Here's the finished, functional code for public use:

// Modified 3-way switch
// Credit to wildbill on the Arduino community forum

int driverPUL = 7; // PUL pin
int driverDIR = 6; // DIR pin
int spd = A0; // 10k pot
int motDIR = A4; //switch base

int pd = 500;  // Pulse delay time

void setup()
{
Serial.begin(9600);
pinMode (driverPUL, OUTPUT);
pinMode (driverDIR, OUTPUT);
}

void loop()
{
  pd = map((analogRead(spd)),0,1023,10000,200);
  
int SwitchSetting=analogRead(motDIR);
if(SwitchSetting<100)
  {
  // Do nothing   
  }
else  if(SwitchSetting<650)
  {  // Up
  digitalWrite(driverDIR, LOW);
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(pd);
  }
else
  {  // Down 
  digitalWrite(driverDIR, HIGH);
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(pd);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(pd);
  }
}

Hope this saves someone some trouble someday

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.