I am very new to coding and trying to get started on a code to drive two stepper motors (1 for X axis and 1 for Z axis) to drive a sensor (readout in volts) to find the highest reading and return to that position.
I am using an Arduino Uno R3, with two 1.8 degree stepper motors powered through two TB6600 Stepper Motor Drivers. If anyone can point me in the right direction to get started it would be appreciated.
I am using Powermax II stepper motors with a potentiometer to simulate the voltage input until I can finalize a sensor and LED display to show the voltage input level. I want to take a single voltage reading after driving to a position. The only code I have thus far is making the stepper motors move and taking continuous readings.
/* Include the library */
#include <AccelStepper.h>
#include <MultiStepper.h>
int value = 0;
int sensorPin = A0; // select the input pin for the potentiometer
int ledPin = 13; // select the pin for the LED
int sensorValue = 0; // variable to store the value coming from the sensor
float voltage;
AccelStepper stepperX(AccelStepper::DRIVER, 8, 9);
AccelStepper stepperZ(AccelStepper::DRIVER, 6, 7);
MultiStepper steppers;
/*
Based on LiquidCrystal Library - Hello World
The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VCC pin to 5V
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
*/
// include the library code:
#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
Serial.begin(9600);
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
stepperX.setMaxSpeed(1000);
stepperZ.setMaxSpeed(1000);
// Original set to 4000
stepperX.setSpeed(0);
stepperZ.setSpeed(0);
stepperX.moveTo(50);
stepperZ.moveTo(50);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Voltage = ");
}
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
// Previously - lcd.print(millis() / 1000);
value = analogRead(A0);
voltage = value * 5.0 / 1024;
Serial.print("Voltage= ");
Serial.println(voltage);
lcd.println(voltage);
// delay(500);
if (stepperX.distanceToGo() == 0)
stepperX.moveTo(-stepperX.currentPosition());
stepperX.run();
if (stepperZ.distanceToGo() == 0)
stepperZ.moveTo(-stepperZ.currentPosition());
stepperZ.run();
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
// turn the ledPin on
digitalWrite(ledPin, HIGH);
// stop the program for <sensorValue> milliseconds:
delay(sensorValue);
// turn the ledPin off:
digitalWrite(ledPin, LOW);
// stop the program for <sensorValue> milliseconds:
delay(sensorValue);
}
can you move the X stepper across its range to find the position that result in the max.
then return the x position where the max was found and do the same along the Z axis and then return to the Z position that had the max
don't understand your thinking in above. shouldn't you be advancing the stepper along one axis at a time one step at a time, making a measurement and checking for max?
Take 10 readings in the X Axis, return to the highest point in the X Axis and take 10 readings in the Z Axis from that point. May be later be necessary to reverse the process for validation (e.g., 10 readings in the Z Axis, return to the highest point in the Z Axis and take 10 readings in the X Axis from that point).
#include <Wire.h>
#include <LiquidCrystal.h>
#include <AccelStepper.h>
const int stepsPerRevolution = 200; // Defines the number of steps per rotation based on each motor (1.8° motor is 200/360°) as a constant
// Define stepper motor connections and interface type
#define motorInterfaceType 1 // 1 means using a driver with STEP/DIR pins
AccelStepper motorX(motorInterfaceType, 19, 23); // Step pin on GPIO 19, Dir pin on GPIO 23
AccelStepper motorZ(motorInterfaceType, 12, 13); // Step pin on GPIO 13, Dir pin on GPIO 12
const int sensorPin = 32; // Analog pin for voltage sensor on ESP32
float maxVoltage = 0;
int maxX = 0, maxZ = 0;
// Define the path arrays
const int MAX_MOVES = 100; // Adjust size based on your needs (Baseline was 100)
int pathX[MAX_MOVES];
int pathZ[MAX_MOVES];
int moveCount = 0;
/* LCD 16x2 Connections as follows:
* LCD 1 VSS to ground
* LCD 2 VCC to 5V
* LCD 3 VEE (VO) Wiper pin 3 (Center)
* LCD 4 RS to digital ESP32 pin 16
* LCD 5 R/W to ground
* LCD 6 Enable (E) to digital ESP32 pin 17
* LCD 7 D0 unused
* LCD 8 D1 unused
* LCD 9 D2 unused
* LCD 10 D3 unused
* LCD 11 D4 to digital ESP32 pin 14
* LCD 12 D5 to digital ESP32 pin 25
* LCD 13 D6 to digital ESP32 pin 26
* LCD 14 D7 to digital ESP32 pin 27
* LCD 15 LED+ to 5V
* LCD 16 LED- to ground
*/
/* initialize the library by associating any needed LCD interface pin
with the ESP32 pin number it is connected to */
const int rs = 16, en = 17, d4 = 14, d5 = 25, d6 = 26, d7 = 27;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
Serial.begin(115200);
motorX.setMaxSpeed(500); // Set Max Speed (Baseline used was 500)
motorZ.setMaxSpeed(500);
motorX.setAcceleration(500); // Set Max Acceleration to increase speed (Baseline used was 500)
motorZ.setAcceleration(500);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Voltage = ");
}
void loop() {
// Sweep motors to find the maximum voltage
for (int x = 0; x <= 360; x += 10) { // Move motorX in 10 degree increments
motorX.moveTo(x * stepsPerRevolution / 360); // moves to each successive position based on the current X value, Smaller value travels farther
for (int z = 0; z <= 360; z += 2) { // Move motorZ in 5 degree increments
motorZ.moveTo(z * stepsPerRevolution / 360); // moves to each successive position based on the current Z value, Smaller value travels farther
// Run both motors until they reach the target positions
while (motorX.distanceToGo() != 0 || motorZ.distanceToGo() != 0) {
motorX.run();
motorZ.run();
}
float voltage = analogRead(sensorPin) * 5.0 / 4096; /* Read voltage and adjust display value 5.0 is the reference voltage (5.0V from the ESP32), 4096 adjusts the display to a max 5.0V */
Serial.print("X: ");
Serial.print(x);
Serial.print(" Z: ");
Serial.print(z);
Serial.print(" Voltage: ");
Serial.println(voltage);
// Display on LCD
lcd.clear(); // Clear the previous content
lcd.setCursor(0, 0); // Set cursor to first line
lcd.print("X: ");
lcd.print(x);
lcd.print(" Z: ");
lcd.print(z);
lcd.setCursor(0, 1); // Set cursor to second line
lcd.print("Voltage: ");
lcd.print(voltage);
// Store the position in path if space allows
if (moveCount < MAX_MOVES) {
pathX[moveCount] = x;
pathZ[moveCount] = z;
moveCount++;
}
// Check if this is the max voltage
if (voltage > maxVoltage) {
maxVoltage = voltage;
maxX = x;
maxZ = z;
}
// delay(50); // Small delay for readability (200 was the default)
}
// Return Z to home position (0) after completing the scan for this X position
motorZ.moveTo(0); // Move Z-axis back to 0 position
while (motorZ.distanceToGo() != 0) {
motorZ.run();
}
}
// Output the results
Serial.print("Max Voltage: ");
Serial.println(maxVoltage);
Serial.print("At Position: X: ");
Serial.print(maxX);
Serial.print(" Z: ");
Serial.println(maxZ);
// Display max voltage on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Max Voltage:");
lcd.setCursor(0, 1);
lcd.print(maxVoltage);
lcd.print(" at X:");
lcd.print(maxX);
lcd.print(" Z:");
lcd.print(maxZ);
// Return to the maximum position by reversing the path
for (int i = moveCount - 1; i >= 0; i--) {
motorX.moveTo(pathX[i]); // Move motorX to stored position
motorZ.moveTo(pathZ[i]); // Move motorZ to stored position
motorX.runToPosition(); // Run to position
motorZ.runToPosition(); // Run to position
}
// Final display on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Returned to:");
lcd.setCursor(0, 1);
lcd.print("X: ");
lcd.print(maxX);
lcd.print(" Z: ");
lcd.print(maxZ);
while (true)
; // Stop the loop after returning to the max position
}