Yes, you can, here is how…
- In your original post, click the “edit” pencil.
- Select your code text.
- “cut” the code text (CTRL-X)
- Click the </> button
- … at this point, do not click anywhere or move the cursor…
- Paste (CTRL-V) the code text
- Click “Save Edit” to save the edit.
The result with your code will look like this… (updated ```cpp) (further updated ```processing)
// === BASIC SETTINGS ===
import processing.serial.; // Import serial library for Arduino communication
import controlP5.; // Import ControlP5 library for GUI buttons and sliders
Serial myPort;
ControlP5 cp5;
String serialInput = "";
HashMap<String, String> data = new HashMap<String, String>(); // Stores all telemetry data
HashMap<String, Integer> servoDefaults = new HashMap<String, Integer>(); // Stores default servo positions
HashMap<String, Integer> servoValues = new HashMap<String, Integer>(); // Stores real-time servo positions
String modes = {"IDLE", "GROUND_TEST", "FLIGHT"}; // Left panel modes
String rightModes = {"ALIGN", "FIN_TEST"}; // Right panel modes
int currentMode = 0;
boolean wasMousePressed = false;
void setup() {
size(1280, 720); // Set canvas size
surface.setTitle("Rocket Ground Station - Meteor V3");
cp5 = new ControlP5(this);
printArray(Serial.list()); // Print available serial ports
myPort = new Serial(this, Serial.list()[0], 115200); // Connect to the first available serial port
myPort.bufferUntil('\n'); // Read serial input line-by-line
setupGUI(); // Create GUI elements
initServos(); // Initialize default servo values
}
void draw() {
background(30);
textAlign(LEFT, BASELINE); // Reset text alignment
// Draw different sections of the interface
drawTelemetry();
drawServoPanel();
drawServoDefaults();
drawStatePanel();
drawRocketState();
wasMousePressed = mousePressed; // Used for button clicks
}
// === INITIALIZATION ===
void setupGUI() {
// Add left side mode buttons
for (int i = 0; i < modes.length; i++) {
cp5.addButton(modes[i])
.setPosition(20, 40 + i * 60)
.setSize(100, 50)
.onClick(e → changeMode(e.getController().getName()));
}
// Add right side mode buttons
for (int i = 0; i < rightModes.length; i++) {
cp5.addButton(rightModes[i])
.setPosition(1150, 40 + i * 60)
.setSize(100, 50)
.onClick(e → changeMode(e.getController().getName()));
}
// Reset Arduino button
cp5.addButton("RESET ARDUINO")
.setPosition(550, 660)
.setSize(180, 40)
.onClick(e → myPort.write("RESET\n"));
}
void initServos() {
// Initialize servo positions to 90°
for (int i = 1; i <= 4; i++) {
String key = "S" + i;
servoValues.put(key, 90);
servoDefaults.put(key, 90);
}
}
// === SERIAL COMMUNICATION ===
void serialEvent(Serial p) {
serialInput = p.readStringUntil('\n');
if (serialInput != null) {
serialInput = serialInput.trim();
if (serialInput.length() == 0) return;
if (!serialInput.contains(":")) return;
parseData(serialInput); // Parse and store incoming data
}
}
void parseData(String line) {
// Split serial line into key:value pairs
String parts = split(line, " “);
for (String part : parts) {
if (part.contains(":")) {
String kv = split(part, ":");
if (kv.length == 2) {
data.put(kv[0], kv[1]); // Store in data map
if (kv[0].startsWith("S")) {
servoValues.put(kv[0], int(kv[1]));
}
}
}
}
}
// === MODE HANDLING ===
void changeMode(String mode) {
int code = -1;
// Map mode name to corresponding code
if (mode.equals("IDLE")) code = 0;
if (mode.equals("ALIGN")) code = 1;
if (mode.equals("GROUND_TEST")) code = 2;
if (mode.equals("FLIGHT")) code = 3;
if (mode.equals("FIN_TEST")) code = 4;
// Send mode to Arduino if valid
if (code != -1) {
currentMode = code;
myPort.write(code + "\n");
println("Modalità cambiata a: " + mode);
}
}
// === TELEMETRY PANEL ===
void drawTelemetry() {
int x = 150, y = 20, w = 260, h = 140, spacing = 20;
// Draw four telemetry boxes
drawBox("Accelerometers", x, y, w, h, "AX", "AY", "AZ");
drawBox("Gyroscopes", x + w + spacing, y, w, h, "GX", "GY", "GZ");
drawBox("PID Output", x, y + h + spacing, w, h, "OUTX", "OUTY", "OUTZ");
drawBox("Angles", x + w + spacing, y + h + spacing, w, h, "ANGX", "ANGY", "ANGZ");
}
void drawBox(String title, int x, int y, int w, int h, String… keys) {
fill(50);
stroke(200);
rect(x, y, w, h, 10);
fill(255);
textSize(14);
text(title, x + 10, y + 25);
textSize(12);
for (int i = 0; i < keys.length; i++) {
String val = data.containsKey(keys[i]) ? data.get(keys[i]) : "—";
text(keys[i] + ": " + val, x + 10, y + 45 + i * 20);
}
}
// === MAIN STATUS PANEL ===
void drawStatePanel() {
int x = 150, y = 340, w = 540, h = 100;
fill(50);
stroke(200);
rect(x, y, w, h, 10);
fill(255);
textSize(14);
text("Rocket Status", x + 10, y + 25);
// Show current flight mode
String modeNames = {"MODE_IDLE", "MODE_ALIGN_SERVO", "MODE_GROUND_TEST", "MODE_FLIGHT", "MODE_FIN_TEST"};
String modeVal = data.getOrDefault("MODE", "—");
String modeText = modeVal.matches("\d") ? modeNames[int(modeVal)] : modeVal;
// Get other state values
String launched = data.getOrDefault("LAUNCHED", "—");
String offx = data.getOrDefault("OFFX", "—");
String offy = data.getOrDefault("OFFY", "—");
fill(255);
text("MODE: " + modeText, x + 10, y + 50);
text("OFFX: " + offx, x + 160, y + 50);
text("OFFY: " + offy, x + 310, y + 50);
// Color LAUNCHED status
if (launched.equals("1")) fill(0, 255, 0);
else fill(255, 0, 0);
text("LAUNCHED: " + launched, x + 10, y + 75);
}
// === SYSTEM STATE PANEL ===
void drawRocketState() {
int x = 710, y = 340, w = 400, h = 100;
fill(50);
stroke(200);
rect(x, y, w, h, 10);
fill(255);
textSize(14);
text("Internal State", x + 10, y + 25);
// This line calls drawStatusText(), which sometimes causes the error
drawStatusText("CALIBRATING", x + 10, y + 50);
drawStatusText("OFFSETTING", x + 210, y + 50);
drawStatusText("MPU", x + 10, y + 75);
}
// === This function is correctly declared! ===
// It displays a blinking or colored status based on value
void drawStatusText(String key, int x, int y) {
String val = data.getOrDefault(key, "—");
if (val.equals("1")) {
if (frameCount % 30 < 15) fill(255, 0, 0);
else fill(255, 255, 0);
} else if (val.equals("0")) {
fill(0, 255, 0);
} else {
fill(200);
}
text(key + ": " + val, x, y);
}
// === SERVO STATUS PANEL ===
void drawServoPanel() {
int cx = 900, cy = 180;
fill(80);
stroke(200);
rect(cx - 120, cy - 120, 240, 240, 10);
fill(255);
textAlign(CENTER);
text("Fin Status", cx, cy - 130);
textAlign(LEFT);
String servos = {"S1", "S2", "S3", "S4"};
int pos = {{cx, cy - 90}, {cx + 90, cy}, {cx, cy + 90}, {cx - 90, cy}};
for (int i = 0; i < servos.length; i++) {
String s = servos[i];
int x = pos[i][0];
int y = pos[i][1];
fill(servoValues.get(s) == null ? 150 : 255);
ellipse(x, y, 40, 40);
fill(0);
textAlign(CENTER, CENTER);
text(s + "\n" + servoValues.get(s), x, y);
}
textAlign(LEFT, BASELINE);
}
// === SERVO DEFAULT PANEL ===
void drawServoDefaults() {
int startX = 820, y = 500;
fill(50);
stroke(200);
rect(startX - 20, y - 40, 280, 180, 10);
fill(255);
textSize(14);
text("Default Fin Positions", startX, y - 10);
String servos = {"S1", "S2", "S3", "S4"};
for (int i = 0; i < servos.length; i++) {
String s = servos[i];
int x = startX;
int sy = y + i * 30;
int val = servoDefaults.get(s);
text(s + ": " + val + "°", x, sy);
drawButton(x + 60, sy - 10, 30, 20, "-1", () -> changeDefault(s, -1));
drawButton(x + 100, sy - 10, 30, 20, "0", () -> resetDefault(s));
drawButton(x + 140, sy - 10, 30, 20, "+1", () -> changeDefault(s, +1));
}
}
// === GENERIC BUTTON HANDLER ===
void drawButton(int x, int y, int w, int h, String label, Runnable action) {
fill(100);
rect(x, y, w, h, 5);
fill(255);
textAlign(CENTER, CENTER);
text(label, x + w / 2, y + h / 2);
boolean inside = mouseX > x && mouseX < x + w && mouseY > y && mouseY < y + h;
if (mousePressed && !wasMousePressed && inside) {
action.run();
}
}
// === SERVO VALUE CHANGERS ===
void changeDefault(String servo, int delta) {
int current = servoDefaults.get(servo);
int newVal = constrain(current + delta, 70, 110);
servoDefaults.put(servo, newVal);
myPort.write(servo + ":" + newVal + "\n");
println("Default command: " + servo + ":" + newVal);
}
void resetDefault(String servo) {
servoDefaults.put(servo, 90);
myPort.write(servo + ":90\n");
println("Reset default: " + servo + ":90");
}
I do not know why this code does not have highlighted keywords…