14. Interface and Application Programming
Overview of week 14 assignment
- Group assignment
- compare as many tool options as possible
- Individual assignment
- write an application that interfaces a user with an input &/or output device that you made
1. Group assignment
For more information, see the Week 14: Group assignment page.
2. Individual assignment
A. Stepper Motor Control with Dial in Processing
This week, I experimented with controlling a stepper motor from a Processing application using G-code-ish commands. I started with a simple setup using one stepper motor and tried rotating it with a dial in Processing.
a. Wiring and components
I reused the setup from week 10, which includes a Nema17 stepper motor, A4988 driver, and an AC adaptor. Please see week 10 for more details.
A4988 | RP2040 |
---|---|
STEP | 27 |
DIR | 26 |
MS1 | 28 |
MS2 | 29 |
MS3 | 6 |
b. Arduino and Processing code
In this setup, Processing reads the mouse movement and clicks, then sends a message (like G-code) to the Arduino via serial, which turns the stepper motor.
Although I used Processing a long time ago, I'm not familiar with Java, so I relied heavily on ChatGPT, especially for the Processing part.
Prompt:
- Create a simple circular UI in Processing to send G-code commands using serial communication between Processing and RP2040
- Program RP2040 using the Arduino IDE to control one stepper motor via A4988 driver
References:
G-code (-ish) formatting in Processing:
1 2 3 |
|
"ROTATE"
: A custom command to move the motor to a specific angle. For example,"ROTATE X90"
means "rotate to 90 degrees"."X"
: The target angle.int(angle)
: Converts the angle to an integer.port.write(... + "\n")
: Sends the command to Arduino, ending with a newline.
Processing code (Expand here!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
G-code decoding in Arduino:
String gcode = Serial.readStringUntil('\n');
if (gcode.startsWith("ROTATE")) {
int xIndex = gcode.indexOf('X');
float angle = gcode.substring(xIndex + 1).toFloat();
}
Serial.readStringUntil('\n')
: Reads the G-code command sent from Processing.gcode.startsWith("ROTATE")
: Checks if the command is "ROTATE".gcode.indexOf('X')
: Finds the position ofX
in the command.gcode.substring(xIndex + 1).toFloat()
: Extracts and converts the angle value to a float.moveTo(targetSteps)
: Moves the motor to the desired position based on the angle.
Arduino code (Expand here!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|
c. Outcome
B. XY Motion Control with Processing and G-code
Next, I added another motor to simulate the XY motion.
a. Wiring and components
Basically, I added one more set of A4988 and Nema 17 motor, while keeping the other components from the previous setup. For the new A4988 driver, I wired it according to the table below, and the MS1, MS2, and MS3 pins are shared with both of A4988 drivers.
A4988 1st (X) | RP2040 |
---|---|
STEP | 27 |
DIR | 26 |
A4988 2nd (Y) | |
STEP | 29 |
DIR | 28 |
Microstep mode (shared with two A4988s) | |
MS1 | 3 |
MS2 | 4 |
MS3 | 2 |
I also added an OLED display to show the current G-code command.
OLED (SH1106) | RP2040 |
---|---|
GND | GND |
VCC | 3.3V |
SCL | 7 |
SDA | 6 |
And here is the wiring...
First, I did a quick test to make sure both motors were working properly, and surprisingly it worked.
b. Arduino and Processing code
Prompt:
- Develop a simple rectangular UI in Processing to send G-code commands via serial communication to an RP2040. The interface tracks mouse position and clicks, converts the XY coordinates into G-code, and transmits the commands to the RP2040 through serial communication.
- Program the RP2040 using the Arduino IDE to control two stepper motors via A4988 drivers, with one motor assigned to X-axis movement and the other to Y-axis. Additionally, display the current G-code command on an OLED display.
G-code sender in Processing:
Processing code (Expand here!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
|
G-code decoding in Arduino:
setup()
- Initializes serial, motors, and OLED display.
loop()
- Waits for G-code (e.g.,
G1 X100 Y50
). - Displays it and moves motors.
- Waits for G-code (e.g.,
displayGcode(gcode)
- Shows G-code on OLED.
processGcode(gcode)
if (gcode.startsWith("G1")) { int xIndex = gcode.indexOf('X'); int yIndex = gcode.indexOf('Y'); // Extract and convert X and Y values if (xIndex != -1) { String xStr = gcode.substring(xIndex + 1, nextSpace); float xVal = xStr.toFloat(); targetX = xVal / MAX_POS * STEPS_PER_REV; } moveToXY(targetX, targetY); // Move motors to new position }
- Parses
G1
command and extracts X/Y. - Calls
moveToXY()
.
- Parses
-
moveToXY(x, y)
: Moves motors to target X/Y position.-
Direction Setup:
- Sets the direction of motors based on the target position relative to the current position.
dirX
anddirY
control the movement direction for the X and Y axes.
digitalWrite(DIR_PIN_X, dirX ? HIGH : LOW); digitalWrite(DIR_PIN_Y, dirY ? HIGH : LOW);
-
Loop to Move Motors:
- This loop moves both motors for the required steps to reach the target positions.
maxSteps
is the greater ofstepsX
andstepsY
, ensuring both motors move together.- Each iteration sends a step pulse to both motors and includes a delay to control the speed.
for (long i = 0; i < maxSteps; i++) { if (i * stepsX / maxSteps < stepsX) digitalWrite(STEP_PIN_X, HIGH); if (i * stepsY / maxSteps < stepsY) digitalWrite(STEP_PIN_Y, HIGH); delayMicroseconds(500); if (i * stepsX / maxSteps < stepsX) digitalWrite(STEP_PIN_X, LOW); if (i * stepsY / maxSteps < stepsY) digitalWrite(STEP_PIN_Y, LOW); delayMicroseconds(500); }
-
-
Position Update:
-
Updates
posX
andposY
to the target position after movement.posX = targetX; posY = targetY;
-
Arduino code (Expand here!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
|
3. Files
No files this week, code in the text.
Afterthoughts
- G28