|
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 135 136 137 138 |
// Arduino Motor Control V6 // Dual motor control system: // - Motor_Focus: Percentage control (0-100%) mapped to (0-205°) // - Motor_Aperture: N-value control (1.4-16.0) with theta lookup table #include <AccelStepper.h> #include <Arduino.h> #include <avr/pgmspace.h> const float STEPS_PER_REV = 4096.0; // Motor wiring: IN1, IN3, IN2, IN4 AccelStepper stepperFocus(AccelStepper::HALF4WIRE, 8, 10, 9, 11); // Motor_Focus AccelStepper stepperAperture(AccelStepper::HALF4WIRE, 4, 6, 5, 7); // Motor_Aperture // Lookup table: θ values for N = 1.4, 1.5, ..., 16.0 (step 0.1) const float thetaLUT[147] PROGMEM = { 0.00,4.00,8.00,12.00,15.02,19.01,22.02,26.01,29.02,32.03, 35.03,38.03,41.03,44.02,47.00,48.05,50.04,52.03,54.01, 55.05,57.02,58.06,60.02,61.05,63.00,64.03,65.05,66.07,67.08, 69.01,70.02,71.03,72.03,73.03,74.03,75.02,76.01,77.00,77.10, 78.08,79.06,80.04,81.00,82.05,84.03,85.07,87.02,88.04,89.06, 90.07,91.07,92.07,93.07,94.07,95.07,96.07,97.06,98.04,99.02, 100.00,100.10,101.07,102.03,102.13,103.09,104.05,106.00,106.10, 106.20,106.29,107.00,107.10,107.20,107.29,108.05,108.15,108.25, 108.34,109.05,109.15,109.25,109.34,110.00,110.10,110.20,111.05, 111.15,111.25,111.34,112.00,112.10,112.20,112.29,113.01,113.10, 113.20,113.30,114.07,114.17,114.26,115.02,115.11,115.21,115.31, 116.05,116.15,116.24,116.34,117.06,117.16,117.26,117.35,118.06, 118.15,118.25,118.35,119.03,119.13,119.23,119.33,119.42,120.08, 120.18,120.28,120.38,121.02,121.12,121.21,121.31,121.41,122.03, 122.13,122.22,122.32,122.42,123.01,123.11,123.21,123.31,123.40, 123.50,124.07,124.17,124.26,124.36,124.46,125.00 }; // Convert N (1.4 → 16.0 step 0.1) to θ using lookup table float thetaFromN(float N) { if (N < 1.4f) return 0.0f; // Return 0° for N < 1.4 if (N > 16.0f) return 125.0f; // Return 125° for N > 16.0 int index = (int)((N - 1.4f) * 10.0f + 0.5f); // nearest index if (index < 0) index = 0; if (index > 146) index = 146; // Updated to 146 (last valid index for 147-element array) return pgm_read_float(&thetaLUT[index]); } // Convert percentage (0-100%) to degrees (0-205°) for Motor_Focus float percentageToDegrees(float percentage) { // Linear mapping: 0% -> 0°, 100% -> 205° return (percentage / 100.0f) * 205.0f; } void setup() { Serial.begin(9600); Serial.println("========================================"); Serial.println(" Arduino Motor Control V6"); Serial.println("========================================"); Serial.println("Motor Control Commands:"); Serial.println("F <percentage> - Motor_Focus position (0-100%) mapped to (0-205°)"); Serial.println("A <N_value> - Motor_Aperture using N value (1.4-16.0)"); Serial.println("Examples:"); Serial.println(" F 50 (Motor_Focus to 50% = 102.5°)"); Serial.println(" F 100 (Motor_Focus to 100% = 205°)"); Serial.println(" A 2.5 (Motor_Aperture to angle corresponding to N=2.5)"); Serial.println("========================================"); stepperFocus.setMaxSpeed(800); stepperFocus.setAcceleration(400); stepperAperture.setMaxSpeed(800); stepperAperture.setAcceleration(400); } void loop() { stepperFocus.run(); stepperAperture.run(); if (Serial.available()) { String cmd = Serial.readStringUntil('\n'); cmd.trim(); if (cmd.length() > 0) parseCommand(cmd); } } long degreesToSteps(float deg) { return (long)((deg / 360.0) * STEPS_PER_REV); } void parseCommand(String cmd) { char buf[32]; cmd.toCharArray(buf, sizeof(buf)); char *token = strtok(buf, " "); if (!token) return; char motor = toupper(token[0]); // 'F' for Focus or 'A' for Aperture token = strtok(NULL, " "); if (!token) return; float value = atof(token); if (motor == 'F') { // Motor_Focus: Percentage control (0-100%) mapped to (0-205°) if (value < 0.0f) { Serial.println("Warning: Motor_Focus percentage clamped to 0%"); value = 0.0f; } if (value > 100.0f) { Serial.println("Warning: Motor_Focus percentage clamped to 100%"); value = 100.0f; } float degrees = percentageToDegrees(value); long targetSteps = degreesToSteps(degrees); stepperFocus.moveTo(targetSteps); Serial.print("Motor_Focus: "); Serial.print(value, 1); Serial.print("% -> "); Serial.print(degrees, 1); Serial.println("°"); } else if (motor == 'A') { // Motor_Aperture: N value control (1.4-16.0) if (value < 1.4f || value > 16.0f) { Serial.print("Warning: N value should be between 1.4 and 16.0. Got: "); Serial.println(value, 2); } float theta = thetaFromN(value); long targetSteps = degreesToSteps(theta); stepperAperture.moveTo(targetSteps); Serial.print("Motor_Aperture: N="); Serial.print(value, 2); Serial.print(" -> θ="); Serial.print(theta, 2); Serial.println("°"); } else { Serial.println("Invalid motor! Use F for Focus or A for Aperture."); } } |
