I’ve been playing with Chat GPT for a few weeks now mostly just kicking the tires but I decided to throw it at some simple Arduino code requests at it:
write an arduino program that controls a stepper motor using an 8825 driver. The direction pin is 4 and the step pin is 5. A global variable of “StepCount” should be initially set to zero. A second global variable of “MaxSteps” should be set to “2000”
A function named “Movement” should allow for serial control with 3 parameters: “direction” (0 for “forward” and 1 for “backward”), “speed” in steps per second, and “steps” the number of steps. After each step if direction is forward and StepCount is less than than MaxSteps increment the “StepCount” by +1. If the Direction is “backward” and “StepCount” >0 increment the “StepCount” by -1.
Another function called “Reset” should allow for serial control and set the “StepCount” to 0.
I made 3 to 4 clarifications then asked chat GPT for a summary of what I tasked it with:
You are tasked with writing an Arduino program that controls a stepper motor using an 8825 driver. The program should have two global variables:
StepCount, initially set to zero.
MaxSteps, set to 2000.
The program should have two functions:Movement: allows for serial control with three parameters:
direction (0 for “forward” and 1 for “backward”)
speed in steps per second
steps the number of steps to move
After each step, if the direction is “forward” and StepCount is less than MaxSteps, increment StepCount by 1. If the direction is “backward” and StepCount is greater than 0, increment StepCount by -1. When the movement command is done, the program should respond with “Movement Complete: X” (where X is the final value of StepCount) via the serial port.
Reset: allows for serial control and sets StepCount to 0. When the reset command is done, the program should respond with “Coordinates Reset” via the serial port.When the program starts, it should send the message “Focuser Ready” via the serial port and list the available functions with sample usage.
If the program receives an unknown command, it should respond with “Unknown Command” via the serial port.
to which it responded with the very decent:
// Define the pin assignments for the stepper motor driver
#define dirPin 4
#define stepPin 5
// Define the global variables for step count and maximum steps
int StepCount = 0;
int MaxSteps = 2000;
// The Movement function allows for serial control of the stepper motor
void Movement(int direction, int speed, int steps) {
// Set the direction pin
digitalWrite(dirPin, direction);
// Step the motor for the specified number of steps at the specified speed
for (int i = 0; i < steps; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(500000 / speed);
digitalWrite(stepPin, LOW);
delayMicroseconds(500000 / speed);
// Update the step count based on the direction of movement
if (direction == 0 && StepCount < MaxSteps) {
StepCount++;
}
else if (direction == 1 && StepCount > 0) {
StepCount--;
}
}
// Print the movement completion message with the current step count
Serial.print("Movement Complete: ");
Serial.println(StepCount);
}
// The Reset function allows for serial control to reset the step count to zero
void Reset() {
StepCount = 0;
Serial.println("Coordinates Reset.");
}
// The UnknownCommand function is called when an unknown command is received
void UnknownCommand() {
Serial.println("Unknown Command");
}
// Set up the initial state of the stepper motor and send the "Focuser Ready" message
void setup() {
pinMode(dirPin, OUTPUT);
pinMode(stepPin, OUTPUT);
Serial.begin(9600);
// List available functions with sample usage
Serial.println("Available functions:");
Serial.println(" - Movement: M<direction>,<speed>,<steps> (e.g. M0,500,1000 to move forward at 500 steps per second for 1000 steps)");
Serial.println(" - Reset: R (e.g. R to reset the step count to zero)");
}
// Main loop of the program
void loop() {
// Check for serial input from the user
if (Serial.available() > 0) {
// Read the incoming command
String command = Serial.readStringUntil('\n');
// Parse the command string
int firstComma = command.indexOf(',');
int secondComma = command.indexOf(',', firstComma + 1);
int direction = command.substring(0, firstComma).toInt();
int speed = command.substring(firstComma + 1, secondComma).toInt();
int steps = command.substring(secondComma + 1).toInt();
// Call the appropriate function based on the command
if (command.startsWith("M")) {
Movement(direction, speed, steps);
}
else if (command.startsWith("R")) {
Reset();
}
else {
UnknownCommand();
}
}
}
The code has a few bugs in how it tracks the steps but pretty good for the rather vague directions I gave it. But it can go a number of steps at a specific speed in a specific direction with no code changes from me.
Now lets write a python client for the app:
write a python client that talks to the Arduino application via serial port. Create functions in python that call each of the Arduino functions with the appropriate parameters.
import serial
import time
# Connect to the Arduino via the serial port
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
# Wait for the Arduino to reset
time.sleep(2)
# Define a function to start the program on the Arduino
def start_program():
ser.write(b'start\n')
response = ser.readline().decode().rstrip()
print(response)
# Define a function to move the motor on the Arduino
def move_motor(direction, speed, steps):
command = f'move,{direction},{speed},{steps}\n'
ser.write(command.encode())
response = ser.readline().decode().rstrip()
print(response)
# Define a function to reset the motor position on the Arduino
def reset_motor():
ser.write(b'reset\n')
response = ser.readline().decode().rstrip()
print(response)
# Call the start_program function to start the program on the Arduino
start_program()
# Call the move_motor function to move the motor forward
move_motor(0, 100, 500)
# Call the move_motor function to move the motor backward
move_motor(1, 50, 200)
# Call the reset_motor function to reset the motor position
reset_motor()
# Close the serial connection
ser.close()
Not too shabby… other than the unneeded start function and having to define the COM port it just works.