Hello,
I have been having an issue with a electro mechanical system I have been developing. I am using an Arduino Mega 2560 to run a few dc motors, a load cell, a stepper motor and control and solid state relay (SSR). The SSR is connected to a air pop popcorn machine (Amazon.com: Dzmb quick and easy hot air popcorn machine with measuring cup, oil-free popcorn machine with on/off switch is suitable for family movie night parties. (Red): Home & Kitchen). The issue I am having is, whenever I run the system with the airpopper plugged in the Arduino will hang and stop running. Without the popper everything is running perfectly fine. Does anyone have any idea why the Arduino would hang whenever the popper is plugged in?
A separate, but maybe related issue, I noticed that if i run the popcorn machine with an extension cord separate from the circuit. If the extension cord plug is close the the arduino the system will shut down as well. I attempted to cover the electronics in a grounded metal box but that did not solve the issue.
Components
- 24 V power supply
- Arduino mega 2560
- 2 x #2516 Pololu Dual G2 High-Power Motor Driver 24v14 Shield
- 3 DC Motors
- 1 Stepper motor
- DRV8825 stepper motor driver
- Adafruit NAU7802
(I left out of the motors and a few limit switches from this circuit diagram)
Code
include <AccelStepper.h>
#include "DualG2HighPowerMotorShield.h"
#include <Adafruit_NAU7802.h>
// Create instance of the Pololu Dual G2 motor driver
// Uncomment the version corresponding with the version of your shield.
DualG2HighPowerMotorShield24v14 md;
// Use your custom pin configuration
DualG2HighPowerMotorShield24v14 md2(41, 43, 45, 39, A2, 40, 42, 44, 38, A3);
// Stepper Motor Pin Definitions
const int dirPin = 2;
const int stepPin = 3;
const int enablePin = 8; // Pin to control ENABLE on DRV8825
const int limitSwitchForward = 4;
const int limitSwitchReverse = 5;
// Microstepping control pins
const int M0 = 9;
const int M1 = 10;
const int M2 = 11;
// Popper control pin definition
const int popperPin = 22; // Pin to control the popper SSR relay
// Define motor interface type
#define motorInterfaceType 1
// DC Motor Settings
const int motorSpeed = 300; // Motor speed (0-400 range)
// Create instances
AccelStepper myStepper(motorInterfaceType, stepPin, dirPin);
Adafruit_NAU7802 nau;
// Load Cell Constants and Variables
const int weightIncrement = 5; // Weight increment to trigger motors (g)
const int weightThreshold = 45; // Final weight threshold (g)
int32_t loadcellTare = 0; // Load cell tare value
int32_t currentBaseline = 0; // Baseline weight for triggering motors
bool dCommandActive = false; // Flag for "D" command activation
// Load Cell Timeout Duration (milliseconds)
const unsigned long loadCellTimeout = 1800000; // Default is 30 minutes
unsigned long lastWeightIncreaseTime = 0; // Tracks the last time a weight increase was detected
// Popper Timer Variables
const unsigned long popperTimeout = 300000; // 5 minutes (300,000 ms)
unsigned long popperStartTime = 0; // When popper was turned on
bool popperActive = false; // Flag for popper active state
// Motor Cycle Timing
unsigned long stepperDuration = 455; // Stepper motor run time (ms)
unsigned long dcMotor1Duration = 1121; // DC motor 1 run time (ms)
unsigned long dcMotor2Duration = 1462; // DC motor 2 run time (ms) - New variable for second motor
// State variables for DC motors
bool isDCMotor1Running = false;
bool isDCMotor2Running = false;
unsigned long dcMotor1StartTime = 0;
unsigned long dcMotor2StartTime = 0;
// Timing for reverse motion in "F" command
// For dispensing 30mL with small syringe
unsigned long reverseStepCount = 8500;
// Encoder Pin Definitions
#define ENCODER_A 19 // Encoder Channel A
#define ENCODER_B 18 // Encoder Channel B
// Encoder Configuration
volatile long encoderCount = 0;
const int pulsesPerRevolution = 64 * 150; // Adjust based on your encoder and gearing
// Auger Motor Settings
const int augerSpeed = 150; // Default motor speed (0-400 range)
unsigned long augerMotorTimeout = 180000; // Safety timeout (30 seconds)
// Function to turn on the popper and start its timer
void turnPopperOn() {
digitalWrite(popperPin, HIGH);
popperActive = true;
popperStartTime = millis();
Serial.println("Popper turned ON - Timer started (5 minutes)");
}
// Function to turn off the popper
void turnPopperOff() {
digitalWrite(popperPin, LOW);
popperActive = false;
Serial.println("Popper turned OFF");
}
// Function to monitor popper timer
void monitorPopperTimer() {
if (popperActive && (millis() - popperStartTime >= popperTimeout)) {
turnPopperOff();
Serial.println("Popper timeout reached (5 minutes)");
}
}
// Helper function to check for motor driver faults
void stopIfFault()
{
if (md.getM1Fault())
{
md.disableDrivers();
delay(1);
Serial.println("M1 fault");
turnPopperOff(); // Turn off popper on motor fault
while (1);
}
if (md.getM2Fault())
{
md.disableDrivers();
delay(1);
Serial.println("M2 fault");
turnPopperOff(); // Turn off popper on motor fault
while (1);
}
}
// Helper function to configure the stepper motor
void configureStepper(float maxSpeed, float acceleration) {
myStepper.setMaxSpeed(maxSpeed);
myStepper.setAcceleration(acceleration);
}
void setup() {
// Initialize serial communication for debugging
Serial.begin(9600);
Serial.println("Starting system initialization...");
// Initialize popper control pin
pinMode(popperPin, OUTPUT);
digitalWrite(popperPin, LOW); // Ensure popper starts in OFF state
Serial.println("Popper control initialized (OFF)");
// Initialize Pololu motor driver
Serial.println("Initializing main motor driver (md)...");
md.init();
md.calibrateCurrentOffsets();
delay(10);
// Initialize the md2 motor driver for auger control - THIS WAS MISSING
Serial.println("Initializing auger motor driver (md2)...");
md2.init();
md2.calibrateCurrentOffsets();
delay(10);
// Enable drivers
Serial.println("Enabling motor drivers...");
md.enableDrivers();
md2.enableDrivers();
delay(10); // Give more time for drivers to initialize
// Start with motors stopped
md.setM1Speed(0);
md.setM2Speed(0);
md2.setM1Speed(0);
md2.setM2Speed(0);
// Initialize stepper motor pins
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, HIGH); // Disable the motor by default
pinMode(limitSwitchForward, INPUT_PULLUP);
pinMode(limitSwitchReverse, INPUT_PULLUP);
pinMode(M0, OUTPUT);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
// Set microstepping mode to 1/8 step
digitalWrite(M0, HIGH);
digitalWrite(M1, HIGH);
digitalWrite(M2, LOW);
// Set stepper motor parameters
configureStepper(1000, 500);
// Initialize encoder for auger control
setupEncoder();
// Initialize the load cell
setupLoadCell();
// User prompt
Serial.println("System ready.");
Serial.println("Commands:");
Serial.println(" Home - Move to home position");
Serial.println(" F - Move fixed steps in reverse");
Serial.println(" D - Start load cell monitoring and popper");
Serial.println(" A<turns> - Rotate auger (e.g., A2.5 for 2.5 turns)");
Serial.println(" Status - Show system status");
}
void setupLoadCell() {
Serial.println("NAU7802 Load Cell Setup");
if (!nau.begin()) {
Serial.println("Failed to find NAU7802");
while (true); // Halt if load cell initialization fails
}
Serial.println("Found NAU7802");
nau.setLDO(NAU7802_3V0);
nau.setGain(NAU7802_GAIN_128);
nau.setRate(NAU7802_RATE_10SPS);
// Flush initial readings
for (uint8_t i = 0; i < 10; i++) {
while (!nau.available()) delay(1);
nau.read();
}
while (!nau.calibrate(NAU7802_CALMOD_INTERNAL)) {
Serial.println("Failed to calibrate internal offset, retrying!");
delay(1000);
}
while (!nau.calibrate(NAU7802_CALMOD_OFFSET)) {
Serial.println("Failed to calibrate system offset, retrying!");
delay(1000);
}
Serial.println("Calibration complete");
// Collect tare readings
int32_t tareSum = 0;
const int tareReadings = 25;
for (uint8_t i = 0; i < tareReadings; i++) {
while (!nau.available()) delay(1);
tareSum += nau.read();
}
loadcellTare = tareSum / tareReadings;
Serial.print("Load Cell Tare Value: ");
Serial.println(loadcellTare);
// Initialize baseline
currentBaseline = 0;
}
int32_t readLoadCell() {
while (!nau.available()) delay(1);
return 0.0025 * (nau.read() - loadcellTare); // Convert to grams
}
void resetLoadCell() {
Serial.println("Resetting Load Cell Tare...");
// Recalculate tare value
int32_t tareSum = 0;
const int tareReadings = 25;
for (uint8_t i = 0; i < tareReadings; i++) {
while (!nau.available()) delay(1);
tareSum += nau.read();
}
loadcellTare = tareSum / tareReadings;
Serial.print("New Load Cell Tare Value: ");
Serial.println(loadcellTare);
// Reset baseline
currentBaseline = 0;
}
void loop() {
// Continuously monitor the reverse limit switch
monitorReverseLimitSwitch();
// Monitor popper timer if active
monitorPopperTimer();
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input.equalsIgnoreCase("Home")) {
Serial.println("Homing: Moving forward until the limit switch is triggered...");
moveHome();
} else if (input.equalsIgnoreCase("F")) {
Serial.println("Moving reverse for fixed steps...");
moveReverseFixedSteps();
} else if (input.equalsIgnoreCase("D")) {
// Reset for new "D" command activation
resetLoadCell(); // Reset the load cell to fresh tare value
dCommandActive = true;
configureStepper(1000, 500); // Reconfigure stepper for D command
// Reset the timeout timer
lastWeightIncreaseTime = millis();
// Reset cycle count
resetCycleCount();
// Turn on the popper
turnPopperOn();
Serial.println("Load Cell Monitoring Started...");
} else if (input.startsWith("A")) {
// Now process the command
if (input.length() > 1) {
// Extract the number of turns from command (e.g., "A2.5")
float turns = input.substring(1).toFloat();
if (turns != 0) {
Serial.print("Auger command received. Turning ");
Serial.print(turns);
Serial.println(" rotations.");
// Set a shorter timeout for first test
unsigned long originalTimeout = augerMotorTimeout;
augerMotorTimeout = 15000; // 15 second timeout for safety
bool result = auger(turns);
// Restore original timeout
augerMotorTimeout = originalTimeout;
if (!result) {
Serial.println("Auger operation failed. Motor has been stopped.");
emergencyStopAuger(); // Extra safety measure
}
} else {
Serial.println("Invalid rotation value. Please specify a non-zero number (e.g., A1.5)");
}
} else {
// Default behavior for just "A"
Serial.println("Auger test mode. Performing 1/4 rotation test.");
auger(0.25); // Just do a quarter turn for testing
}
} else if (input.startsWith("Set1:")) {
// Set DC Motor 1 duration
dcMotor1Duration = input.substring(5).toInt();
Serial.print("DC Motor 1 duration set to: ");
Serial.println(dcMotor1Duration);
} else if (input.startsWith("Set2:")) {
// Set DC Motor 2 duration
dcMotor2Duration = input.substring(5).toInt();
Serial.print("DC Motor 2 duration set to: ");
Serial.println(dcMotor2Duration);
} else if (input.equalsIgnoreCase("Status")) {
// Print current status
Serial.println("Current status:");
Serial.print("DC Motor 1 duration: ");
Serial.println(dcMotor1Duration);
Serial.print("DC Motor 2 duration: ");
Serial.println(dcMotor2Duration);
// Report motor currents
Serial.print("M1 current: ");
Serial.print(md.getM1CurrentMilliamps());
Serial.println(" mA");
Serial.print("M2 current: ");
Serial.print(md.getM2CurrentMilliamps());
Serial.println(" mA");
// Report popper status
Serial.print("Popper status: ");
Serial.println(popperActive ? "ON" : "OFF");
if (popperActive) {
unsigned long timeRemaining = (popperTimeout - (millis() - popperStartTime)) / 1000;
Serial.print("Popper time remaining: ");
Serial.print(timeRemaining);
Serial.println(" seconds");
}
}
}
if (dCommandActive) {
monitorLoadCell();
}
// Monitor DC Motors state - non-blocking
monitorDCMotors();
// Check for motor driver faults
stopIfFault();
}
// Reset cycle count function
const int maxCycleCount = 8;
int totalCyclesRun = 0;
void resetCycleCount() {
totalCyclesRun = 0; // Reset cycle count at start of D command
}
// Updated monitorLoadCell function with timeout and forward limit switch detection
void monitorLoadCell() {
int32_t loadCellValue = readLoadCell();
Serial.print("Load Cell Value: ");
Serial.println(loadCellValue);
// Check forward limit switch
if (digitalRead(limitSwitchForward) == LOW) {
Serial.println("Forward limit switch triggered. Stopping D command.");
stopDCommand();
turnPopperOff(); // Turn off popper when limit switch is triggered
return;
}
// Timeout logic
if (millis() - lastWeightIncreaseTime > loadCellTimeout) {
Serial.println("Timeout: No weight increase detected within the timeout duration. Stopping D command.");
stopDCommand();
return;
}
// Calculate the number of cycles needed
int additionalWeight = loadCellValue - currentBaseline;
int cyclesNeeded = additionalWeight / weightIncrement;
// Adjust cyclesNeeded to not exceed maxCycleCount
if (totalCyclesRun + cyclesNeeded > maxCycleCount) {
cyclesNeeded = maxCycleCount - totalCyclesRun;
}
if (cyclesNeeded > 0) {
currentBaseline += cyclesNeeded * weightIncrement; // Update baseline
totalCyclesRun += cyclesNeeded; // Increment total cycle count
Serial.print("Additional weight detected: ");
Serial.print(additionalWeight);
Serial.print("g. Running ");
Serial.print(cyclesNeeded);
Serial.println(" additional cycles.");
// Reset timeout timer on weight increase
lastWeightIncreaseTime = millis();
// Trigger motor cycles and stop if limit switch is triggered
for (int i = 0; i < cyclesNeeded; i++) {
if (digitalRead(limitSwitchForward) == LOW) {
Serial.println("Forward limit switch triggered during cycle. Stopping motor.");
stopDCommand();
turnPopperOff(); // Turn off popper when limit switch is triggered
return;
}
executeMotorCycle(); // The cycle logic is handled in this function
}
}
// Final threshold check
if (loadCellValue > weightThreshold) {
Serial.println("Final weight threshold reached. Executing final motor cycles.");
executeMotorCycle(); // First motor cycle
delay(5000); // Wait 5 seconds
executeMotorCycle(); // Second motor cycle
stopDCommand(); // Stop load cell monitoring
turnPopperOff(); // Turn off popper when weight threshold is reached
}
}
// Helper function to stop D command
void stopDCommand() {
dCommandActive = false; // Disable D command monitoring
lastWeightIncreaseTime = 0; // Reset timeout tracking
currentBaseline = 0; // Reset baseline for new command
Serial.println("D command stopped. Ready for a new command.");
}
// Updated executeMotorCycle function maintaining synchronized operation but non-blocking
void executeMotorCycle() {
Serial.println("Starting Motor Cycle...");
// Configure stepper motor with current settings
configureStepper(1888, 2400); // Adjust these values as needed
// Set step count for the stepper motor's movement
int stepCount = 851; // Define how many steps to move per cycle
myStepper.move(stepCount);
// Enable stepper motor
digitalWrite(enablePin, LOW); // Enable stepper motor
bool stepperRunning = true;
// Start DC motors
startDCMotor1();
delay(500);
startDCMotor2();
// Run the stepper motor until it completes its motion
// This ensures proper sequencing while keeping DC motors non-blocking
while (stepperRunning) {
// Stepper motor control (step-based)
if (myStepper.distanceToGo() == 0) {
digitalWrite(enablePin, HIGH); // Disable stepper motor
stepperRunning = false;
Serial.println("Stepper Motor OFF");
} else {
if (digitalRead(limitSwitchForward) == LOW) { // Forward limit switch check
Serial.println("Forward limit switch triggered during motor cycle. Stopping stepper motor.");
myStepper.stop();
digitalWrite(enablePin, HIGH); // Disable stepper
stepperRunning = false;
turnPopperOff(); // Turn off popper when limit switch is triggered
} else {
myStepper.run();
}
}
// Still monitor DC motors even within this function
monitorDCMotors();
}
// The DC motors will continue running and be monitored in the loop()
Serial.println("Stepper cycle completed, DC motors may still be running");
}
// Non-blocking DC motor control functions
void startDCMotor1() {
md.enableM1Driver();
delay(1);
md.setM1Speed(motorSpeed);
isDCMotor1Running = true;
dcMotor1StartTime = millis();
Serial.println("DC Motor 1 ON");
}
void startDCMotor2() {
md.enableM2Driver();
delay(1);
md.setM2Speed(motorSpeed);
isDCMotor2Running = true;
dcMotor2StartTime = millis();
Serial.println("DC Motor 2 ON");
}
void monitorDCMotors() {
unsigned long currentTime = millis();
// Check and update DC Motor 1
if (isDCMotor1Running) {
if (currentTime - dcMotor1StartTime >= dcMotor1Duration) {
// Turn off DC motor 1 after the duration
md.setM1Speed(0);
isDCMotor1Running = false;
Serial.println("DC Motor 1 OFF");
}
}
// Check and update DC Motor 2
if (isDCMotor2Running) {
if (currentTime - dcMotor2StartTime >= dcMotor2Duration) {
// Turn off DC motor 2 after the duration
md.setM2Speed(0);
isDCMotor2Running = false;
Serial.println("DC Motor 2 OFF");
}
}
}
void encoderISR_A() {
if (digitalRead(ENCODER_A) == digitalRead(ENCODER_B)) {
encoderCount++;
} else {
encoderCount--;
}
}
// Function to run when Encoder Channel B changes
void encoderISR_B() {
if (digitalRead(ENCODER_A) == digitalRead(ENCODER_B)) {
encoderCount--;
} else {
encoderCount++;
}
}
// Add this to your setup() function after other initializations
// This configures the encoder pins and interrupts
void setupEncoder() {
pinMode(ENCODER_A, INPUT_PULLUP);
pinMode(ENCODER_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_A), encoderISR_A, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCODER_B), encoderISR_B, CHANGE);
Serial.println("Encoder setup complete");
}
// Emergency stop function for auger motor
void emergencyStopAuger() {
// Try multiple approaches to ensure the motor stops
// 1. Normal speed setting to zero
md2.setM1Speed(0);
// 2. Disable the driver
md2.disableM1Driver();
// 3. If possible, directly control the enable pin (if connected)
// Uncomment if you have an enable pin connected for md2
// digitalWrite(md2EnablePin, HIGH); // HIGH typically disables the driver
Serial.println("EMERGENCY STOP: Auger motor halted");
// Turn off popper during emergency
turnPopperOff();
// Small delay to allow the motor to fully stop
delay(100);
}
// Improved auger function to prevent overshooting
bool auger(float turns) {
if (turns == 0) {
Serial.println("Auger: Zero turns requested, no action needed");
return true;
}
// Reset encoder at the start
encoderCount = 0;
delay(10); // Small delay to ensure the reset is processed
Serial.print("Auger: Rotating for ");
Serial.print(turns);
Serial.println(" turns");
// Calculate target encoder pulses
long targetPulses = abs(turns) * pulsesPerRevolution;
// Debug output
Serial.print("Target pulses: ");
Serial.println(targetPulses);
// Get direction based on sign of turns
int direction = (turns > 0) ? 1 : -1;
// Set up timing variables
unsigned long startTime = millis();
unsigned long lastReportTime = startTime;
unsigned long lastEncoderCheckTime = startTime;
long lastEncoderCount = 0;
// Start the motor with gradual acceleration
md2.enableM1Driver();
delay(20); // Small delay to ensure driver is enabled
// Gradual speed ramp-up to avoid sudden current spikes
for (int i = 50; i <= 200; i += 25) { // Lower max speed to 200 from 300
md2.setM1Speed(i * direction);
delay(20);
// Check for faults during ramp-up
if (md2.getM1Fault()) {
Serial.print("Fault detected during speed ramp-up at speed ");
Serial.println(i);
emergencyStopAuger();
return false;
}
}
// Main control loop with multiple safety checks
bool approachingTarget = false;
int currentSpeed = 200 * direction; // Start at our max speed
while (abs(encoderCount) < targetPulses) {
// Begin deceleration when we're 75% of the way there
if (!approachingTarget && abs(encoderCount) > (targetPulses * 0.75)) {
approachingTarget = true;
Serial.println("Approaching target: starting deceleration");
// Reduce speed for more precise stopping
currentSpeed = 100 * direction;
md2.setM1Speed(currentSpeed);
}
// Further reduce speed when we're 90% of the way there
if (approachingTarget && abs(encoderCount) > (targetPulses * 0.9)) {
currentSpeed = 75 * direction;
md2.setM1Speed(currentSpeed);
}
// Final slow approach at 95%
if (approachingTarget && abs(encoderCount) > (targetPulses * 0.95)) {
currentSpeed = 50 * direction;
md2.setM1Speed(currentSpeed);
}
// PRIMARY SAFETY CHECK: Maximum runtime exceeded
if (millis() - startTime > augerMotorTimeout) {
Serial.println("SAFETY: Timeout reached! Emergency stop.");
emergencyStopAuger();
return false;
}
// SAFETY CHECK: Motor fault detected
if (md2.getM1Fault()) {
Serial.println("SAFETY: M1 fault detected! Emergency stop.");
emergencyStopAuger();
return false;
}
// SAFETY CHECK: Encoder not responding (check every 500ms)
if (millis() - lastEncoderCheckTime > 500) {
if (encoderCount == lastEncoderCount) {
Serial.println("SAFETY: Encoder not updating! Emergency stop.");
emergencyStopAuger();
return false;
}
lastEncoderCount = encoderCount;
lastEncoderCheckTime = millis();
}
// SAFETY CHECK: If we're overshooting, stop immediately
if (abs(encoderCount) >= targetPulses + 100) {
Serial.println("SAFETY: Overshooting target! Emergency stop.");
emergencyStopAuger();
return false;
}
// Progress reporting (every second)
if (millis() - lastReportTime > 1000) {
lastReportTime = millis();
// Show motor current before position
Serial.print("M1 current: ");
Serial.print(md2.getM1CurrentMilliamps());
Serial.println(" mA");
Serial.print("Auger: Position ");
Serial.print(encoderCount);
Serial.print(" / ");
Serial.print(targetPulses);
Serial.print(" (");
Serial.print((float)abs(encoderCount) / targetPulses * 100);
Serial.println("%)");
}
}
// As soon as we reach or exceed the target, stop immediately
Serial.print("Target reached at position ");
Serial.println(encoderCount);
// Immediate stop - don't use gradual deceleration here to prevent overshooting
md2.setM1Speed(0);
delay(10);
md2.disableM1Driver();
// Final position report
Serial.print("Auger: Final position: ");
Serial.print(encoderCount);
Serial.print(" / ");
Serial.println(targetPulses);
return true;
}
// Function for "Home" command
void moveHome() {
digitalWrite(enablePin, LOW); // Enable the motor
myStepper.setSpeed(400);
// Move forward until the forward limit switch is triggered
while (digitalRead(limitSwitchForward) == HIGH) {
monitorReverseLimitSwitch();
myStepper.runSpeed();
}
// Stop the motor
Serial.println("Forward limit switch reached. Homing complete.");
myStepper.stop();
digitalWrite(enablePin, HIGH); // Disable the motor
}
// Function for "F" command
void moveReverseFixedSteps() {
digitalWrite(enablePin, LOW); // Enable the motor
configureStepper(200, 500);
// Move reverse for reverseStepCount steps
myStepper.move(-reverseStepCount);
while (myStepper.distanceToGo() != 0) {
monitorReverseLimitSwitch();
myStepper.run();
}
// Stop the motor
Serial.println("Reverse motion complete.");
myStepper.stop();
digitalWrite(enablePin, HIGH); // Disable the motor
}
// Function to monitor the reverse limit switch
void monitorReverseLimitSwitch() {
if (digitalRead(limitSwitchReverse) == LOW) {
Serial.println("Reverse limit switch triggered. Stopping motion.");
stopAllMotion();
turnPopperOff(); // Turn off popper when reverse limit switch is triggered
while (true); // Halt program until reset
}
}
// Stop all motion
void stopAllMotion() {
myStepper.stop();
md.setM1Speed(0); // Turn off DC motor 1
md.setM2Speed(0); // Turn off DC motor 2
digitalWrite(enablePin, HIGH); // Disable the stepper motor
isDCMotor1Running = false;
isDCMotor2Running = false;
turnPopperOff();
}```
