Hello All,
This is my first post and I don't have much knowledge of electrical, but I have to do a project to automate a Spray gun mechanism.
I have NEMA 17 stepper motor connect to pulley and controlled by belt drive. Motor is connect to Motor drive DRV8825. I have two limit switches, which when pressed, it should change the direction of motor.
I have also added a 24V valve to control the Spray Gun which is connected to MOS Module IRF520N. Below i have added a design of the circuits and have given 12V of power to control the whole setup. I am giving my commands from GUI made in python.
I want to automate the cycles to spray the liquid when motor is started. The valve should open at the same time when motor is started and when limit switch triggers the valve should close. The motor should wait for the delay time given and restart again to opposite direction until other side limit switch is triggered. The valve should also start at the same time and close accordingly to the motor's working.
Below is the code I have made:
// Pin definitions
#define DIR_PIN 2
#define STEP_PIN 3
#define ENABLE_PIN 7
#define RIGHT_LIMIT_SWITCH_PIN 6
#define LEFT_LIMIT_SWITCH_PIN 5
#define VALVE_PIN 1 // Valve control pin
// Variables
volatile bool motorRunning = false;
int rpm = 60; // Default RPM
bool direction = true; // true = Right (Forward), false = Left (Reverse)
int stepDelay = 1000; // Default delay in microseconds
int limitSwitchDelay = 1000; // Delay in milliseconds at the endpoint
bool rightLimitSwitchTriggered = false; // Flag for right limit switch
bool leftLimitSwitchTriggered = false; // Flag for left limit switch
int reverseMicrosteps = 75; // Number of microsteps to release the limit switch
int cycles = 0; // Number of cycles
int currentCycle = 0; // Current cycle count
bool resetMode = false; // Flag for reset mode
bool valveAutoMode = false; // Auto mode initially OFF (wait for user command)
bool valveState = false; // Valve initially OFF
void setup() {
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
pinMode(ENABLE_PIN, OUTPUT);
pinMode(RIGHT_LIMIT_SWITCH_PIN, INPUT_PULLUP);
pinMode(LEFT_LIMIT_SWITCH_PIN, INPUT_PULLUP);
pinMode(VALVE_PIN, OUTPUT);
// Disable motor and keep valve closed at startup
digitalWrite(ENABLE_PIN, HIGH);
digitalWrite(VALVE_PIN, LOW);
// Serial Communication
Serial.begin(9600);
while (!Serial) {
; // Wait for serial port to connect
}
}
void loop() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
handleCommand(command);
}
if (resetMode) {
handleReset();
return;
}
if (motorRunning) {
if (direction) { // Moving right (forward)
if (digitalRead(RIGHT_LIMIT_SWITCH_PIN) == LOW && !rightLimitSwitchTriggered) {
rightLimitSwitchTriggered = true;
handleRightLimitSwitch();
} else {
stepMotor();
}
} else { // Moving left (reverse)
if (digitalRead(LEFT_LIMIT_SWITCH_PIN) == LOW && !leftLimitSwitchTriggered) {
leftLimitSwitchTriggered = true;
handleLeftLimitSwitch();
} else {
stepMotor();
}
}
}
}
void handleCommand(String command) {
if (command == "START") {
motorRunning = true;
direction = true; // Start by moving right
digitalWrite(DIR_PIN, HIGH); // Set direction to right
digitalWrite(ENABLE_PIN, LOW); // Enable motor
if (valveAutoMode) controlValve(true); // Open valve if auto mode
} else if (command == "STOP") {
motorRunning = false;
digitalWrite(ENABLE_PIN, HIGH); // Disable motor
if (valveAutoMode) controlValve(false); // Close valve if auto mode
} else if (command.startsWith("SET_RPM")) {
rpm = command.substring(8).toInt();
stepDelay = calculateStepDelay(rpm);
} else if (command.startsWith("SET_DELAY")) {
limitSwitchDelay = command.substring(10).toInt();
} else if (command.startsWith("SET_REVERSE_STEPS")) {
reverseMicrosteps = command.substring(17).toInt();
} else if (command.startsWith("SET_CYCLES")) {
cycles = command.substring(10).toInt();
currentCycle = 0; // Reset cycle count
} else if (command == "RESET") {
resetMode = true;
} else if (command == "VALVE_ON") {
valveAutoMode = false; // Disable auto mode
controlValve(true);
} else if (command == "VALVE_OFF") {
valveAutoMode = false; // Disable auto mode
controlValve(false);
} else if (command == "VALVE_AUTO") {
valveAutoMode = true; // Enable auto mode
}
}
int calculateStepDelay(int rpm) {
int stepsPerRevolution = 200; // 1.8° stepper motor without microstepping
long stepsPerMinute = rpm * stepsPerRevolution;
long stepDelayMicroseconds = (60L * 1000000L) / stepsPerMinute;
return stepDelayMicroseconds;
}
void stepMotor() {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(stepDelay);
}
void handleRightLimitSwitch() {
if (valveAutoMode) controlValve(false); // Close valve at limit switch
digitalWrite(DIR_PIN, LOW); // Reverse direction
for (int i = 0; i < reverseMicrosteps; i++) {
stepMotor();
}
delay(limitSwitchDelay);
direction = false;
digitalWrite(DIR_PIN, LOW);
rightLimitSwitchTriggered = false;
if (valveAutoMode) controlValve(true); // Open valve again when motor restarts
if (cycles > 0) {
currentCycle++;
if (currentCycle >= cycles) {
motorRunning = false;
moveToLeftLimit();
}
}
}
void handleLeftLimitSwitch() {
if (valveAutoMode) controlValve(false); // Close valve at limit switch
digitalWrite(DIR_PIN, HIGH); // Reverse direction
for (int i = 0; i < reverseMicrosteps; i++) {
stepMotor();
}
delay(limitSwitchDelay);
direction = true;
digitalWrite(DIR_PIN, HIGH);
leftLimitSwitchTriggered = false;
if (valveAutoMode) controlValve(true); // Open valve again when motor restarts
}
void handleReset() {
motorRunning = false;
digitalWrite(ENABLE_PIN, HIGH); // Disable motor
controlValve(false); // Close valve
delay(1000);
moveToLeftLimit();
resetMode = false;
}
void moveToLeftLimit() {
motorRunning = true;
direction = false;
digitalWrite(DIR_PIN, LOW);
digitalWrite(ENABLE_PIN, LOW);
while (digitalRead(LEFT_LIMIT_SWITCH_PIN) == HIGH) {
stepMotor();
}
handleLeftLimitSwitch();
motorRunning = false;
digitalWrite(ENABLE_PIN, HIGH);
}
void controlValve(bool state) {
if (!valveAutoMode) { // Manual mode
digitalWrite(VALVE_PIN, state ? HIGH : LOW);
} else { // Auto mode
if (state) {
digitalWrite(VALVE_PIN, HIGH); // Open valve
} else {
digitalWrite(VALVE_PIN, LOW); // Close valve
}
}
}
My questions are:
- I cannot the speed of the motor by RPM commands, if i give 100 rpm and shift directly to 1000 the motor still works on 100rpm.
- For valve operation what modifications more i can do to make it work independently, irrespective of working of the motor.
If you need any more info, please let me know.
Thanks for the help
