ATTENZIONE!!! RICHIEDE ARDUINO UNO R4 MINIMA O ALTRA VERSIONE COMPATIBILE CON LIBRERIA KEYBOARD |
ATTENTION!!! REQUIRES ARDUINO UNO R4 MINIMA OR OTHER VERSION COMPATIBLE WITH KEYBOARD LIBRARY |
VEDI Miglioramento del sistema di accoppiamento meccanico |
SEE Improvement of the mechanical coupling system |
VEDI Microscope Z-Stage knob controlled by serial dialogue |
SEE Microscope Z-Stage knob controlled by serial dialogue |
Due importanti sviluppiLa precedente realizzazione (Microscope Z-Stage knob controlled by serial dialogue) è stata radicalmente migliorata in diversi aspetti, che la portano a essere un'alternativa a una slitta micrometrica motorizzata: rispetto a prodotti come quelli MJKZZ, che però non sempre sono integrabili con applicazzioni di cattura immagini basate su personal computer.
|
Two important developmentsThe previous creation (Microscope Z-Stage knob controlled by serial dialogue)has been radically improved in various aspects, which lead it to be an alternative to a motorized micrometric slide: compared to products such as the MJKZZ ones, which however cannot always be integrated with personal computer-based image capture applications.
|
/* Stepper-based microscope Z-stage Circuit and comments: See http://www.cesarebrizio.it/Arduino/Z-Stage.html Circuit is as illustrated here: https://www.tdegypt.com/wp-content/uploads/2017/08/stepper-motor-wiring.png the only exception being that the sketch uses digital outputs 4 - 5 - 6 - 7 while the Fritzing diagram uses digital outputs 8 - 9 - 10 - 11 */ /*-----( Import needed libraries )-----*/ #include <AccelStepper.h> #include <Keyboard.h> // Needed only if keyboard stroke is to be sent (REQUIRES Arduino UNO R4 Minima) /*-----( Declare Constants and Pin Numbers )-----*/ /* NEVER PUT ; AFTER A #define statement!!!! */ // motor pins #define motorPin1 4 // Blue - 28BYJ-48 pin 1 #define motorPin2 5 // Pink - 28BYJ-48 pin 2 #define motorPin3 6 // Yellow - 28BYJ-48 pin 3 #define motorPin4 7 // Orange - 28BYJ-48 pin 4 \ // Red - 28BYJ-48 pin 5 (VCC) \ // Blue - 28BYJ-48 pin GND #define STEPS_PER_TURN 2048 // number of steps in 360° #define STEPS_PER_FOUR 22 // number of steps in 4° #define STEPS_PER_FIVE 28 // number of steps in 5° #define STEPS_PER_TEN 57 // number of steps in 10° #define STEPS_PER_TWENTY 114 // number of steps in 20° #define STEPS_PER_FORTY 228 // number of steps in 40° int motorSpeed = 500; // High speeds (800 and above) may cause erratic behavior in 28BYJ-48 int motorAccel = 400; // As above: better avoiding extreme accelerations int myPos = 0; // will be used to define a starting point for 360° rotations int LeftTurnUp = 0; // Couple of flags to determine rotation direction int RightTurnDown = 0; // Couple of flags to determine rotation direction int Continuous = 2; // used below to discriminate single rotation commands // Continuous will be set to 1 or 0 only when a valid command character will be received //int incomingByte = 0; // for incoming serial data int STEPS_TO_DO = 0; // to allocate the number of steps needed to perform the required rotation int RotationsRequired = 0; // How many rotations of the desired type are required? int RotationsDone = 0; // How many rotations of the desired type were completed? int RotationsRemaining = 0; // How many rotations remain to do? int delay_between_rotations = 2000; //milliseconds of delay between consecutive rotations bool active = false; // is the stepper active? /*-----( Objects for stepper control )-----*/ // Set up the stepper as 4 wire bipolar on pin 4,5,6,7 // NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48 AccelStepper stepper(4, motorPin1, motorPin3, motorPin2, motorPin4); void setup() { Serial.begin(9600); stepper.setMinPulseWidth(20); // Advisable setting to avoid that pulses from Arduino are too quick to be decoded stepper.setMaxSpeed(motorSpeed); stepper.setSpeed(motorSpeed); stepper.setAcceleration(motorAccel); // the following two lines reset "step zero" to the current position stepper.setCurrentPosition(stepper.currentPosition()); stepper.runToPosition(); // The following is required to initialize the communication with the keyboard Keyboard.begin(); // I should ask the user what he wants to do askUser(); } void loop() { stepper.run(); // ================================================== // Let's check whether: // A) the stepper is active; // B) the stepper is still running. // ================================================== if (active && (stepper.distanceToGo() == 0)) { //Serial.println("stepper.distanceToGo() = 0"); // the rotation was completed // Send F1 to the keyboard Keyboard.press(KEY_F1); delay(100); Keyboard.releaseAll(); // Delay before the next rotation delay(delay_between_rotations); Serial.print("Sent F1 Keystroke and waited "); Serial.print(delay_between_rotations); Serial.println(" milliseconds."); // Increase the count of rotations done RotationsDone = RotationsDone + 1; // Check how many rotations remain to do RotationsRemaining = RotationsRequired - RotationsDone; if (RotationsRemaining > 0) { Serial.print("Starting rotation number "); Serial.print(RotationsDone + 1); Serial.print(" of "); Serial.println(RotationsRequired); // reset current position myPos = stepper.currentPosition(); // start a new rotation of the same kind as the last one if (LeftTurnUp == 1) //left turn { stepper.moveTo(myPos + STEPS_TO_DO); // number of steps in 5, 10, 20 or 360° } if (RightTurnDown == 1) //right turn { stepper.moveTo(myPos - STEPS_TO_DO); // number of steps in 5, 10, 20 or 360° } // I'm activating the stepper and I should // begin checking whether it has completed // its required rotations active = true; } else { // I'm inactivating the stepper and I should // stop checking whether it has completed // its required rotations active = false; // I should ask the user what he wants to do askUser(); } } } void askUser() { // Delay to ensure that the serial port has the time to initialize correctly delay(delay_between_rotations); // ================================================================ // The user is asked for A NUMBER OF REQUIRED ROTATIONS // AND THE KIND OF ROTATIONS REQUIRED // ================================================================ Serial.println("==============================="); Serial.println("How many rotations are desired?"); while (Serial.available() == 0) { } RotationsRequired = Serial.parseInt(); while(Serial.available()) Serial.read(); // Empty the seerial buffer from any remaining character RotationsDone = 0; // For now, no rotations has been completed RotationsRemaining = RotationsRequired; // For now, no rotations has been completed Serial.print("You required "); Serial.print(RotationsRequired); Serial.println(" rotations."); Serial.println(" "); Serial.println("Which kind of rotation is required ?"); Serial.println("Available commands:"); Serial.println("====> 360° Rotation"); Serial.println("o = 360° clockwise rotation"); Serial.println("O = 360° counter-clockwise rotation"); Serial.println("====> Rotation by small increments"); Serial.println("k = rotate 4° clockwise"); Serial.println("K = rotate 4° counter-clockwise"); Serial.println("f = rotate 5° clockwise"); Serial.println("F = rotate 5° counter-clockwise"); Serial.println("t = rotate 10° clockwise"); Serial.println("T = rotate 10° counter-clockwise"); Serial.println("w = rotate 20° clockwise"); Serial.println("W = rotate 20° counter-clockwise"); Serial.println("q = rotate 40° clockwise"); Serial.println("Q = rotate 40° counter-clockwise"); while (Serial.available() == 0) { } String incomingByte = Serial.readString(); while(Serial.available()) Serial.read(); // Empty the seerial buffer from any remaining character Serial.print("Received "); Serial.println(incomingByte); if (incomingByte == "o") { Serial.println("received «o» - activating single clockwise rotation"); // The following couple of flags determines rotation direction LeftTurnUp = 0; RightTurnDown = 1; STEPS_TO_DO = STEPS_PER_TURN; } if (incomingByte == "O") { Serial.println("received «O» - activating single counter-clockwise rotation"); // The following couple of flags determines rotation direction RightTurnDown = 0; LeftTurnUp = 1; STEPS_TO_DO = STEPS_PER_TURN; } if (incomingByte == "k") { Serial.println("received «k» - activating 4° clockwise rotation"); // The following couple of flags determines rotation direction LeftTurnUp = 0; RightTurnDown = 1; STEPS_TO_DO = STEPS_PER_FOUR; } if (incomingByte == "K") { Serial.println("received «K» - activating 4° counter-clockwise rotation"); // The following couple of flags determines rotation direction RightTurnDown = 0; LeftTurnUp = 1; STEPS_TO_DO = STEPS_PER_FOUR; } if (incomingByte == "f") { Serial.println("received «f» - activating 5° clockwise rotation"); // The following couple of flags determines rotation direction LeftTurnUp = 0; RightTurnDown = 1; STEPS_TO_DO = STEPS_PER_FIVE; } if (incomingByte == "F") { Serial.println("received «F» - activating 5° counter-clockwise rotation"); // The following couple of flags determines rotation direction RightTurnDown = 0; LeftTurnUp = 1; STEPS_TO_DO = STEPS_PER_FIVE; } if (incomingByte == "t") { Serial.println("received «t» - activating 10° clockwise rotation"); // The following couple of flags determines rotation direction LeftTurnUp = 0; RightTurnDown = 1; STEPS_TO_DO = STEPS_PER_TEN; } if (incomingByte == "T") { Serial.println("received «T» - activating 10° counter-clockwise rotation"); // The following couple of flags determines rotation direction RightTurnDown = 0; LeftTurnUp = 1; STEPS_TO_DO = STEPS_PER_TEN; } if (incomingByte == "w") { Serial.println("received «w» - activating 20° clockwise rotation"); // The following couple of flags determines rotation direction LeftTurnUp = 0; RightTurnDown = 1; STEPS_TO_DO = STEPS_PER_TWENTY; } if (incomingByte == "W") { Serial.println("received «W» - activating 20° counter-clockwise rotation"); // The following couple of flags determines rotation direction RightTurnDown = 0; LeftTurnUp = 1; STEPS_TO_DO = STEPS_PER_TWENTY; } if (incomingByte == "q") { Serial.println("received «q» - activating 40° clockwise rotation"); // The following couple of flags determines rotation direction LeftTurnUp = 0; RightTurnDown = 1; STEPS_TO_DO = STEPS_PER_FORTY; } if (incomingByte == "Q") { Serial.println("received «Q» - activating 40° counter-clockwise rotation"); // The following couple of flags determines rotation direction RightTurnDown = 0; LeftTurnUp = 1; STEPS_TO_DO = STEPS_PER_FORTY; } // The two lines that follow allow to send commands in any sequence: // before execution, a quick stop is performed stepper.stop(); // Stop as fast as possible: sets new target stepper.runToPosition(); // Now stopped after quickstop stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here" stepper.setSpeed(motorSpeed); // Previous commands have reset the speed Serial.print("Starting rotation number 1 of "); Serial.println(RotationsRequired); // I store my current position as starting point of the rotation myPos = stepper.currentPosition(); if (LeftTurnUp == 1) //left turn { stepper.moveTo(myPos + STEPS_TO_DO); // number of steps in 5, 10, 20 or 360° } if (RightTurnDown == 1) //right turn { stepper.moveTo(myPos - STEPS_TO_DO); // number of steps in 5, 10, 20 or 360° } // I'm activating the stepper and I should // begin checking whether it has completed // its required rotations active = true; }
❦