Hello,
I have been working on a project that is re-purposing a 3D printer into a measuring device. The goal right now is to make a number of measurements every 1mm along a single path. The Z axis would move down at a slow speed until the touch probe touches the surface, at this pioint the X, Y and Z axis co-ordinates are printed to serial print. The Z axis would then move up (zretract), move along X axis 1mm and repeat.
I also have 2 joysticks in the system that allow me to position the probe at the desired start point. Once in the correct position, push the button (which is incopertaed into one of the joysticks) and the sequence starts.
This all works well (so I know the wiring is correct), except the sequence does not stop after the desired number of measurement points. Currently the code is written to perform 3 measurement points. I think it is looping the sequence over and over, so making 3 measurements, followed by another 3 and so on.
I have tried using various methods to stop the sequence, using examples but with no impact.
Any advice please?
Hardware is:
Arduino Uno
CNC Shield V3 & A4988 Stepper Driver
The stepper motors are from an Artillery Genius Pro
The probe is a BL Touch Probe
Joysticks: XY Axis Joystick Module - Thumbstick - Arduino Experimentation Module - UK | eBay
Here is the code without an attempt to stop the loop.
#include <SpeedyStepper.h>
#include <ezButton.h>
#include <Servo.h>
// Stepper motor objects
SpeedyStepper stepperX;
SpeedyStepper stepperY;
SpeedyStepper stepperZ;
// Servo object for BLTouch
Servo blTouchServo; //servo object to control a servo
int Touch = 0; // state of blTouch
// BLTouch control pins
const int blTouchPin = 12; // White wire output to Digital pin 12
const int blTouchServoPin = 11; // Yellow wire for probe wire control to Digital Pin 11
// Button for starting the sequence
ezButton startButton(13); // Button connected to pin 13 from X Y Joystick Module
// Joystick pins
const int joyXPin = A0;
const int joyYPin = A1;
const int joyZPin = A2;
// Motor driver pins
const int stepXPin = 2, dirXPin = 5;
const int stepYPin = 3, dirYPin = 6;
const int stepZPin = 4, dirZPin = 7;
const int STEPPERS_ENABLE_PIN = 8;
// Configurable Parameters
const float xStepDistance = 1.0; // Distance to move in X-axis per step (mm).
const float zRetractDistance = 1.0; // Distance to retract in Z-axis (mm)
const float xTotalDistance = 3.0; // Total X-axis distance to measure (mm)
const int maxSpeedX = 50; // Max speed for X-axis stepper (mm/second)
const int maxSpeedY = 10; // Max speed for Y-axis stepper (mm/second)
const int maxSpeedZ = 10; // Max speed for Z-axis stepper (mm/second)
const int maxSpeedZProbe = 5; // Max speed for Z-axis stepper when probing (mm/second)
const int maxAccelX = 500; // Max acceleration for X-axis stepper (mm/second/second)
const int maxAccelY = 500; // Max acceleration for X-axis stepper (mm/second/second)
const int maxAccelZ = 500; // Max acceleration for X-axis stepper (mm/second/second)
// Joystick sensitivity
const int joystickThreshold = 20; // Sensitivity threshold
const int joystickMaxSpeed = 100; // Max speed for joystick control (mm/second)
// Absolute position variables
float absX = 0.0, absY = 0.0, absZ = 0.0;
// Correction factors if needed
const float FactorX = (5/1); // Correction factor for X axis.
// const float FactorY = (5/1); // Correction factor for Y axis.
const float FactorZ = (5/1); // Correction factor for Z axis.
// Calculating steps per mm
#define PI 3.1415926535897932384626433832795
const int MotorStepsPerRev = 200; // Motor Steps per revolution for all steppers
const int MicroStep = 16; // Microstepping for all drivers.
const int ToothPitch = 2; //Tooth to Tooth pitch for X and Y in millimeters
const int PulleyTeeth = 20; //No of Teeth for pulleys on X and Y.
const float PulleyPitch = (ToothPitch * PulleyTeeth)/(PI); // Pulley pitch for X and Y in millimetres.
const float StepsPermm = (MotorStepsPerRev * MicroStep)/(PulleyPitch * PulleyTeeth)*FactorX; // Step per mm for X and Y
const int LeadScrewLead = 8; // Z Axis Lead screw lead (mm per revolution)
const float StepsPermmZ = (MotorStepsPerRev * MicroStep)/(LeadScrewLead)*FactorZ; // Steps per mm for Z axis
void setup() {
pinMode(STEPPERS_ENABLE_PIN, OUTPUT);
// Initialize BLTouch servo
blTouchServo.attach(blTouchServoPin); // Attaches the servo on the digital pin to the servo object
pinMode(blTouchPin, INPUT_PULLUP); // May need resistor in circuit. Then remove PULLUP
Serial.begin(9600);
//De-bugging blTouch. Touch the probe, what happens?
// while (true) {
// int state = digitalRead(blTouchPin);
//Serial.println(state);
//delay(1000); // Slow down output for readability
// }
// connect and configure the stepper motor to there IO pins
stepperX.connectToPins(stepXPin, dirXPin);
stepperY.connectToPins(stepYPin, dirYPin);
stepperZ.connectToPins(stepZPin, dirZPin);
// enable the stepper motors
digitalWrite(STEPPERS_ENABLE_PIN, LOW);
// Initialize button
startButton.setDebounceTime(50); // Debounce for button
// Show blTouch works
deployProbe(); // Deploy probe at startup to show it works
delay(500);
//retractProbe(); // Retract probe at startup to show it works
Serial.println("Setup complete. Use joysticks to position X, Y and Z.");
}
void loop() {//The measurements loop, i.e. do not finish when total X reached
// Set max speeds for stepper motors. Can these be in setup?
stepperX.setSpeedInMillimetersPerSecond(maxSpeedX);
stepperY.setSpeedInMillimetersPerSecond(maxSpeedY);
stepperZ.setSpeedInMillimetersPerSecond(maxSpeedZ);
// Set acceleration for stepper motors
stepperX.setAccelerationInMillimetersPerSecondPerSecond(maxAccelX);
stepperY.setAccelerationInMillimetersPerSecondPerSecond(maxAccelY);
stepperZ.setAccelerationInMillimetersPerSecondPerSecond(maxAccelZ);
// Set steps per millimetre
stepperX.setStepsPerMillimeter(StepsPermm); // Steps per millimetere for X axis
stepperY.setStepsPerMillimeter(StepsPermm); // Steps per millimetere for Y axis
stepperZ.setStepsPerMillimeter(StepsPermmZ); // Steps per millimetere for Z axis
// Update button state
startButton.loop();
// Joystick control for X, Y AND z axes
int joyX = analogRead(joyXPin) - 512;
int joyY = analogRead(joyYPin) - 512;
int joyZ = analogRead(joyZPin) - 512;
if (abs(joyX) > joystickThreshold) {
int speedX = map(joyX, 512, -512, -joystickMaxSpeed, joystickMaxSpeed);
stepperX.setSpeedInMillimetersPerSecond(speedX);
stepperX.moveRelativeInMillimeters(speedX > 0 ? 10 : -10);
absX += (speedX > 0 ? 10 : -10); // Update absolute position
}
if (abs(joyY) > joystickThreshold) {
int speedY = map(joyY, 512, -512, -joystickMaxSpeed, joystickMaxSpeed);
stepperY.setSpeedInMillimetersPerSecond(speedY);
stepperY.moveRelativeInMillimeters(speedY > 0 ? 10 : -10);
absY += (speedY > 0 ? 10 : -10); // Update absolute position
}
if (abs(joyZ) > joystickThreshold) {
int speedZ = map(joyZ, 512, -512, -joystickMaxSpeed, joystickMaxSpeed);
stepperZ.setSpeedInMillimetersPerSecond(speedZ);
stepperZ.moveRelativeInMillimeters(speedZ > 0 ? 10 : -10);
absZ += (speedZ > 0 ? 10 : -10); // Update absolute position
}
// Start sequence on button press
if (startButton.isPressed()) {
Serial.println("Sequence starting...");
executeSequence();
}
}
void executeSequence() {
// Mark current position as (0, 0, 0)
absX = 0.0;
absY = 0.0;
absZ = 0.0;
Serial.print("Position: X=");
Serial.print(absX);
Serial.print(", Y=");
Serial.print(absY);
Serial.print(", Z=");
Serial.println(absZ);
int PositionsInX = xTotalDistance / xStepDistance; // Calculate total number of positions in X-axis to be measured
for (int i = 0; i <= PositionsInX; i++) {
// Move Z down until BLTouch is triggered
Serial.println("Probing Z...");
deployProbe();
while (digitalRead(blTouchPin) == LOW) {
stepperZ.setSpeedInMillimetersPerSecond(maxSpeedZProbe); // Move Z down
stepperZ.moveRelativeInSteps(1); //positive to get correct direction on stepper motor
absZ -= 0.01; // Update absolute Z position
}
retractProbe();
Serial.print("Position: X=");
Serial.print(absX);
Serial.print(", Y=");
Serial.print(absY);
Serial.print(", Z=");
Serial.println(absZ);
// Move Z up by retract distance
stepperZ.setSpeedInMillimetersPerSecond(maxSpeedZ); // Move Z up
stepperZ.moveRelativeInMillimeters(-zRetractDistance); //negative to get correct direction on stepper motor
absZ += zRetractDistance;
// Move X by position distance for the next measurement
stepperX.setSpeedInMillimetersPerSecond(maxSpeedX); //is it needed again here? If should I include acceleration again?
stepperX.moveRelativeInMillimeters(xStepDistance);
absX += xStepDistance;
delay(500); // Small delay for stability
}
Serial.println("Sequence complete.");
}
// Deploy the BLTouch probe
void deployProbe() {
blTouchServo.write(10); // Adjust angle for deployment
delay(500);
}
// Retract the BLTouch probe
void retractProbe() {
blTouchServo.write(90); // Adjust angle for retraction
delay(500);
}
//void blink() {
// Touch = 1;
Here is a code with an attempt to stop the loop
#include <SpeedyStepper.h>
#include <ezButton.h>
#include <Servo.h>
bool sequenceInProgress = false; //Flag to indicate if sequence in progress
// Stepper motor objects
SpeedyStepper stepperX;
SpeedyStepper stepperY;
SpeedyStepper stepperZ;
// Servo object for BLTouch
Servo blTouchServo; //servo object to control a servo
int Touch = 0; // state of blTouch
// BLTouch control pins
const int blTouchPin = 12; // White wire output to Digital pin 12
const int blTouchServoPin = 11; // Yellow wire for probe wire control to Digital Pin 11
// Button for starting the sequence
ezButton startButton(13); // Button connected to pin 13 from X Y Joystick Module
// Joystick pins
const int joyXPin = A0;
const int joyYPin = A1;
const int joyZPin = A2;
// Motor driver pins
const int stepXPin = 2, dirXPin = 5;
const int stepYPin = 3, dirYPin = 6;
const int stepZPin = 4, dirZPin = 7;
const int STEPPERS_ENABLE_PIN = 8;
// Configurable Parameters
const float xStepDistance = 1.0; // Distance to move in X-axis per step (mm).
const float zRetractDistance = 10.0; // Distance to retract in Z-axis (mm)
const float xTotalDistance = 3.0; // Total X-axis distance to cover (mm)
const int maxSpeedX = 10; // Max speed for X-axis stepper (mm/second)
const int maxSpeedY = 10; // Max speed for Y-axis stepper (mm/second)
const int maxSpeedZ = 10; // Max speed for Z-axis stepper (mm/second)
const int maxSpeedZProbe = 5; // Max speed for Z-axis stepper when probing (mm/second)
const int maxAccelX = 250; // Max acceleration for X-axis stepper (mm/second/second)
const int maxAccelY = 250; // Max acceleration for Y-axis stepper (mm/second/second)
const int maxAccelZ = 250; // Max acceleration for Z-axis stepper (mm/second/second)
// Joystick sensitivity
const int joystickThreshold = 200; // Sensitivity threshold
const int joystickMaxSpeed = 100; // Max speed for joystick control (mm/second)
// Absolute position variables
float absX = 0.0, absY = 0.0, absZ = 0.0;
// Correction factiors if needed
const float FactorX = (5/1); // Correction factor for X axis. This is correct
//const float FactorY = (5/1); // Correction factor for Y axis. This is correct
const float FactorZ = (5/1); // Correction factor for Z axis. Might be correct
// Calculating steps per mm
#define PI 3.1415926535897932384626433832795
const int MotorStepsPerRev = 200; // Motor Steps per revolution for all steppers
const int MicroStep = 16; // Microstepping for all drivers.
const int ToothPitch = 2; //Tooth to Tooth pitch for X and Y in millimeters
const int PulleyTeeth = 20; //No of Teeth for pulleys on X and Y.
const float PulleyPitch = (ToothPitch * PulleyTeeth)/(PI); // Pulley pitch for X and Y in millimetres.
const float StepsPermm = (MotorStepsPerRev * MicroStep)/(PulleyPitch * PulleyTeeth)*FactorX; // Step per mm for X and Y
const int LeadScrewLead = 8; // Z Axis Lead screw lead (mm per revolution)
const float StepsPermmZ = (MotorStepsPerRev * MicroStep)/(LeadScrewLead)*FactorZ; // Steps per mm for Z axis
void setup() {
pinMode(STEPPERS_ENABLE_PIN, OUTPUT);
// Initialize BLTouch servo
blTouchServo.attach(blTouchServoPin); // Attaches the servo on the digital pin to the servo object
pinMode(blTouchPin, INPUT_PULLUP); // May need resistor in circuit. Then remove PULLUP
Serial.begin(9600);
//De-bugging blTouch. Touch the probe, what happens?
// while (true) {
// int state = digitalRead(blTouchPin);
//Serial.println(state);
//delay(1000); // Slow down output for readability
// }
// connect and configure the stepper motor to there IO pins
stepperX.connectToPins(stepXPin, dirXPin);
stepperY.connectToPins(stepYPin, dirYPin);
stepperZ.connectToPins(stepZPin, dirZPin);
// enable the stepper motors
digitalWrite(STEPPERS_ENABLE_PIN, LOW);
// Initialize button
startButton.setDebounceTime(50); // Debounce for button
// Show blTouch works
deployProbe(); // Deploy probe at startup to show it works
delay(500);
//retractProbe(); // Retract probe at startup to show it works
Serial.println("Setup complete. Use joysticks to position X, Y and Z.");
}
void loop() {//The measurements loop, i.e. do not finish when total X reached
// Set max speeds for stepper motors. Can these be in setup?
stepperX.setSpeedInMillimetersPerSecond(maxSpeedX);
stepperY.setSpeedInMillimetersPerSecond(maxSpeedY);
stepperZ.setSpeedInMillimetersPerSecond(maxSpeedZ);
// Set acceleration for stepper motors
stepperX.setAccelerationInMillimetersPerSecondPerSecond(maxAccelX);
stepperY.setAccelerationInMillimetersPerSecondPerSecond(maxAccelY);
stepperZ.setAccelerationInMillimetersPerSecondPerSecond(maxAccelZ);
// Set steps per millimetre
stepperX.setStepsPerMillimeter(StepsPermm); // Steps per millimetere for X axis
stepperY.setStepsPerMillimeter(StepsPermm); // Steps per millimetere for Y axis
stepperZ.setStepsPerMillimeter(StepsPermmZ); // Steps per millimetere for Z axis
// Update button state
startButton.loop();
// Joystick control for X, Y AND z axes
int joyX = analogRead(joyXPin) - 512;
int joyY = analogRead(joyYPin) - 512;
int joyZ = analogRead(joyZPin) - 512;
if (abs(joyX) > joystickThreshold) {
int speedX = map(joyX, 512, -512, -joystickMaxSpeed, joystickMaxSpeed);
stepperX.setSpeedInMillimetersPerSecond(speedX);
stepperX.moveRelativeInMillimeters(speedX > 0 ? 5 : -5);
absX += (speedX > 0 ? 5 : -5); // Update absolute position
}
if (abs(joyY) > joystickThreshold) {
int speedY = map(joyY, 512, -512, -joystickMaxSpeed, joystickMaxSpeed);
stepperY.setSpeedInMillimetersPerSecond(speedY);
stepperY.moveRelativeInMillimeters(speedY > 0 ? 5 : -5);
absY += (speedY > 0 ? 5 : -5); // Update absolute position
}
if (abs(joyZ) > joystickThreshold) {
int speedZ = map(joyZ, 512, -512, -joystickMaxSpeed, joystickMaxSpeed);
stepperZ.setSpeedInMillimetersPerSecond(speedZ);
stepperZ.moveRelativeInMillimeters(speedZ > 0 ? 5 : -5);
absZ += (speedZ > 0 ? 5 : -5); // Update absolute position
}
// Start sequence on button press
if (startButton.isPressed() && !sequenceInProgress) {
Serial.println("Sequence starting...");
sequenceInProgress = true; // Mark the sequence as in progress
executeSequence();
sequenceInProgress = false; // Reset the flag after completiion
}
}
void executeSequence() {
// Mark current position as (0, 0, 0)
absX = 0.0;
absY = 0.0;
absZ = 0.0;
int PositionsInX = xTotalDistance / xStepDistance; // Calculate total number of positions in X-axis to be measured
for (int i = 0; i <= PositionsInX; i++) {
// Move Z down until BLTouch is triggered
Serial.println("Probing Z...");
deployProbe();
while (digitalRead(blTouchPin) == LOW) {
stepperZ.setSpeedInMillimetersPerSecond(maxSpeedZProbe); // Move Z down
stepperZ.moveRelativeInSteps(1); //positive tp get correct motor direction
absZ -= 0.01; // Update absolute Z position
}
retractProbe();
Serial.print("Position: X=");
Serial.print(absX);
Serial.print(", Y=");
Serial.print(absY);
Serial.print(", Z=");
Serial.println(absZ);
// Move Z up by retract distance
stepperZ.setSpeedInMillimetersPerSecond(maxSpeedZ); // Move Z up
stepperZ.moveRelativeInMillimeters(-zRetractDistance); //negative to get correct motor direction
absZ += zRetractDistance;
// Move X by position distance for the next measurement
stepperX.setSpeedInMillimetersPerSecond(maxSpeedX); //is it needed again here? If should I include acceleration again?
stepperX.moveRelativeInMillimeters(xStepDistance);
absX += xStepDistance;
delay(500); // Small delay for stability
}
Serial.println("Sequence complete.");
}
// Deploy the BLTouch probe
void deployProbe() {
blTouchServo.write(10); // Adjust angle for deployment
delay(500);
}
// Retract the BLTouch probe
void retractProbe() {
blTouchServo.write(90); // Adjust angle for retraction
delay(500);
}
//void blink() {
// Touch = 1;
Suggestions and tips welcome please!
Many thanks
Matt